ia64/xen-unstable

annotate 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
rev   line source
djm@6458 1 /******************************************************************************
djm@6458 2 * xensetup.c
djm@6458 3 * Copyright (c) 2004-2005 Hewlett-Packard Co
djm@6458 4 * Dan Magenheimer <dan.magenheimer@hp.com>
djm@6458 5 */
djm@6458 6
djm@6458 7 #include <xen/config.h>
djm@6458 8 #include <xen/lib.h>
djm@6458 9 #include <xen/errno.h>
djm@6458 10 //#include <xen/spinlock.h>
djm@6458 11 #include <xen/multiboot.h>
djm@6458 12 #include <xen/sched.h>
djm@6458 13 #include <xen/mm.h>
djm@6458 14 //#include <xen/delay.h>
djm@6458 15 #include <xen/compile.h>
djm@6458 16 //#include <xen/console.h>
djm@6458 17 #include <xen/serial.h>
djm@6458 18 #include <xen/trace.h>
djm@6458 19 #include <asm/meminit.h>
djm@6458 20 #include <asm/page.h>
djm@6458 21 #include <asm/setup.h>
djm@6458 22 #include <xen/string.h>
djm@6458 23
djm@6458 24 unsigned long xenheap_phys_end;
djm@6458 25
djm@6458 26 char saved_command_line[COMMAND_LINE_SIZE];
djm@6458 27
djm@6458 28 struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
djm@6458 29
djm@6458 30 cpumask_t cpu_present_map;
djm@6458 31
djm@6458 32 #ifdef CLONE_DOMAIN0
djm@6458 33 struct domain *clones[CLONE_DOMAIN0];
djm@6458 34 #endif
djm@6458 35 extern unsigned long domain0_ready;
djm@6458 36
djm@6458 37 int find_max_pfn (unsigned long, unsigned long, void *);
djm@6458 38 void start_of_day(void);
djm@6458 39
djm@6458 40 /* opt_nosmp: If true, secondary processors are ignored. */
djm@6458 41 static int opt_nosmp = 0;
djm@6458 42 boolean_param("nosmp", opt_nosmp);
djm@6458 43
djm@6458 44 /* maxcpus: maximum number of CPUs to activate. */
djm@6458 45 static unsigned int max_cpus = NR_CPUS;
djm@6458 46 integer_param("maxcpus", max_cpus);
djm@6458 47
djm@6458 48 /*
djm@6458 49 * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
djm@6458 50 * xen image
djm@6458 51 * bootmap bits
djm@6458 52 * xen heap
djm@6458 53 * Note: To allow xenheap size configurable, the prerequisite is
djm@6458 54 * to configure elilo allowing relocation defaultly. Then since
djm@6458 55 * elilo chooses 256M as alignment when relocating, alignment issue
djm@6458 56 * on IPF can be addressed.
djm@6458 57 */
djm@6458 58 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
djm@6458 59 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
djm@6458 60 extern long running_on_sim;
djm@6458 61 unsigned long xen_pstart;
djm@6458 62
djm@6458 63 static int
djm@6458 64 xen_count_pages(u64 start, u64 end, void *arg)
djm@6458 65 {
djm@6458 66 unsigned long *count = arg;
djm@6458 67
djm@6458 68 /* FIXME: do we need consider difference between DMA-usable memory and
djm@6458 69 * normal memory? Seems that HV has no requirement to operate DMA which
djm@6458 70 * is owned by Dom0? */
djm@6458 71 *count += (end - start) >> PAGE_SHIFT;
djm@6458 72 return 0;
djm@6458 73 }
djm@6458 74
djm@6458 75 /* Find first hole after trunk for xen image */
djm@6458 76 static int
djm@6458 77 xen_find_first_hole(u64 start, u64 end, void *arg)
djm@6458 78 {
djm@6458 79 unsigned long *first_hole = arg;
djm@6458 80
djm@6458 81 if ((*first_hole) == 0) {
djm@6458 82 if ((start <= KERNEL_START) && (KERNEL_START < end))
djm@6458 83 *first_hole = __pa(end);
djm@6458 84 }
djm@6458 85
djm@6458 86 return 0;
djm@6458 87 }
djm@6458 88
djm@6458 89 static void __init do_initcalls(void)
djm@6458 90 {
djm@6458 91 initcall_t *call;
djm@6458 92 for ( call = &__initcall_start; call < &__initcall_end; call++ )
djm@6458 93 (*call)();
djm@6458 94 }
djm@6458 95
djm@6458 96 /*
djm@6458 97 * IPF loader only supports one commaind line currently, for
djm@6458 98 * both xen and guest kernel. This function provides pre-parse
djm@6458 99 * to mixed command line, to split it into two parts.
djm@6458 100 *
djm@6458 101 * User should split the parameters by "--", with strings after
djm@6458 102 * spliter for guest kernel. Missing "--" means whole line belongs
djm@6458 103 * to guest. Example:
djm@6458 104 * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
djm@6458 105 * root=/dev/sda3 ro"
djm@6458 106 */
djm@6458 107 static char null[4] = { 0 };
djm@6458 108
djm@6458 109 void early_cmdline_parse(char **cmdline_p)
djm@6458 110 {
djm@6458 111 char *guest_cmd;
djm@6458 112 char *split = "--";
djm@6458 113
djm@6458 114 if (*cmdline_p == NULL) {
djm@6458 115 *cmdline_p = &null[0];
djm@6458 116 saved_command_line[0] = '\0';
djm@6458 117 return;
djm@6458 118 }
djm@6458 119
djm@6458 120 guest_cmd = strstr(*cmdline_p, split);
djm@6458 121 /* If no spliter, whole line is for guest */
djm@6458 122 if (guest_cmd == NULL) {
djm@6458 123 guest_cmd = *cmdline_p;
djm@6458 124 *cmdline_p = &null[0];
djm@6458 125 } else {
djm@6458 126 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
djm@6458 127 guest_cmd += strlen(split);
djm@6458 128 while (*guest_cmd == ' ') guest_cmd++;
djm@6458 129 }
djm@6458 130
djm@6458 131 strlcpy(saved_command_line, guest_cmd, COMMAND_LINE_SIZE);
djm@6458 132 return;
djm@6458 133 }
djm@6458 134
djm@6458 135 struct ns16550_defaults ns16550_com1 = {
djm@6458 136 .baud = BAUD_AUTO,
djm@6458 137 .data_bits = 8,
djm@6458 138 .parity = 'n',
djm@6458 139 .stop_bits = 1
djm@6458 140 };
djm@6458 141
djm@6458 142 struct ns16550_defaults ns16550_com2 = {
djm@6458 143 .baud = BAUD_AUTO,
djm@6458 144 .data_bits = 8,
djm@6458 145 .parity = 'n',
djm@6458 146 .stop_bits = 1
djm@6458 147 };
djm@6458 148
djm@6458 149 void start_kernel(void)
djm@6458 150 {
djm@6458 151 unsigned char *cmdline;
djm@6458 152 void *heap_start;
djm@6458 153 int i;
djm@6458 154 unsigned long max_mem, nr_pages, firsthole_start;
djm@6458 155 unsigned long dom0_memory_start, dom0_memory_end;
djm@6458 156 unsigned long initial_images_start, initial_images_end;
djm@6458 157
djm@6458 158 running_on_sim = is_platform_hp_ski();
djm@6458 159 /* Kernel may be relocated by EFI loader */
djm@6458 160 xen_pstart = ia64_tpa(KERNEL_START);
djm@6458 161
djm@6458 162 /* Must do this early -- e.g., spinlocks rely on get_current(). */
djm@6458 163 //set_current(&idle0_vcpu);
djm@6458 164 ia64_r13 = (void *)&idle0_vcpu;
djm@6458 165 idle0_vcpu.domain = &idle0_domain;
djm@6458 166
djm@6458 167 early_setup_arch(&cmdline);
djm@6458 168
djm@6458 169 /* We initialise the serial devices very early so we can get debugging. */
djm@6458 170 if (running_on_sim) hpsim_serial_init();
djm@6458 171 else {
djm@6458 172 ns16550_init(0, &ns16550_com1);
djm@6458 173 /* Also init com2 for Tiger4. */
djm@6458 174 ns16550_com2.io_base = 0x2f8;
djm@6458 175 ns16550_com2.irq = 3;
djm@6458 176 ns16550_init(1, &ns16550_com2);
djm@6458 177 }
djm@6458 178 serial_init_preirq();
djm@6458 179
djm@6458 180 init_console();
djm@6458 181 set_printk_prefix("(XEN) ");
djm@6458 182
djm@6458 183 /* xenheap should be in same TR-covered range with xen image */
djm@6458 184 xenheap_phys_end = xen_pstart + xenheap_size;
djm@6458 185 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
djm@6458 186 xen_pstart, xenheap_phys_end);
djm@6458 187
djm@6458 188 /* Find next hole */
djm@6458 189 firsthole_start = 0;
djm@6458 190 efi_memmap_walk(xen_find_first_hole, &firsthole_start);
djm@6458 191
djm@6458 192 initial_images_start = xenheap_phys_end;
djm@6458 193 initial_images_end = initial_images_start + ia64_boot_param->initrd_size;
djm@6458 194
djm@6458 195 /* Later may find another memory trunk, even away from xen image... */
djm@6458 196 if (initial_images_end > firsthole_start) {
djm@6458 197 printk("Not enough memory to stash the DOM0 kernel image.\n");
djm@6458 198 printk("First hole:0x%lx, relocation end: 0x%lx\n",
djm@6458 199 firsthole_start, initial_images_end);
djm@6458 200 for ( ; ; );
djm@6458 201 }
djm@6458 202
djm@6458 203 /* This copy is time consuming, but elilo may load Dom0 image
djm@6458 204 * within xenheap range */
djm@6458 205 printk("ready to move Dom0 to 0x%lx...", initial_images_start);
djm@6458 206 memmove(__va(initial_images_start),
djm@6458 207 __va(ia64_boot_param->initrd_start),
djm@6458 208 ia64_boot_param->initrd_size);
djm@6458 209 ia64_boot_param->initrd_start = initial_images_start;
djm@6458 210 printk("Done\n");
djm@6458 211
djm@6458 212 /* first find highest page frame number */
djm@6458 213 max_page = 0;
djm@6458 214 efi_memmap_walk(find_max_pfn, &max_page);
djm@6458 215 printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
djm@6458 216
djm@6458 217 heap_start = memguard_init(ia64_imva(&_end));
djm@6458 218 printf("Before heap_start: 0x%lx\n", heap_start);
djm@6458 219 heap_start = __va(init_boot_allocator(__pa(heap_start)));
djm@6458 220 printf("After heap_start: 0x%lx\n", heap_start);
djm@6458 221
djm@6458 222 reserve_memory();
djm@6458 223
djm@6458 224 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
djm@6458 225 efi_memmap_walk(xen_count_pages, &nr_pages);
djm@6458 226
djm@6458 227 printk("System RAM: %luMB (%lukB)\n",
djm@6458 228 nr_pages >> (20 - PAGE_SHIFT),
djm@6458 229 nr_pages << (PAGE_SHIFT - 10));
djm@6458 230
djm@6458 231 init_frametable();
djm@6458 232
djm@6458 233 ia64_fph_enable();
djm@6458 234 __ia64_init_fpu();
djm@6458 235
djm@6458 236 alloc_dom0();
djm@6458 237 #ifdef DOMU_BUILD_STAGING
djm@6458 238 alloc_domU_staging();
djm@6458 239 #endif
djm@6458 240
djm@6458 241 end_boot_allocator();
djm@6458 242
djm@6458 243 init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
djm@6458 244 printk("Xen heap: %luMB (%lukB)\n",
djm@6458 245 (xenheap_phys_end-__pa(heap_start)) >> 20,
djm@6458 246 (xenheap_phys_end-__pa(heap_start)) >> 10);
djm@6458 247
djm@6458 248 late_setup_arch(&cmdline);
djm@6458 249 setup_per_cpu_areas();
djm@6458 250 mem_init();
djm@6458 251
djm@6458 252 printk("About to call scheduler_init()\n");
djm@6458 253 scheduler_init();
djm@6458 254 local_irq_disable();
djm@6458 255 printk("About to call xen_time_init()\n");
djm@6458 256 xen_time_init();
djm@6458 257 #ifdef CONFIG_VTI
djm@6458 258 init_xen_time(); /* initialise the time */
djm@6458 259 #endif // CONFIG_VTI
djm@6458 260 printk("About to call ac_timer_init()\n");
djm@6458 261 ac_timer_init();
djm@6458 262 // init_xen_time(); ???
djm@6458 263
djm@6458 264 #ifdef CONFIG_SMP
djm@6458 265 if ( opt_nosmp )
djm@6458 266 {
djm@6458 267 max_cpus = 0;
djm@6458 268 smp_num_siblings = 1;
djm@6458 269 //boot_cpu_data.x86_num_cores = 1;
djm@6458 270 }
djm@6458 271
djm@6458 272 smp_prepare_cpus(max_cpus);
djm@6458 273
djm@6458 274 /* We aren't hotplug-capable yet. */
djm@6458 275 //BUG_ON(!cpus_empty(cpu_present_map));
djm@6458 276 for_each_cpu ( i )
djm@6458 277 cpu_set(i, cpu_present_map);
djm@6458 278
djm@6458 279 //BUG_ON(!local_irq_is_enabled());
djm@6458 280
djm@6458 281 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
djm@6458 282 for_each_present_cpu ( i )
djm@6458 283 {
djm@6458 284 if ( num_online_cpus() >= max_cpus )
djm@6458 285 break;
djm@6458 286 if ( !cpu_online(i) ) {
djm@6458 287 printk("About to call __cpu_up(%d)\n",i);
djm@6458 288 __cpu_up(i);
djm@6458 289 }
djm@6458 290 }
djm@6458 291
djm@6458 292 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
djm@6458 293 smp_cpus_done(max_cpus);
djm@6458 294 #endif
djm@6458 295
djm@6458 296
djm@6458 297 // FIXME: Should the following be swapped and moved later?
djm@6458 298 schedulers_start();
djm@6458 299 do_initcalls();
djm@6458 300 printk("About to call sort_main_extable()\n");
djm@6458 301 sort_main_extable();
djm@6458 302
djm@6458 303 /* surrender usage of kernel registers to domain, use percpu area instead */
djm@6458 304 __get_cpu_var(cpu_kr)._kr[IA64_KR_IO_BASE] = ia64_get_kr(IA64_KR_IO_BASE);
djm@6458 305 __get_cpu_var(cpu_kr)._kr[IA64_KR_PER_CPU_DATA] = ia64_get_kr(IA64_KR_PER_CPU_DATA);
djm@6458 306 __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT_STACK] = ia64_get_kr(IA64_KR_CURRENT_STACK);
djm@6458 307 __get_cpu_var(cpu_kr)._kr[IA64_KR_FPU_OWNER] = ia64_get_kr(IA64_KR_FPU_OWNER);
djm@6458 308 __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT] = ia64_get_kr(IA64_KR_CURRENT);
djm@6458 309 __get_cpu_var(cpu_kr)._kr[IA64_KR_PT_BASE] = ia64_get_kr(IA64_KR_PT_BASE);
djm@6458 310
djm@6458 311 /* Create initial domain 0. */
djm@6458 312 printk("About to call do_createdomain()\n");
djm@6458 313 dom0 = do_createdomain(0, 0);
djm@6458 314 init_task.domain = &idle0_domain;
djm@6458 315 init_task.processor = 0;
djm@6458 316 // init_task.mm = &init_mm;
djm@6458 317 init_task.domain->arch.mm = &init_mm;
djm@6458 318 // init_task.thread = INIT_THREAD;
djm@6458 319 //arch_do_createdomain(current);
djm@6458 320 #ifdef CLONE_DOMAIN0
djm@6458 321 {
djm@6458 322 int i;
djm@6458 323 for (i = 0; i < CLONE_DOMAIN0; i++) {
djm@6458 324 clones[i] = do_createdomain(i+1, 0);
djm@6458 325 if ( clones[i] == NULL )
djm@6458 326 panic("Error creating domain0 clone %d\n",i);
djm@6458 327 }
djm@6458 328 }
djm@6458 329 #endif
djm@6458 330 if ( dom0 == NULL )
djm@6458 331 panic("Error creating domain 0\n");
djm@6458 332
djm@6458 333 set_bit(_DOMF_privileged, &dom0->domain_flags);
djm@6458 334
djm@6458 335 /*
djm@6458 336 * We're going to setup domain0 using the module(s) that we stashed safely
djm@6458 337 * above our heap. The second module, if present, is an initrd ramdisk.
djm@6458 338 */
djm@6458 339 printk("About to call construct_dom0()\n");
djm@6458 340 dom0_memory_start = __va(ia64_boot_param->initrd_start);
djm@6458 341 dom0_memory_end = ia64_boot_param->initrd_size;
djm@6458 342 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_end,
djm@6458 343 0,
djm@6458 344 0,
djm@6458 345 0) != 0)
djm@6458 346 panic("Could not set up DOM0 guest OS\n");
djm@6458 347 #ifdef CLONE_DOMAIN0
djm@6458 348 {
djm@6458 349 int i;
djm@6458 350 dom0_memory_start = __va(ia64_boot_param->initrd_start);
djm@6458 351 dom0_memory_end = ia64_boot_param->initrd_size;
djm@6458 352 for (i = 0; i < CLONE_DOMAIN0; i++) {
djm@6458 353 printk("CONSTRUCTING DOMAIN0 CLONE #%d\n",i+1);
djm@6458 354 if ( construct_domU(clones[i], dom0_memory_start, dom0_memory_end,
djm@6458 355 0,
djm@6458 356 0,
djm@6458 357 0) != 0)
djm@6458 358 panic("Could not set up DOM0 clone %d\n",i);
djm@6458 359 }
djm@6458 360 }
djm@6458 361 #endif
djm@6458 362
djm@6458 363 /* The stash space for the initial kernel image can now be freed up. */
djm@6458 364 init_domheap_pages(ia64_boot_param->initrd_start,
djm@6458 365 ia64_boot_param->initrd_start + ia64_boot_param->initrd_size);
djm@6458 366 if (!running_on_sim) // slow on ski and pages are pre-initialized to zero
djm@6458 367 scrub_heap_pages();
djm@6458 368
djm@6458 369 printk("About to call init_trace_bufs()\n");
djm@6458 370 init_trace_bufs();
djm@6458 371
djm@6458 372 /* Give up the VGA console if DOM0 is configured to grab it. */
djm@6458 373 #ifndef IA64
djm@6458 374 console_endboot(cmdline && strstr(cmdline, "tty0"));
djm@6458 375 #endif
djm@6458 376
djm@6458 377 #ifdef CLONE_DOMAIN0
djm@6458 378 {
djm@6458 379 int i;
djm@6458 380 for (i = 0; i < CLONE_DOMAIN0; i++)
djm@6458 381 domain_unpause_by_systemcontroller(clones[i]);
djm@6458 382 }
djm@6458 383 #endif
djm@6458 384 domain_unpause_by_systemcontroller(dom0);
djm@6458 385 domain0_ready = 1;
djm@6458 386 local_irq_enable();
djm@6458 387 printk("About to call startup_cpu_idle_loop()\n");
djm@6458 388 startup_cpu_idle_loop();
djm@6458 389 }