ia64/xen-unstable

annotate xen/arch/ia64/xen/xensetup.c @ 16071:2d761ca771fb

xen: Changes to printk handling:
1. Command-line option 'console_timestamps' adds a timestamp prefix
to each line of Xen console output (x86 only, after CMOS has been
interrogated).
2. Clean up prefix handling and vanity banner info.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Thu Oct 04 17:58:16 2007 +0100 (2007-10-04)
parents 4ffca478e2f7
children af3550f53874
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/multiboot.h>
djm@6458 11 #include <xen/sched.h>
djm@6458 12 #include <xen/mm.h>
djm@6723 13 #include <public/version.h>
kaf24@9117 14 #include <xen/gdbstub.h>
kfraser@10890 15 #include <xen/version.h>
awilliam@9005 16 #include <xen/console.h>
awilliam@10664 17 #include <xen/domain.h>
djm@6458 18 #include <xen/serial.h>
djm@6458 19 #include <xen/trace.h>
kfraser@11718 20 #include <xen/keyhandler.h>
alex@15563 21 #include <xen/vga.h>
djm@6458 22 #include <asm/meminit.h>
djm@6458 23 #include <asm/page.h>
djm@6458 24 #include <asm/setup.h>
djm@6458 25 #include <xen/string.h>
djm@8475 26 #include <asm/vmx.h>
awilliam@9005 27 #include <linux/efi.h>
awilliam@10445 28 #include <asm/iosapic.h>
awilliam@13479 29 #include <xen/softirq.h>
awilliam@13780 30 #include <xen/rcupdate.h>
kfraser@15819 31 #include <xsm/acm/acm_hooks.h>
alex@15135 32 #include <asm/sn/simulator.h>
djm@6458 33
awilliam@9773 34 unsigned long xenheap_phys_end, total_pages;
djm@6458 35
djm@6458 36 char saved_command_line[COMMAND_LINE_SIZE];
alex@15131 37 char __initdata dom0_command_line[COMMAND_LINE_SIZE];
djm@6458 38
djm@6458 39 cpumask_t cpu_present_map;
djm@6458 40
djm@6458 41 extern unsigned long domain0_ready;
djm@6458 42
djm@6458 43 int find_max_pfn (unsigned long, unsigned long, void *);
djm@6458 44
awilliam@9005 45 /* FIXME: which header these declarations should be there ? */
awilliam@9005 46 extern void early_setup_arch(char **);
awilliam@9005 47 extern void late_setup_arch(char **);
awilliam@9005 48 extern void hpsim_serial_init(void);
awilliam@9005 49 extern void setup_per_cpu_areas(void);
awilliam@9005 50 extern void mem_init(void);
awilliam@9005 51 extern void init_IRQ(void);
awilliam@10157 52 extern void trap_init(void);
awilliam@11639 53 extern void xen_patch_kernel(void);
awilliam@9005 54
alex@15765 55 /* nosmp: ignore secondary processors */
alex@15765 56 static int __initdata opt_nosmp;
djm@6458 57 boolean_param("nosmp", opt_nosmp);
djm@6458 58
alex@15765 59 /* maxcpus: maximum number of CPUs to activate */
alex@15131 60 static unsigned int __initdata max_cpus = NR_CPUS;
djm@6458 61 integer_param("maxcpus", max_cpus);
djm@6458 62
alex@15765 63 /* xencons: toggle xenconsole input (and irq).
awilliam@10442 64 Note: you have to disable 8250 serials in domains (to avoid use of the
awilliam@10442 65 same resource). */
alex@15131 66 static int __initdata opt_xencons = 1;
awilliam@10698 67 integer_param("xencons", opt_xencons);
awilliam@10442 68
alex@15765 69 /* xencons_poll: toggle non-legacy xencons UARTs to run in polling mode */
alex@15131 70 static int __initdata opt_xencons_poll;
awilliam@10445 71 boolean_param("xencons_poll", opt_xencons_poll);
awilliam@10445 72
djm@6458 73 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
djm@6458 74 unsigned long xen_pstart;
alex@15131 75 void *xen_pickle_offset __read_mostly;
djm@6458 76
alex@15131 77 static int __init
djm@6458 78 xen_count_pages(u64 start, u64 end, void *arg)
djm@6458 79 {
djm@6458 80 unsigned long *count = arg;
djm@6458 81
djm@6458 82 /* FIXME: do we need consider difference between DMA-usable memory and
djm@6458 83 * normal memory? Seems that HV has no requirement to operate DMA which
djm@6458 84 * is owned by Dom0? */
djm@6458 85 *count += (end - start) >> PAGE_SHIFT;
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 /*
alex@15765 97 * IPF loader only supports one command 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
alex@15131 109 void __init early_cmdline_parse(char **cmdline_p)
djm@6458 110 {
djm@6458 111 char *guest_cmd;
awilliam@9270 112 static const char * const 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';
awilliam@9270 117 dom0_command_line[0] = '\0';
djm@6458 118 return;
djm@6458 119 }
djm@6458 120
djm@6458 121 guest_cmd = strstr(*cmdline_p, split);
djm@6458 122 /* If no spliter, whole line is for guest */
djm@6458 123 if (guest_cmd == NULL) {
djm@6458 124 guest_cmd = *cmdline_p;
djm@6458 125 *cmdline_p = &null[0];
djm@6458 126 } else {
djm@6458 127 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
djm@6458 128 guest_cmd += strlen(split);
djm@6458 129 while (*guest_cmd == ' ') guest_cmd++;
djm@6458 130 }
djm@6458 131
awilliam@9270 132 strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
awilliam@9270 133 strlcpy(dom0_command_line, guest_cmd, COMMAND_LINE_SIZE);
djm@6458 134 return;
djm@6458 135 }
djm@6458 136
djm@6458 137 struct ns16550_defaults ns16550_com1 = {
djm@6458 138 .data_bits = 8,
djm@6458 139 .parity = 'n',
djm@6458 140 .stop_bits = 1
djm@6458 141 };
djm@6458 142
awilliam@10445 143 unsigned int ns16550_com1_gsi;
awilliam@10445 144 unsigned int ns16550_com1_polarity;
awilliam@10445 145 unsigned int ns16550_com1_trigger;
awilliam@10445 146
djm@6458 147 struct ns16550_defaults ns16550_com2 = {
djm@6458 148 .data_bits = 8,
djm@6458 149 .parity = 'n',
djm@6458 150 .stop_bits = 1
djm@6458 151 };
djm@6458 152
awilliam@9750 153 /* efi_print: print efi table at boot */
alex@15131 154 static int __initdata opt_efi_print;
awilliam@9750 155 boolean_param("efi_print", opt_efi_print);
awilliam@9750 156
awilliam@9750 157 /* print EFI memory map: */
alex@15131 158 static void __init
awilliam@9750 159 efi_print(void)
awilliam@9750 160 {
awilliam@9750 161 void *efi_map_start, *efi_map_end;
awilliam@9750 162 u64 efi_desc_size;
awilliam@9750 163
awilliam@9750 164 efi_memory_desc_t *md;
awilliam@9750 165 void *p;
awilliam@9750 166 int i;
awilliam@9750 167
awilliam@9750 168 if (!opt_efi_print)
awilliam@9750 169 return;
awilliam@9750 170
awilliam@9750 171 efi_map_start = __va(ia64_boot_param->efi_memmap);
awilliam@9750 172 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
awilliam@9750 173 efi_desc_size = ia64_boot_param->efi_memdesc_size;
awilliam@9750 174
awilliam@9750 175 for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
awilliam@9750 176 md = p;
awilliam@11741 177 printk("mem%02u: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) "
awilliam@11741 178 "(%luMB)\n", i, md->type, md->attribute, md->phys_addr,
awilliam@9750 179 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
awilliam@9750 180 md->num_pages >> (20 - EFI_PAGE_SHIFT));
awilliam@9750 181 }
awilliam@9750 182 }
awilliam@9750 183
awilliam@10270 184 /*
awilliam@10270 185 * These functions are utility functions for getting and
awilliam@10270 186 * testing memory descriptors for allocating the xenheap area.
awilliam@10270 187 */
alex@15765 188 static efi_memory_desc_t * __init
awilliam@10270 189 efi_get_md (unsigned long phys_addr)
awilliam@10270 190 {
awilliam@10270 191 void *efi_map_start, *efi_map_end, *p;
awilliam@10270 192 efi_memory_desc_t *md;
awilliam@10270 193 u64 efi_desc_size;
awilliam@10270 194
awilliam@10270 195 efi_map_start = __va(ia64_boot_param->efi_memmap);
awilliam@10270 196 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
awilliam@10270 197 efi_desc_size = ia64_boot_param->efi_memdesc_size;
awilliam@10270 198
awilliam@10270 199 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
awilliam@10270 200 md = p;
awilliam@10270 201 if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
awilliam@10270 202 return md;
awilliam@10270 203 }
awilliam@10270 204 return 0;
awilliam@10270 205 }
awilliam@10270 206
alex@15765 207 static int __init
awilliam@10270 208 is_xenheap_usable_memory(efi_memory_desc_t *md)
awilliam@10270 209 {
awilliam@10270 210 if (!(md->attribute & EFI_MEMORY_WB))
awilliam@10270 211 return 0;
awilliam@10270 212
awilliam@10270 213 switch (md->type) {
awilliam@10270 214 case EFI_LOADER_CODE:
awilliam@10270 215 case EFI_LOADER_DATA:
awilliam@10270 216 case EFI_BOOT_SERVICES_CODE:
awilliam@10270 217 case EFI_BOOT_SERVICES_DATA:
awilliam@10270 218 case EFI_CONVENTIONAL_MEMORY:
awilliam@10270 219 return 1;
awilliam@10270 220 }
awilliam@10270 221 return 0;
awilliam@10270 222 }
awilliam@10270 223
alex@15765 224 static inline int __init
awilliam@10270 225 md_overlaps(efi_memory_desc_t *md, unsigned long phys_addr)
awilliam@10270 226 {
awilliam@10270 227 return (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT));
awilliam@10270 228 }
awilliam@10270 229
awilliam@10270 230 #define MD_SIZE(md) (md->num_pages << EFI_PAGE_SHIFT)
awilliam@10270 231
alex@15131 232 extern char __init_begin[], __init_end[];
alex@15131 233 static void noinline init_done(void)
alex@15131 234 {
alex@15131 235 memset(__init_begin, 0, __init_end - __init_begin);
alex@15131 236 flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end);
alex@15131 237 init_xenheap_pages(__pa(__init_begin), __pa(__init_end));
alex@15131 238 printk("Freed %ldkB init memory.\n",
alex@15131 239 (long)(__init_end-__init_begin)>>10);
alex@15131 240
alex@15131 241 startup_cpu_idle_loop();
alex@15131 242 }
alex@15131 243
alex@15423 244 int running_on_sim;
alex@15423 245
alex@15423 246 static int __init
alex@15423 247 is_platform_hp_ski(void)
alex@15423 248 {
alex@15423 249 int i;
alex@15423 250 long cpuid[6];
alex@15423 251
alex@15423 252 for (i = 0; i < 5; ++i)
alex@15423 253 cpuid[i] = ia64_get_cpuid(i);
alex@15423 254
alex@15423 255 if ((cpuid[0] & 0xff) != 'H')
alex@15423 256 return 0;
alex@15423 257 if ((cpuid[3] & 0xff) != 0x4)
alex@15423 258 return 0;
alex@15423 259 if (((cpuid[3] >> 8) & 0xff) != 0x0)
alex@15423 260 return 0;
alex@15423 261 if (((cpuid[3] >> 16) & 0xff) != 0x0)
alex@15423 262 return 0;
alex@15423 263 if (((cpuid[3] >> 24) & 0x7) != 0x7)
alex@15423 264 return 0;
alex@15423 265
alex@15423 266 return 1;
alex@15423 267 }
alex@15423 268
alex@15131 269 void __init start_kernel(void)
djm@6458 270 {
awilliam@10442 271 char *cmdline;
awilliam@10270 272 unsigned long nr_pages;
djm@7735 273 unsigned long dom0_memory_start, dom0_memory_size;
djm@7735 274 unsigned long dom0_initrd_start, dom0_initrd_size;
awilliam@10270 275 unsigned long md_end, relo_start, relo_end, relo_size = 0;
kaf24@8552 276 struct domain *idle_domain;
awilliam@13434 277 struct vcpu *dom0_vcpu0;
awilliam@10270 278 efi_memory_desc_t *kern_md, *last_md, *md;
alex@15131 279 void *xen_heap_start;
awilliam@9314 280 #ifdef CONFIG_SMP
awilliam@9314 281 int i;
awilliam@9314 282 #endif
djm@6458 283
awilliam@11036 284 /* Be sure the struct shared_info size is <= XSI_SIZE. */
awilliam@11036 285 BUILD_BUG_ON(sizeof(struct shared_info) > XSI_SIZE);
awilliam@11036 286
djm@6458 287 /* Kernel may be relocated by EFI loader */
djm@6458 288 xen_pstart = ia64_tpa(KERNEL_START);
djm@6458 289
alex@15423 290 running_on_sim = is_platform_hp_ski();
alex@15423 291
awilliam@10442 292 early_setup_arch(&cmdline);
djm@6458 293
djm@6458 294 /* We initialise the serial devices very early so we can get debugging. */
awilliam@13845 295 if (running_on_sim)
awilliam@13845 296 hpsim_serial_init();
djm@6458 297 else {
awilliam@13845 298 ns16550_init(0, &ns16550_com1);
awilliam@13904 299 ns16550_init(1, &ns16550_com2);
djm@6458 300 }
djm@6458 301 serial_init_preirq();
djm@6458 302
alex@15563 303 #ifdef CONFIG_VGA
alex@15563 304 /* Plug in a default VGA mode */
alex@15563 305 vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
alex@15563 306 vga_console_info.u.text_mode_3.font_height = 16; /* generic VGA? */
alex@15563 307 vga_console_info.u.text_mode_3.cursor_x =
alex@15563 308 ia64_boot_param->console_info.orig_x;
alex@15563 309 vga_console_info.u.text_mode_3.cursor_y =
alex@15563 310 ia64_boot_param->console_info.orig_y;
alex@15563 311 vga_console_info.u.text_mode_3.rows =
alex@15563 312 ia64_boot_param->console_info.num_rows;
alex@15563 313 vga_console_info.u.text_mode_3.columns =
alex@15563 314 ia64_boot_param->console_info.num_cols;
alex@15563 315 #endif
alex@15563 316
djm@6458 317 init_console();
djm@6458 318
awilliam@10270 319 if (running_on_sim || ia64_boot_param->domain_start == 0 ||
awilliam@10270 320 ia64_boot_param->domain_size == 0) {
awilliam@10270 321 /* This is possible only with the old elilo, which does not support
awilliam@10270 322 a vmm. Fix now, and continue without initrd. */
awilliam@10270 323 printk ("Your elilo is not Xen-aware. Bootparams fixed\n");
awilliam@10270 324 ia64_boot_param->domain_start = ia64_boot_param->initrd_start;
awilliam@10270 325 ia64_boot_param->domain_size = ia64_boot_param->initrd_size;
awilliam@10270 326 ia64_boot_param->initrd_start = 0;
awilliam@10270 327 ia64_boot_param->initrd_size = 0;
awilliam@10270 328 }
awilliam@10270 329
awilliam@11306 330 printk("Xen command line: %s\n", saved_command_line);
djm@6458 331 /* xenheap should be in same TR-covered range with xen image */
djm@6458 332 xenheap_phys_end = xen_pstart + xenheap_size;
djm@6458 333 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
awilliam@10270 334 xen_pstart, xenheap_phys_end);
djm@6458 335
awilliam@11639 336 xen_patch_kernel();
awilliam@11639 337
awilliam@10270 338 kern_md = md = efi_get_md(xen_pstart);
awilliam@10270 339 md_end = __pa(ia64_imva(&_end));
awilliam@10270 340 relo_start = xenheap_phys_end;
awilliam@10270 341
awilliam@10270 342 /*
awilliam@10270 343 * Scan through the memory descriptors after the kernel
awilliam@10270 344 * image to make sure we have enough room for the xenheap
awilliam@10270 345 * area, pushing out whatever may already be there.
awilliam@10270 346 */
awilliam@10270 347 while (relo_start + relo_size >= md_end) {
awilliam@10270 348 md = efi_get_md(md_end);
awilliam@10270 349
awilliam@10270 350 BUG_ON(!md);
awilliam@10270 351 BUG_ON(!is_xenheap_usable_memory(md));
awilliam@10270 352
awilliam@10270 353 md_end = md->phys_addr + MD_SIZE(md);
awilliam@10270 354 /*
awilliam@10270 355 * The dom0 kernel or initrd could overlap, reserve space
awilliam@10270 356 * at the end to relocate them later.
awilliam@10270 357 */
awilliam@10270 358 if (md->type == EFI_LOADER_DATA) {
awilliam@10270 359 /* Test for ranges we're not prepared to move */
awilliam@10270 360 BUG_ON(md_overlaps(md, __pa(ia64_boot_param)) ||
awilliam@10270 361 md_overlaps(md, ia64_boot_param->efi_memmap) ||
awilliam@10270 362 md_overlaps(md, ia64_boot_param->command_line));
awilliam@10270 363
awilliam@10270 364 relo_size += MD_SIZE(md);
awilliam@10270 365 /* If range overlaps the end, push out the relocation start */
awilliam@10270 366 if (md_end > relo_start)
awilliam@10270 367 relo_start = md_end;
awilliam@10270 368 }
awilliam@10270 369 }
awilliam@10270 370 last_md = md;
awilliam@10270 371 relo_end = relo_start + relo_size;
awilliam@10270 372
awilliam@10270 373 md_end = __pa(ia64_imva(&_end));
awilliam@10270 374
awilliam@10270 375 /*
awilliam@10270 376 * Move any relocated data out into the previously found relocation
awilliam@10270 377 * area. Any extra memory descriptrs are moved out to the end
awilliam@10270 378 * and set to zero pages.
awilliam@10270 379 */
awilliam@10270 380 for (md = efi_get_md(md_end) ;; md = efi_get_md(md_end)) {
awilliam@10270 381 md_end = md->phys_addr + MD_SIZE(md);
awilliam@10270 382
awilliam@10270 383 if (md->type == EFI_LOADER_DATA) {
awilliam@10270 384 unsigned long relo_offset;
awilliam@10270 385
awilliam@10270 386 if (md_overlaps(md, ia64_boot_param->domain_start)) {
awilliam@10270 387 relo_offset = ia64_boot_param->domain_start - md->phys_addr;
awilliam@10270 388 printk("Moving Dom0 kernel image: 0x%lx -> 0x%lx (%ld KiB)\n",
awilliam@10270 389 ia64_boot_param->domain_start, relo_start + relo_offset,
awilliam@10270 390 ia64_boot_param->domain_size >> 10);
awilliam@10270 391 ia64_boot_param->domain_start = relo_start + relo_offset;
awilliam@10270 392 }
awilliam@10270 393 if (ia64_boot_param->initrd_size &&
awilliam@10270 394 md_overlaps(md, ia64_boot_param->initrd_start)) {
awilliam@10270 395 relo_offset = ia64_boot_param->initrd_start - md->phys_addr;
awilliam@10270 396 printk("Moving Dom0 initrd image: 0x%lx -> 0x%lx (%ld KiB)\n",
awilliam@10270 397 ia64_boot_param->initrd_start, relo_start + relo_offset,
awilliam@10270 398 ia64_boot_param->initrd_size >> 10);
awilliam@10270 399 ia64_boot_param->initrd_start = relo_start + relo_offset;
awilliam@10270 400 }
awilliam@10270 401 memcpy(__va(relo_start), __va(md->phys_addr), MD_SIZE(md));
awilliam@10270 402 relo_start += MD_SIZE(md);
awilliam@10270 403 }
awilliam@10270 404
awilliam@10270 405 if (md == kern_md)
awilliam@10270 406 continue;
awilliam@10270 407 if (md == last_md)
awilliam@10270 408 break;
awilliam@10270 409
awilliam@10270 410 md->phys_addr = relo_end;
awilliam@10270 411 md->num_pages = 0;
djm@7735 412 }
djm@7735 413
awilliam@10270 414 /* Trim the last entry */
awilliam@10270 415 md->phys_addr = relo_end;
awilliam@10270 416 md->num_pages = (md_end - relo_end) >> EFI_PAGE_SHIFT;
djm@6458 417
awilliam@10270 418 /*
awilliam@10270 419 * Expand the new kernel/xenheap (and maybe dom0/initrd) out to
awilliam@10270 420 * the full size. This range will already be type EFI_LOADER_DATA,
awilliam@10270 421 * therefore the xenheap area is now protected being allocated for
awilliam@10270 422 * use by find_memmap_space() in efi.c
awilliam@10270 423 */
awilliam@10270 424 kern_md->num_pages = (relo_end - kern_md->phys_addr) >> EFI_PAGE_SHIFT;
djm@7735 425
awilliam@10270 426 reserve_memory();
djm@6458 427
djm@6458 428 /* first find highest page frame number */
djm@6458 429 max_page = 0;
djm@6458 430 efi_memmap_walk(find_max_pfn, &max_page);
kfraser@11947 431 printk("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
awilliam@9750 432 efi_print();
alex@15131 433
alex@15131 434 /*
alex@15131 435 * later [__init_begin, __init_end) will be freed up as xen heap
alex@15131 436 * so that struct domain might be allocated from the init area
alex@15131 437 * which is < xen_heap_start. so we can't simply set
alex@15131 438 * xen_pickle_offset = xen_heap_start.
alex@15131 439 */
alex@15131 440 xen_pickle_offset = ia64_imva(__init_begin);
djm@6458 441
awilliam@11606 442 xen_heap_start = memguard_init(ia64_imva(&_end));
awilliam@11961 443 printk("Before xen_heap_start: %p\n", xen_heap_start);
awilliam@11606 444 xen_heap_start = __va(init_boot_allocator(__pa(xen_heap_start)));
awilliam@11961 445 printk("After xen_heap_start: %p\n", xen_heap_start);
djm@6458 446
djm@6458 447 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
djm@6458 448 efi_memmap_walk(xen_count_pages, &nr_pages);
djm@6458 449
djm@6458 450 printk("System RAM: %luMB (%lukB)\n",
djm@6458 451 nr_pages >> (20 - PAGE_SHIFT),
djm@6458 452 nr_pages << (PAGE_SHIFT - 10));
awilliam@9773 453 total_pages = nr_pages;
djm@6458 454
djm@6458 455 init_frametable();
djm@6458 456
awilliam@10157 457 trap_init();
awilliam@10157 458
awilliam@11606 459 init_xenheap_pages(__pa(xen_heap_start), xenheap_phys_end);
djm@6458 460 printk("Xen heap: %luMB (%lukB)\n",
awilliam@11606 461 (xenheap_phys_end-__pa(xen_heap_start)) >> 20,
awilliam@11606 462 (xenheap_phys_end-__pa(xen_heap_start)) >> 10);
djm@6458 463
alex@15154 464 end_boot_allocator();
alex@15154 465
kaf24@11019 466 late_setup_arch(&cmdline);
kaf24@11019 467
kaf24@8552 468 scheduler_init();
kaf24@8552 469 idle_vcpu[0] = (struct vcpu*) ia64_r13;
kfraser@14911 470 idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
kfraser@10655 471 if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
kfraser@10655 472 BUG();
kaf24@8552 473
awilliam@10151 474 alloc_dom_xen_and_dom_io();
djm@6458 475 setup_per_cpu_areas();
djm@6458 476 mem_init();
djm@6458 477
djm@6458 478 local_irq_disable();
djm@7332 479 init_IRQ ();
djm@6458 480 init_xen_time(); /* initialise the time */
kaf24@8586 481 timer_init();
djm@6458 482
awilliam@13667 483 rcu_init();
awilliam@13667 484
awilliam@13479 485 #ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
awilliam@13479 486 open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
awilliam@13479 487 #endif
awilliam@13479 488
djm@6458 489 #ifdef CONFIG_SMP
djm@6458 490 if ( opt_nosmp )
djm@6458 491 {
djm@6458 492 max_cpus = 0;
djm@6458 493 smp_num_siblings = 1;
djm@6458 494 //boot_cpu_data.x86_num_cores = 1;
djm@6458 495 }
djm@6458 496
awilliam@9495 497 /* A vcpu is created for the idle domain on every physical cpu.
awilliam@9495 498 Limit the number of cpus to the maximum number of vcpus. */
awilliam@9495 499 if (max_cpus > MAX_VIRT_CPUS)
awilliam@9495 500 max_cpus = MAX_VIRT_CPUS;
awilliam@9495 501
djm@6458 502 smp_prepare_cpus(max_cpus);
awilliam@9495 503
djm@6458 504 /* We aren't hotplug-capable yet. */
djm@6458 505 for_each_cpu ( i )
djm@6458 506 cpu_set(i, cpu_present_map);
djm@6458 507
djm@7332 508 /* Enable IRQ to receive IPI (needed for ITC sync). */
djm@7332 509 local_irq_enable();
djm@7332 510
djm@6458 511 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
djm@6458 512 for_each_present_cpu ( i )
djm@6458 513 {
djm@6458 514 if ( num_online_cpus() >= max_cpus )
djm@6458 515 break;
djm@6458 516 if ( !cpu_online(i) ) {
awilliam@13667 517 rcu_online_cpu(i);
djm@6458 518 __cpu_up(i);
djm@6458 519 }
djm@6458 520 }
djm@6458 521
djm@7332 522 local_irq_disable();
djm@7332 523
djm@6458 524 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
djm@6458 525 smp_cpus_done(max_cpus);
djm@6458 526 #endif
djm@6458 527
kaf24@9117 528 initialise_gdb(); /* could be moved earlier */
kaf24@9117 529
djm@6458 530 do_initcalls();
djm@6458 531 sort_main_extable();
djm@6458 532
awilliam@9685 533 init_rid_allocator ();
awilliam@9685 534
awilliam@10442 535 local_irq_enable();
awilliam@10442 536
awilliam@10442 537 if (opt_xencons) {
awilliam@10445 538 initialize_keytable();
awilliam@10445 539 if (ns16550_com1_gsi) {
awilliam@10445 540 if (opt_xencons_poll ||
awilliam@10445 541 iosapic_register_intr(ns16550_com1_gsi,
awilliam@10445 542 ns16550_com1_polarity,
awilliam@10445 543 ns16550_com1_trigger) < 0) {
awilliam@10445 544 ns16550_com1.irq = 0;
awilliam@10445 545 ns16550_init(0, &ns16550_com1);
awilliam@10445 546 }
awilliam@10445 547 }
awilliam@10445 548 serial_init_postirq();
awilliam@10442 549 }
awilliam@9685 550
awilliam@11726 551 expose_p2m_init();
awilliam@11726 552
djm@6458 553 /* Create initial domain 0. */
kfraser@14911 554 dom0 = domain_create(0, 0, DOM0_SSIDREF);
awilliam@13434 555 if (dom0 == NULL)
djm@6458 556 panic("Error creating domain 0\n");
awilliam@13434 557 dom0_vcpu0 = alloc_vcpu(dom0, 0, 0);
awilliam@13434 558 if (dom0_vcpu0 == NULL || vcpu_late_initialise(dom0_vcpu0) != 0)
awilliam@13434 559 panic("Cannot allocate dom0 vcpu 0\n");
djm@6458 560
kfraser@12210 561 dom0->is_privileged = 1;
djm@6458 562
djm@6458 563 /*
djm@6458 564 * We're going to setup domain0 using the module(s) that we stashed safely
djm@6458 565 * above our heap. The second module, if present, is an initrd ramdisk.
djm@6458 566 */
awilliam@10270 567 dom0_memory_start = (unsigned long) __va(ia64_boot_param->domain_start);
djm@7735 568 dom0_memory_size = ia64_boot_param->domain_size;
awilliam@9864 569 dom0_initrd_start = (unsigned long) __va(ia64_boot_param->initrd_start);
djm@7735 570 dom0_initrd_size = ia64_boot_param->initrd_size;
djm@7735 571
djm@7735 572 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_size,
djm@7735 573 dom0_initrd_start,dom0_initrd_size,
djm@7735 574 0) != 0)
djm@6458 575 panic("Could not set up DOM0 guest OS\n");
djm@7332 576
alex@15135 577 if (!running_on_sim && !IS_MEDUSA()) // slow on ski and pages are pre-initialized to zero
djm@6458 578 scrub_heap_pages();
djm@6458 579
djm@6458 580 init_trace_bufs();
djm@6458 581
awilliam@10934 582 if (opt_xencons) {
awilliam@10513 583 console_endboot();
awilliam@10934 584 serial_endboot();
awilliam@10934 585 }
djm@6458 586
djm@7332 587 domain0_ready = 1;
djm@7332 588
djm@6458 589 domain_unpause_by_systemcontroller(dom0);
djm@7332 590
alex@15131 591 init_done();
djm@6458 592 }
djm@6723 593
ian@13763 594 void arch_get_xen_caps(xen_capabilities_info_t *info)
djm@6723 595 {
kfraser@14997 596 /* Interface name is always xen-3.0-* for Xen-3.x. */
kfraser@14997 597 int major = 3, minor = 0;
keir@13754 598 char s[32];
djm@6723 599
ian@13763 600 (*info)[0] = '\0';
keir@13754 601
ian@13763 602 snprintf(s, sizeof(s), "xen-%d.%d-ia64 ", major, minor);
ian@13763 603 safe_strcat(*info, s);
djm@6723 604
awilliam@14037 605 snprintf(s, sizeof(s), "xen-%d.%d-ia64be ", major, minor);
awilliam@14037 606 safe_strcat(*info, s);
awilliam@14037 607
djm@8475 608 if (vmx_enabled)
keir@13754 609 {
keir@13754 610 snprintf(s, sizeof(s), "hvm-%d.%d-ia64 ", major, minor);
ian@13763 611 safe_strcat(*info, s);
keir@13754 612 }
djm@6723 613 }
djm@6723 614