ia64/xen-unstable

diff xen/arch/ia64/xen/xensetup.c @ 6458:3ca4ca7a9cc2

Final changes for linux 2.6.13 rebasing and some directory reorgs
author djm@kirby.fc.hp.com
date Thu Sep 01 12:46:28 2005 -0600 (2005-09-01)
parents
children 89fc07f85b01
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xen/arch/ia64/xen/xensetup.c	Thu Sep 01 12:46:28 2005 -0600
     1.3 @@ -0,0 +1,389 @@
     1.4 +/******************************************************************************
     1.5 + * xensetup.c
     1.6 + * Copyright (c) 2004-2005  Hewlett-Packard Co
     1.7 + *         Dan Magenheimer <dan.magenheimer@hp.com>
     1.8 + */
     1.9 +
    1.10 +#include <xen/config.h>
    1.11 +#include <xen/lib.h>
    1.12 +#include <xen/errno.h>
    1.13 +//#include <xen/spinlock.h>
    1.14 +#include <xen/multiboot.h>
    1.15 +#include <xen/sched.h>
    1.16 +#include <xen/mm.h>
    1.17 +//#include <xen/delay.h>
    1.18 +#include <xen/compile.h>
    1.19 +//#include <xen/console.h>
    1.20 +#include <xen/serial.h>
    1.21 +#include <xen/trace.h>
    1.22 +#include <asm/meminit.h>
    1.23 +#include <asm/page.h>
    1.24 +#include <asm/setup.h>
    1.25 +#include <xen/string.h>
    1.26 +
    1.27 +unsigned long xenheap_phys_end;
    1.28 +
    1.29 +char saved_command_line[COMMAND_LINE_SIZE];
    1.30 +
    1.31 +struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
    1.32 +
    1.33 +cpumask_t cpu_present_map;
    1.34 +
    1.35 +#ifdef CLONE_DOMAIN0
    1.36 +struct domain *clones[CLONE_DOMAIN0];
    1.37 +#endif
    1.38 +extern unsigned long domain0_ready;
    1.39 +
    1.40 +int find_max_pfn (unsigned long, unsigned long, void *);
    1.41 +void start_of_day(void);
    1.42 +
    1.43 +/* opt_nosmp: If true, secondary processors are ignored. */
    1.44 +static int opt_nosmp = 0;
    1.45 +boolean_param("nosmp", opt_nosmp);
    1.46 +
    1.47 +/* maxcpus: maximum number of CPUs to activate. */
    1.48 +static unsigned int max_cpus = NR_CPUS;
    1.49 +integer_param("maxcpus", max_cpus); 
    1.50 +
    1.51 +/*
    1.52 + * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
    1.53 + *	xen image
    1.54 + *	bootmap bits
    1.55 + *	xen heap
    1.56 + * Note: To allow xenheap size configurable, the prerequisite is
    1.57 + * to configure elilo allowing relocation defaultly. Then since
    1.58 + * elilo chooses 256M as alignment when relocating, alignment issue
    1.59 + * on IPF can be addressed.
    1.60 + */
    1.61 +unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
    1.62 +unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
    1.63 +extern long running_on_sim;
    1.64 +unsigned long xen_pstart;
    1.65 +
    1.66 +static int
    1.67 +xen_count_pages(u64 start, u64 end, void *arg)
    1.68 +{
    1.69 +    unsigned long *count = arg;
    1.70 +
    1.71 +    /* FIXME: do we need consider difference between DMA-usable memory and
    1.72 +     * normal memory? Seems that HV has no requirement to operate DMA which
    1.73 +     * is owned by Dom0? */
    1.74 +    *count += (end - start) >> PAGE_SHIFT;
    1.75 +    return 0;
    1.76 +}
    1.77 +
    1.78 +/* Find first hole after trunk for xen image */
    1.79 +static int
    1.80 +xen_find_first_hole(u64 start, u64 end, void *arg)
    1.81 +{
    1.82 +    unsigned long *first_hole = arg;
    1.83 +
    1.84 +    if ((*first_hole) == 0) {
    1.85 +	if ((start <= KERNEL_START) && (KERNEL_START < end))
    1.86 +	    *first_hole = __pa(end);
    1.87 +    }
    1.88 +
    1.89 +    return 0;
    1.90 +}
    1.91 +
    1.92 +static void __init do_initcalls(void)
    1.93 +{
    1.94 +    initcall_t *call;
    1.95 +    for ( call = &__initcall_start; call < &__initcall_end; call++ )
    1.96 +        (*call)();
    1.97 +}
    1.98 +
    1.99 +/*
   1.100 + * IPF loader only supports one commaind line currently, for
   1.101 + * both xen and guest kernel. This function provides pre-parse
   1.102 + * to mixed command line, to split it into two parts.
   1.103 + *
   1.104 + * User should split the parameters by "--", with strings after
   1.105 + * spliter for guest kernel. Missing "--" means whole line belongs
   1.106 + * to guest. Example:
   1.107 + *	"com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
   1.108 + * root=/dev/sda3 ro"
   1.109 + */
   1.110 +static char null[4] = { 0 };
   1.111 +
   1.112 +void early_cmdline_parse(char **cmdline_p)
   1.113 +{
   1.114 +    char *guest_cmd;
   1.115 +    char *split = "--";
   1.116 +
   1.117 +    if (*cmdline_p == NULL) {
   1.118 +	*cmdline_p = &null[0];
   1.119 +	saved_command_line[0] = '\0';
   1.120 +	return;
   1.121 +    }
   1.122 +
   1.123 +    guest_cmd = strstr(*cmdline_p, split);
   1.124 +    /* If no spliter, whole line is for guest */
   1.125 +    if (guest_cmd == NULL) {
   1.126 +	guest_cmd = *cmdline_p;
   1.127 +	*cmdline_p = &null[0];
   1.128 +    } else {
   1.129 +	*guest_cmd = '\0';	/* Split boot parameters for xen and guest */
   1.130 +	guest_cmd += strlen(split);
   1.131 +	while (*guest_cmd == ' ') guest_cmd++;
   1.132 +    }
   1.133 +
   1.134 +    strlcpy(saved_command_line, guest_cmd, COMMAND_LINE_SIZE);
   1.135 +    return;
   1.136 +}
   1.137 +
   1.138 +struct ns16550_defaults ns16550_com1 = {
   1.139 +    .baud      = BAUD_AUTO,
   1.140 +    .data_bits = 8,
   1.141 +    .parity    = 'n',
   1.142 +    .stop_bits = 1
   1.143 +};
   1.144 +
   1.145 +struct ns16550_defaults ns16550_com2 = {
   1.146 +    .baud      = BAUD_AUTO,
   1.147 +    .data_bits = 8,
   1.148 +    .parity    = 'n',
   1.149 +    .stop_bits = 1
   1.150 +};
   1.151 +
   1.152 +void start_kernel(void)
   1.153 +{
   1.154 +    unsigned char *cmdline;
   1.155 +    void *heap_start;
   1.156 +    int i;
   1.157 +    unsigned long max_mem, nr_pages, firsthole_start;
   1.158 +    unsigned long dom0_memory_start, dom0_memory_end;
   1.159 +    unsigned long initial_images_start, initial_images_end;
   1.160 +
   1.161 +    running_on_sim = is_platform_hp_ski();
   1.162 +    /* Kernel may be relocated by EFI loader */
   1.163 +    xen_pstart = ia64_tpa(KERNEL_START);
   1.164 +
   1.165 +    /* Must do this early -- e.g., spinlocks rely on get_current(). */
   1.166 +    //set_current(&idle0_vcpu);
   1.167 +    ia64_r13 = (void *)&idle0_vcpu;
   1.168 +    idle0_vcpu.domain = &idle0_domain;
   1.169 +
   1.170 +    early_setup_arch(&cmdline);
   1.171 +
   1.172 +    /* We initialise the serial devices very early so we can get debugging. */
   1.173 +    if (running_on_sim) hpsim_serial_init();
   1.174 +    else {
   1.175 +	ns16550_init(0, &ns16550_com1);
   1.176 +	/* Also init com2 for Tiger4. */
   1.177 +	ns16550_com2.io_base = 0x2f8;
   1.178 +	ns16550_com2.irq     = 3;
   1.179 +	ns16550_init(1, &ns16550_com2);
   1.180 +    }
   1.181 +    serial_init_preirq();
   1.182 +
   1.183 +    init_console();
   1.184 +    set_printk_prefix("(XEN) ");
   1.185 +
   1.186 +    /* xenheap should be in same TR-covered range with xen image */
   1.187 +    xenheap_phys_end = xen_pstart + xenheap_size;
   1.188 +    printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
   1.189 +	    xen_pstart, xenheap_phys_end);
   1.190 +
   1.191 +    /* Find next hole */
   1.192 +    firsthole_start = 0;
   1.193 +    efi_memmap_walk(xen_find_first_hole, &firsthole_start);
   1.194 +
   1.195 +    initial_images_start = xenheap_phys_end;
   1.196 +    initial_images_end = initial_images_start + ia64_boot_param->initrd_size;
   1.197 +
   1.198 +    /* Later may find another memory trunk, even away from xen image... */
   1.199 +    if (initial_images_end > firsthole_start) {
   1.200 +	printk("Not enough memory to stash the DOM0 kernel image.\n");
   1.201 +	printk("First hole:0x%lx, relocation end: 0x%lx\n",
   1.202 +		firsthole_start, initial_images_end);
   1.203 +	for ( ; ; );
   1.204 +    }
   1.205 +
   1.206 +    /* This copy is time consuming, but elilo may load Dom0 image
   1.207 +     * within xenheap range */
   1.208 +    printk("ready to move Dom0 to 0x%lx...", initial_images_start);
   1.209 +    memmove(__va(initial_images_start),
   1.210 +	   __va(ia64_boot_param->initrd_start),
   1.211 +	   ia64_boot_param->initrd_size);
   1.212 +    ia64_boot_param->initrd_start = initial_images_start;
   1.213 +    printk("Done\n");
   1.214 +
   1.215 +    /* first find highest page frame number */
   1.216 +    max_page = 0;
   1.217 +    efi_memmap_walk(find_max_pfn, &max_page);
   1.218 +    printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
   1.219 +
   1.220 +    heap_start = memguard_init(ia64_imva(&_end));
   1.221 +    printf("Before heap_start: 0x%lx\n", heap_start);
   1.222 +    heap_start = __va(init_boot_allocator(__pa(heap_start)));
   1.223 +    printf("After heap_start: 0x%lx\n", heap_start);
   1.224 +
   1.225 +    reserve_memory();
   1.226 +
   1.227 +    efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
   1.228 +    efi_memmap_walk(xen_count_pages, &nr_pages);
   1.229 +
   1.230 +    printk("System RAM: %luMB (%lukB)\n",
   1.231 +	nr_pages >> (20 - PAGE_SHIFT),
   1.232 +	nr_pages << (PAGE_SHIFT - 10));
   1.233 +
   1.234 +    init_frametable();
   1.235 +
   1.236 +    ia64_fph_enable();
   1.237 +    __ia64_init_fpu();
   1.238 +
   1.239 +    alloc_dom0();
   1.240 +#ifdef DOMU_BUILD_STAGING
   1.241 +    alloc_domU_staging();
   1.242 +#endif
   1.243 +
   1.244 +    end_boot_allocator();
   1.245 +
   1.246 +    init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
   1.247 +    printk("Xen heap: %luMB (%lukB)\n",
   1.248 +	(xenheap_phys_end-__pa(heap_start)) >> 20,
   1.249 +	(xenheap_phys_end-__pa(heap_start)) >> 10);
   1.250 +
   1.251 +    late_setup_arch(&cmdline);
   1.252 +    setup_per_cpu_areas();
   1.253 +    mem_init();
   1.254 +
   1.255 +printk("About to call scheduler_init()\n");
   1.256 +    scheduler_init();
   1.257 +    local_irq_disable();
   1.258 +printk("About to call xen_time_init()\n");
   1.259 +    xen_time_init();
   1.260 +#ifdef CONFIG_VTI
   1.261 +    init_xen_time(); /* initialise the time */
   1.262 +#endif // CONFIG_VTI 
   1.263 +printk("About to call ac_timer_init()\n");
   1.264 +    ac_timer_init();
   1.265 +// init_xen_time(); ???
   1.266 +
   1.267 +#ifdef CONFIG_SMP
   1.268 +    if ( opt_nosmp )
   1.269 +    {
   1.270 +        max_cpus = 0;
   1.271 +        smp_num_siblings = 1;
   1.272 +        //boot_cpu_data.x86_num_cores = 1;
   1.273 +    }
   1.274 +
   1.275 +    smp_prepare_cpus(max_cpus);
   1.276 +
   1.277 +    /* We aren't hotplug-capable yet. */
   1.278 +    //BUG_ON(!cpus_empty(cpu_present_map));
   1.279 +    for_each_cpu ( i )
   1.280 +        cpu_set(i, cpu_present_map);
   1.281 +
   1.282 +    //BUG_ON(!local_irq_is_enabled());
   1.283 +
   1.284 +printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
   1.285 +    for_each_present_cpu ( i )
   1.286 +    {
   1.287 +        if ( num_online_cpus() >= max_cpus )
   1.288 +            break;
   1.289 +        if ( !cpu_online(i) ) {
   1.290 +printk("About to call __cpu_up(%d)\n",i);
   1.291 +            __cpu_up(i);
   1.292 +	}
   1.293 +    }
   1.294 +
   1.295 +    printk("Brought up %ld CPUs\n", (long)num_online_cpus());
   1.296 +    smp_cpus_done(max_cpus);
   1.297 +#endif
   1.298 +
   1.299 +
   1.300 +	// FIXME: Should the following be swapped and moved later?
   1.301 +    schedulers_start();
   1.302 +    do_initcalls();
   1.303 +printk("About to call sort_main_extable()\n");
   1.304 +    sort_main_extable();
   1.305 +
   1.306 +    /* surrender usage of kernel registers to domain, use percpu area instead */
   1.307 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_IO_BASE] = ia64_get_kr(IA64_KR_IO_BASE);
   1.308 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_PER_CPU_DATA] = ia64_get_kr(IA64_KR_PER_CPU_DATA);
   1.309 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT_STACK] = ia64_get_kr(IA64_KR_CURRENT_STACK);
   1.310 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_FPU_OWNER] = ia64_get_kr(IA64_KR_FPU_OWNER);
   1.311 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT] = ia64_get_kr(IA64_KR_CURRENT);
   1.312 +    __get_cpu_var(cpu_kr)._kr[IA64_KR_PT_BASE] = ia64_get_kr(IA64_KR_PT_BASE);
   1.313 +
   1.314 +    /* Create initial domain 0. */
   1.315 +printk("About to call do_createdomain()\n");
   1.316 +    dom0 = do_createdomain(0, 0);
   1.317 +    init_task.domain = &idle0_domain;
   1.318 +    init_task.processor = 0;
   1.319 +//    init_task.mm = &init_mm;
   1.320 +    init_task.domain->arch.mm = &init_mm;
   1.321 +//    init_task.thread = INIT_THREAD;
   1.322 +    //arch_do_createdomain(current);
   1.323 +#ifdef CLONE_DOMAIN0
   1.324 +    {
   1.325 +    int i;
   1.326 +    for (i = 0; i < CLONE_DOMAIN0; i++) {
   1.327 +	clones[i] = do_createdomain(i+1, 0);
   1.328 +        if ( clones[i] == NULL )
   1.329 +            panic("Error creating domain0 clone %d\n",i);
   1.330 +    }
   1.331 +    }
   1.332 +#endif
   1.333 +    if ( dom0 == NULL )
   1.334 +        panic("Error creating domain 0\n");
   1.335 +
   1.336 +    set_bit(_DOMF_privileged, &dom0->domain_flags);
   1.337 +
   1.338 +    /*
   1.339 +     * We're going to setup domain0 using the module(s) that we stashed safely
   1.340 +     * above our heap. The second module, if present, is an initrd ramdisk.
   1.341 +     */
   1.342 +printk("About to call construct_dom0()\n");
   1.343 +    dom0_memory_start = __va(ia64_boot_param->initrd_start);
   1.344 +    dom0_memory_end = ia64_boot_param->initrd_size;
   1.345 +    if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_end,
   1.346 +			0,
   1.347 +                        0,
   1.348 +			0) != 0)
   1.349 +        panic("Could not set up DOM0 guest OS\n");
   1.350 +#ifdef CLONE_DOMAIN0
   1.351 +    {
   1.352 +    int i;
   1.353 +    dom0_memory_start = __va(ia64_boot_param->initrd_start);
   1.354 +    dom0_memory_end = ia64_boot_param->initrd_size;
   1.355 +    for (i = 0; i < CLONE_DOMAIN0; i++) {
   1.356 +printk("CONSTRUCTING DOMAIN0 CLONE #%d\n",i+1);
   1.357 +        if ( construct_domU(clones[i], dom0_memory_start, dom0_memory_end,
   1.358 +                        0, 
   1.359 +                        0,
   1.360 +			0) != 0)
   1.361 +            panic("Could not set up DOM0 clone %d\n",i);
   1.362 +    }
   1.363 +    }
   1.364 +#endif
   1.365 +
   1.366 +    /* The stash space for the initial kernel image can now be freed up. */
   1.367 +    init_domheap_pages(ia64_boot_param->initrd_start,
   1.368 +		       ia64_boot_param->initrd_start + ia64_boot_param->initrd_size);
   1.369 +    if (!running_on_sim)  // slow on ski and pages are pre-initialized to zero
   1.370 +	scrub_heap_pages();
   1.371 +
   1.372 +printk("About to call init_trace_bufs()\n");
   1.373 +    init_trace_bufs();
   1.374 +
   1.375 +    /* Give up the VGA console if DOM0 is configured to grab it. */
   1.376 +#ifndef IA64
   1.377 +    console_endboot(cmdline && strstr(cmdline, "tty0"));
   1.378 +#endif
   1.379 +
   1.380 +#ifdef CLONE_DOMAIN0
   1.381 +    {
   1.382 +    int i;
   1.383 +    for (i = 0; i < CLONE_DOMAIN0; i++)
   1.384 +	domain_unpause_by_systemcontroller(clones[i]);
   1.385 +    }
   1.386 +#endif
   1.387 +    domain_unpause_by_systemcontroller(dom0);
   1.388 +    domain0_ready = 1;
   1.389 +    local_irq_enable();
   1.390 +printk("About to call startup_cpu_idle_loop()\n");
   1.391 +    startup_cpu_idle_loop();
   1.392 +}