source: trunk/packages/xen-3.1/xen-3.1/xen/arch/ia64/xen/xensetup.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 16.5 KB
Line 
1/******************************************************************************
2 * xensetup.c
3 * Copyright (c) 2004-2005  Hewlett-Packard Co
4 *         Dan Magenheimer <dan.magenheimer@hp.com>
5 */
6
7#include <xen/config.h>
8#include <xen/lib.h>
9#include <xen/errno.h>
10//#include <xen/spinlock.h>
11#include <xen/multiboot.h>
12#include <xen/sched.h>
13#include <xen/mm.h>
14#include <public/version.h>
15#include <xen/gdbstub.h>
16#include <xen/version.h>
17#include <xen/console.h>
18#include <xen/domain.h>
19#include <xen/serial.h>
20#include <xen/trace.h>
21#include <xen/keyhandler.h>
22#include <asm/meminit.h>
23#include <asm/page.h>
24#include <asm/setup.h>
25#include <xen/string.h>
26#include <asm/vmx.h>
27#include <linux/efi.h>
28#include <asm/iosapic.h>
29#include <xen/softirq.h>
30#include <xen/rcupdate.h>
31#include <acm/acm_hooks.h>
32
33unsigned long xenheap_phys_end, total_pages;
34
35char saved_command_line[COMMAND_LINE_SIZE];
36char dom0_command_line[COMMAND_LINE_SIZE];
37
38cpumask_t cpu_present_map;
39
40extern unsigned long domain0_ready;
41
42int find_max_pfn (unsigned long, unsigned long, void *);
43
44/* FIXME: which header these declarations should be there ? */
45extern long is_platform_hp_ski(void);
46extern void early_setup_arch(char **);
47extern void late_setup_arch(char **);
48extern void hpsim_serial_init(void);
49extern void alloc_dom0(void);
50extern void setup_per_cpu_areas(void);
51extern void mem_init(void);
52extern void init_IRQ(void);
53extern void trap_init(void);
54extern void xen_patch_kernel(void);
55
56/* opt_nosmp: If true, secondary processors are ignored. */
57static int opt_nosmp;
58boolean_param("nosmp", opt_nosmp);
59
60/* maxcpus: maximum number of CPUs to activate. */
61static unsigned int max_cpus = NR_CPUS;
62integer_param("maxcpus", max_cpus); 
63
64/* xencons: if true enable xenconsole input (and irq).
65   Note: you have to disable 8250 serials in domains (to avoid use of the
66   same resource).  */
67static int opt_xencons = 1;
68integer_param("xencons", opt_xencons);
69
70/* Toggle to allow non-legacy xencons UARTs to run in polling mode */
71static int opt_xencons_poll;
72boolean_param("xencons_poll", opt_xencons_poll);
73
74/*
75 * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
76 *      xen image
77 *      bootmap bits
78 *      xen heap
79 * Note: To allow xenheap size configurable, the prerequisite is
80 * to configure elilo allowing relocation defaultly. Then since
81 * elilo chooses 256M as alignment when relocating, alignment issue
82 * on IPF can be addressed.
83 */
84unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
85unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
86extern long running_on_sim;
87unsigned long xen_pstart;
88void *xen_heap_start __read_mostly;
89
90static int
91xen_count_pages(u64 start, u64 end, void *arg)
92{
93    unsigned long *count = arg;
94
95    /* FIXME: do we need consider difference between DMA-usable memory and
96     * normal memory? Seems that HV has no requirement to operate DMA which
97     * is owned by Dom0? */
98    *count += (end - start) >> PAGE_SHIFT;
99    return 0;
100}
101
102static void __init do_initcalls(void)
103{
104    initcall_t *call;
105    for ( call = &__initcall_start; call < &__initcall_end; call++ )
106        (*call)();
107}
108
109/*
110 * IPF loader only supports one commaind line currently, for
111 * both xen and guest kernel. This function provides pre-parse
112 * to mixed command line, to split it into two parts.
113 *
114 * User should split the parameters by "--", with strings after
115 * spliter for guest kernel. Missing "--" means whole line belongs
116 * to guest. Example:
117 *      "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
118 * root=/dev/sda3 ro"
119 */
120static char null[4] = { 0 };
121
122void early_cmdline_parse(char **cmdline_p)
123{
124    char *guest_cmd;
125    static const char * const split = "--";
126
127    if (*cmdline_p == NULL) {
128        *cmdline_p = &null[0];
129        saved_command_line[0] = '\0';
130        dom0_command_line[0] = '\0';
131        return;
132    }
133
134    guest_cmd = strstr(*cmdline_p, split);
135    /* If no spliter, whole line is for guest */
136    if (guest_cmd == NULL) {
137        guest_cmd = *cmdline_p;
138        *cmdline_p = &null[0];
139    } else {
140        *guest_cmd = '\0';      /* Split boot parameters for xen and guest */
141        guest_cmd += strlen(split);
142        while (*guest_cmd == ' ') guest_cmd++;
143    }
144
145    strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
146    strlcpy(dom0_command_line, guest_cmd, COMMAND_LINE_SIZE);
147    return;
148}
149
150struct ns16550_defaults ns16550_com1 = {
151    .data_bits = 8,
152    .parity    = 'n',
153    .stop_bits = 1
154};
155
156unsigned int ns16550_com1_gsi;
157unsigned int ns16550_com1_polarity;
158unsigned int ns16550_com1_trigger;
159
160struct ns16550_defaults ns16550_com2 = {
161    .data_bits = 8,
162    .parity    = 'n',
163    .stop_bits = 1
164};
165
166/* efi_print: print efi table at boot */
167static int opt_efi_print;
168boolean_param("efi_print", opt_efi_print);
169
170/* print EFI memory map: */
171static void
172efi_print(void)
173{
174    void *efi_map_start, *efi_map_end;
175    u64 efi_desc_size;
176
177    efi_memory_desc_t *md;
178    void *p;
179    int i;
180
181    if (!opt_efi_print)
182        return;
183
184    efi_map_start = __va(ia64_boot_param->efi_memmap);
185    efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
186    efi_desc_size = ia64_boot_param->efi_memdesc_size;
187
188    for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
189        md = p;
190        printk("mem%02u: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) "
191               "(%luMB)\n", i, md->type, md->attribute, md->phys_addr,
192               md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
193               md->num_pages >> (20 - EFI_PAGE_SHIFT));
194    }
195}
196
197/*
198 * These functions are utility functions for getting and
199 * testing memory descriptors for allocating the xenheap area.
200 */
201static efi_memory_desc_t *
202efi_get_md (unsigned long phys_addr)
203{
204    void *efi_map_start, *efi_map_end, *p;
205    efi_memory_desc_t *md;
206    u64 efi_desc_size;
207
208    efi_map_start = __va(ia64_boot_param->efi_memmap);
209    efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
210    efi_desc_size = ia64_boot_param->efi_memdesc_size;
211
212    for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
213        md = p;
214        if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
215            return md;
216    }
217    return 0;
218}
219
220static int
221is_xenheap_usable_memory(efi_memory_desc_t *md)
222{
223    if (!(md->attribute & EFI_MEMORY_WB))
224        return 0;
225
226    switch (md->type) {
227        case EFI_LOADER_CODE:
228        case EFI_LOADER_DATA:
229        case EFI_BOOT_SERVICES_CODE:
230        case EFI_BOOT_SERVICES_DATA:
231        case EFI_CONVENTIONAL_MEMORY:
232            return 1;
233    }
234    return 0;
235}
236
237static inline int
238md_overlaps(efi_memory_desc_t *md, unsigned long phys_addr)
239{
240    return (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT));
241}
242
243#define MD_SIZE(md) (md->num_pages << EFI_PAGE_SHIFT)
244
245void start_kernel(void)
246{
247    char *cmdline;
248    unsigned long nr_pages;
249    unsigned long dom0_memory_start, dom0_memory_size;
250    unsigned long dom0_initrd_start, dom0_initrd_size;
251    unsigned long md_end, relo_start, relo_end, relo_size = 0;
252    struct domain *idle_domain;
253    struct vcpu *dom0_vcpu0;
254    efi_memory_desc_t *kern_md, *last_md, *md;
255#ifdef CONFIG_SMP
256    int i;
257#endif
258
259    /* Be sure the struct shared_info size is <= XSI_SIZE.  */
260    BUILD_BUG_ON(sizeof(struct shared_info) > XSI_SIZE);
261
262    running_on_sim = is_platform_hp_ski();
263    /* Kernel may be relocated by EFI loader */
264    xen_pstart = ia64_tpa(KERNEL_START);
265
266    early_setup_arch(&cmdline);
267
268    /* We initialise the serial devices very early so we can get debugging. */
269    if (running_on_sim)
270        hpsim_serial_init();
271    else {
272        ns16550_init(0, &ns16550_com1);
273        ns16550_init(1, &ns16550_com2);
274    }
275    serial_init_preirq();
276
277    init_console();
278    set_printk_prefix("(XEN) ");
279
280    if (running_on_sim || ia64_boot_param->domain_start == 0 ||
281                          ia64_boot_param->domain_size == 0) {
282        /* This is possible only with the old elilo, which does not support
283           a vmm.  Fix now, and continue without initrd.  */
284        printk ("Your elilo is not Xen-aware.  Bootparams fixed\n");
285        ia64_boot_param->domain_start = ia64_boot_param->initrd_start;
286        ia64_boot_param->domain_size = ia64_boot_param->initrd_size;
287        ia64_boot_param->initrd_start = 0;
288        ia64_boot_param->initrd_size = 0;
289    }
290
291    printk("Xen command line: %s\n", saved_command_line);
292    /* xenheap should be in same TR-covered range with xen image */
293    xenheap_phys_end = xen_pstart + xenheap_size;
294    printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
295           xen_pstart, xenheap_phys_end);
296
297    xen_patch_kernel();
298
299    kern_md = md = efi_get_md(xen_pstart);
300    md_end = __pa(ia64_imva(&_end));
301    relo_start = xenheap_phys_end;
302
303    /*
304     * Scan through the memory descriptors after the kernel
305     * image to make sure we have enough room for the xenheap
306     * area, pushing out whatever may already be there.
307     */
308    while (relo_start + relo_size >= md_end) {
309        md = efi_get_md(md_end);
310
311        BUG_ON(!md);
312        BUG_ON(!is_xenheap_usable_memory(md));
313
314        md_end = md->phys_addr + MD_SIZE(md);
315        /*
316         * The dom0 kernel or initrd could overlap, reserve space
317         * at the end to relocate them later.
318         */
319        if (md->type == EFI_LOADER_DATA) {
320            /* Test for ranges we're not prepared to move */
321            BUG_ON(md_overlaps(md, __pa(ia64_boot_param)) ||
322                   md_overlaps(md, ia64_boot_param->efi_memmap) ||
323                   md_overlaps(md, ia64_boot_param->command_line));
324
325            relo_size += MD_SIZE(md);
326            /* If range overlaps the end, push out the relocation start */
327            if (md_end > relo_start)
328                relo_start = md_end;
329        }
330    }
331    last_md = md;
332    relo_end = relo_start + relo_size;
333
334    md_end = __pa(ia64_imva(&_end));
335 
336    /*
337     * Move any relocated data out into the previously found relocation
338     * area.  Any extra memory descriptrs are moved out to the end
339     * and set to zero pages.
340     */
341    for (md = efi_get_md(md_end) ;; md = efi_get_md(md_end)) {
342        md_end = md->phys_addr + MD_SIZE(md);
343
344        if (md->type == EFI_LOADER_DATA) {
345            unsigned long relo_offset;
346
347            if (md_overlaps(md, ia64_boot_param->domain_start)) {
348                relo_offset = ia64_boot_param->domain_start - md->phys_addr;
349                printk("Moving Dom0 kernel image: 0x%lx -> 0x%lx (%ld KiB)\n",
350                       ia64_boot_param->domain_start, relo_start + relo_offset,
351                       ia64_boot_param->domain_size >> 10);
352                ia64_boot_param->domain_start = relo_start + relo_offset;
353            }
354            if (ia64_boot_param->initrd_size &&
355                md_overlaps(md, ia64_boot_param->initrd_start)) {
356                relo_offset = ia64_boot_param->initrd_start - md->phys_addr;
357                printk("Moving Dom0 initrd image: 0x%lx -> 0x%lx (%ld KiB)\n",
358                       ia64_boot_param->initrd_start, relo_start + relo_offset,
359                       ia64_boot_param->initrd_size >> 10);
360                ia64_boot_param->initrd_start = relo_start + relo_offset;
361            }
362            memcpy(__va(relo_start), __va(md->phys_addr), MD_SIZE(md));
363            relo_start += MD_SIZE(md);
364        }
365
366        if (md == kern_md)
367            continue;
368        if (md == last_md)
369            break;
370
371        md->phys_addr = relo_end;
372        md->num_pages = 0;
373    }
374
375    /* Trim the last entry */
376    md->phys_addr = relo_end;
377    md->num_pages = (md_end - relo_end) >> EFI_PAGE_SHIFT;
378
379    /*
380     * Expand the new kernel/xenheap (and maybe dom0/initrd) out to
381     * the full size.  This range will already be type EFI_LOADER_DATA,
382     * therefore the xenheap area is now protected being allocated for
383     * use by find_memmap_space() in efi.c
384     */
385    kern_md->num_pages = (relo_end - kern_md->phys_addr) >> EFI_PAGE_SHIFT;
386
387    reserve_memory();
388
389    /* first find highest page frame number */
390    max_page = 0;
391    efi_memmap_walk(find_max_pfn, &max_page);
392    printk("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
393    efi_print();
394
395    xen_heap_start = memguard_init(ia64_imva(&_end));
396    printk("Before xen_heap_start: %p\n", xen_heap_start);
397    xen_heap_start = __va(init_boot_allocator(__pa(xen_heap_start)));
398    printk("After xen_heap_start: %p\n", xen_heap_start);
399
400    efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
401    efi_memmap_walk(xen_count_pages, &nr_pages);
402
403    printk("System RAM: %luMB (%lukB)\n",
404        nr_pages >> (20 - PAGE_SHIFT),
405        nr_pages << (PAGE_SHIFT - 10));
406    total_pages = nr_pages;
407
408    init_frametable();
409
410    trap_init();
411
412    alloc_dom0();
413
414    end_boot_allocator();
415
416    init_xenheap_pages(__pa(xen_heap_start), xenheap_phys_end);
417    printk("Xen heap: %luMB (%lukB)\n",
418        (xenheap_phys_end-__pa(xen_heap_start)) >> 20,
419        (xenheap_phys_end-__pa(xen_heap_start)) >> 10);
420
421    late_setup_arch(&cmdline);
422
423    scheduler_init();
424    idle_vcpu[0] = (struct vcpu*) ia64_r13;
425    idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
426    if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
427        BUG();
428
429    alloc_dom_xen_and_dom_io();
430    setup_per_cpu_areas();
431    mem_init();
432
433    local_irq_disable();
434    init_IRQ ();
435    init_xen_time(); /* initialise the time */
436    timer_init();
437
438    rcu_init();
439
440#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
441    open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
442#endif
443
444#ifdef CONFIG_SMP
445    if ( opt_nosmp )
446    {
447        max_cpus = 0;
448        smp_num_siblings = 1;
449        //boot_cpu_data.x86_num_cores = 1;
450    }
451
452    /* A vcpu is created for the idle domain on every physical cpu.
453       Limit the number of cpus to the maximum number of vcpus.  */
454    if (max_cpus > MAX_VIRT_CPUS)
455        max_cpus = MAX_VIRT_CPUS;
456
457    smp_prepare_cpus(max_cpus);
458
459    /* We aren't hotplug-capable yet. */
460    for_each_cpu ( i )
461        cpu_set(i, cpu_present_map);
462
463    /*  Enable IRQ to receive IPI (needed for ITC sync).  */
464    local_irq_enable();
465
466printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
467    for_each_present_cpu ( i )
468    {
469        if ( num_online_cpus() >= max_cpus )
470            break;
471        if ( !cpu_online(i) ) {
472            rcu_online_cpu(i);
473            __cpu_up(i);
474        }
475    }
476
477    local_irq_disable();
478
479    printk("Brought up %ld CPUs\n", (long)num_online_cpus());
480    smp_cpus_done(max_cpus);
481#endif
482
483    initialise_gdb(); /* could be moved earlier */
484
485    do_initcalls();
486    sort_main_extable();
487
488    init_rid_allocator ();
489
490    local_irq_enable();
491
492    if (opt_xencons) {
493        initialize_keytable();
494        if (ns16550_com1_gsi) {
495            if (opt_xencons_poll ||
496                iosapic_register_intr(ns16550_com1_gsi,
497                                      ns16550_com1_polarity,
498                                      ns16550_com1_trigger) < 0) {
499                ns16550_com1.irq = 0;
500                ns16550_init(0, &ns16550_com1);
501            }
502        }
503        serial_init_postirq();
504
505        /* Hide the HCDP table from dom0 */
506        efi.hcdp = NULL;
507    }
508
509    expose_p2m_init();
510
511    /* Create initial domain 0. */
512    dom0 = domain_create(0, 0, DOM0_SSIDREF);
513    if (dom0 == NULL)
514        panic("Error creating domain 0\n");
515    dom0_vcpu0 = alloc_vcpu(dom0, 0, 0);
516    if (dom0_vcpu0 == NULL || vcpu_late_initialise(dom0_vcpu0) != 0)
517        panic("Cannot allocate dom0 vcpu 0\n");
518
519    dom0->is_privileged = 1;
520
521    /*
522     * We're going to setup domain0 using the module(s) that we stashed safely
523     * above our heap. The second module, if present, is an initrd ramdisk.
524     */
525    dom0_memory_start = (unsigned long) __va(ia64_boot_param->domain_start);
526    dom0_memory_size = ia64_boot_param->domain_size;
527    dom0_initrd_start = (unsigned long) __va(ia64_boot_param->initrd_start);
528    dom0_initrd_size = ia64_boot_param->initrd_size;
529 
530    if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_size,
531                        dom0_initrd_start,dom0_initrd_size,
532                        0) != 0)
533        panic("Could not set up DOM0 guest OS\n");
534
535    if (!running_on_sim)  // slow on ski and pages are pre-initialized to zero
536        scrub_heap_pages();
537
538    init_trace_bufs();
539
540    if (opt_xencons) {
541        console_endboot();
542        serial_endboot();
543    }
544
545    domain0_ready = 1;
546
547    domain_unpause_by_systemcontroller(dom0);
548
549    startup_cpu_idle_loop();
550}
551
552void arch_get_xen_caps(xen_capabilities_info_t *info)
553{
554    /* Interface name is always xen-3.0-* for Xen-3.x. */
555    int major = 3, minor = 0;
556    char s[32];
557
558    (*info)[0] = '\0';
559
560    snprintf(s, sizeof(s), "xen-%d.%d-ia64 ", major, minor);
561    safe_strcat(*info, s);
562
563    snprintf(s, sizeof(s), "xen-%d.%d-ia64be ", major, minor);
564    safe_strcat(*info, s);
565
566    if (vmx_enabled)
567    {
568        snprintf(s, sizeof(s), "hvm-%d.%d-ia64 ", major, minor);
569        safe_strcat(*info, s);
570    }
571}
572
Note: See TracBrowser for help on using the repository browser.