ia64/xen-unstable

annotate xen/arch/x86/setup.c @ 11296:86d26e6ec89b

Replace dom0_ops hypercall with three new hypercalls:
1. platform_op -- used by dom0 kernel to perform actions on the
hardware platform (e.g., MTRR access, microcode update, platform
quirks, ...)
2. domctl -- used by management tools to control a specified domain
3. sysctl -- used by management tools for system-wide actions

Benefits include more sensible factoring of actions to
hypercalls. Also allows tool compatibility to be tracked separately
from the dom0 kernel. The assumption is that it will be easier to
replace libxenctrl, libxenguest and Xen as a matched set if the
dom0 kernel does not need to be replaced too (e.g., because that
would require vendor revalidation).

From here on we hope to maintain dom0 kernel compatibility. This
promise is not extended to tool compatibility beyond the existing
guarantee that compatibility will not be broken within a three-level
stable release [3.0.2, 3.0.3, etc.].

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Aug 25 18:39:10 2006 +0100 (2006-08-25)
parents 56b05c672033
children 828c0c89d830
rev   line source
kaf24@1452 1
kaf24@1452 2 #include <xen/config.h>
kaf24@1452 3 #include <xen/init.h>
kaf24@1452 4 #include <xen/lib.h>
kaf24@1452 5 #include <xen/sched.h>
cl349@5247 6 #include <xen/domain.h>
kaf24@1452 7 #include <xen/serial.h>
kaf24@1506 8 #include <xen/softirq.h>
kaf24@1452 9 #include <xen/acpi.h>
kaf24@3338 10 #include <xen/console.h>
iap10@4287 11 #include <xen/serial.h>
kaf24@3338 12 #include <xen/trace.h>
kaf24@3338 13 #include <xen/multiboot.h>
kaf24@5356 14 #include <xen/domain_page.h>
kfraser@10890 15 #include <xen/version.h>
kaf24@9117 16 #include <xen/gdbstub.h>
kaf24@9818 17 #include <xen/percpu.h>
kfraser@11296 18 #include <xen/hypercall.h>
iap10@6721 19 #include <public/version.h>
kaf24@1452 20 #include <asm/bitops.h>
kaf24@1452 21 #include <asm/smp.h>
kaf24@1452 22 #include <asm/processor.h>
kaf24@1452 23 #include <asm/mpspec.h>
kaf24@1452 24 #include <asm/apic.h>
kaf24@1452 25 #include <asm/desc.h>
kaf24@3338 26 #include <asm/shadow.h>
kaf24@3344 27 #include <asm/e820.h>
kaf24@5536 28 #include <acm/acm_hooks.h>
kaf24@3338 29
kaf24@5157 30 extern void dmi_scan_machine(void);
kaf24@5211 31 extern void generic_apic_probe(void);
kaf24@5157 32
kaf24@3338 33 /*
kaf24@3338 34 * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
kaf24@8726 35 * page_info table and allocation bitmap.
kaf24@3338 36 */
kaf24@3338 37 static unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
kaf24@4950 38 #if defined(CONFIG_X86_64)
kaf24@3338 39 integer_param("xenheap_megabytes", opt_xenheap_megabytes);
kaf24@3354 40 #endif
kaf24@1452 41
kaf24@5146 42 /* opt_nosmp: If true, secondary processors are ignored. */
kaf24@5900 43 static int opt_nosmp = 0;
kaf24@5146 44 boolean_param("nosmp", opt_nosmp);
kaf24@5146 45
kaf24@5146 46 /* maxcpus: maximum number of CPUs to activate. */
kaf24@5146 47 static unsigned int max_cpus = NR_CPUS;
shand@11156 48 integer_param("maxcpus", max_cpus);
kaf24@5146 49
kaf24@3334 50 /* opt_watchdog: If true, run a watchdog NMI on each processor. */
kaf24@3334 51 static int opt_watchdog = 0;
kaf24@3334 52 boolean_param("watchdog", opt_watchdog);
kaf24@3334 53
kaf24@4850 54 /* **** Linux config option: propagated to domain0. */
kaf24@4850 55 /* "acpi=off": Sisables both ACPI table parsing and interpreter. */
kaf24@4850 56 /* "acpi=force": Override the disable blacklist. */
kaf24@4850 57 /* "acpi=strict": Disables out-of-spec workarounds. */
kaf24@4850 58 /* "acpi=ht": Limit ACPI just to boot-time to enable HT. */
kaf24@4850 59 /* "acpi=noirq": Disables ACPI interrupt routing. */
kaf24@4850 60 static void parse_acpi_param(char *s);
kaf24@4850 61 custom_param("acpi", parse_acpi_param);
kaf24@4850 62
kaf24@4850 63 /* **** Linux config option: propagated to domain0. */
kaf24@4850 64 /* acpi_skip_timer_override: Skip IRQ0 overrides. */
kaf24@4850 65 extern int acpi_skip_timer_override;
kaf24@4850 66 boolean_param("acpi_skip_timer_override", acpi_skip_timer_override);
kaf24@4850 67
kaf24@4850 68 /* **** Linux config option: propagated to domain0. */
kaf24@4850 69 /* noapic: Disable IOAPIC setup. */
kaf24@4850 70 extern int skip_ioapic_setup;
kaf24@4850 71 boolean_param("noapic", skip_ioapic_setup);
kaf24@4850 72
kaf24@3594 73 int early_boot = 1;
kaf24@3594 74
kaf24@5146 75 cpumask_t cpu_present_map;
kaf24@5146 76
kaf24@5003 77 /* Limits of Xen heap, used to initialise the allocator. */
kaf24@5003 78 unsigned long xenheap_phys_start, xenheap_phys_end;
kaf24@3338 79
kaf24@2298 80 extern void arch_init_memory(void);
kaf24@1589 81 extern void init_IRQ(void);
kaf24@1589 82 extern void trap_init(void);
kaf24@5604 83 extern void early_time_init(void);
kaf24@5167 84 extern void initialize_keytable(void);
kaf24@5167 85 extern void early_cpu_init(void);
kaf24@1589 86
kaf24@8533 87 struct tss_struct init_tss[NR_CPUS];
kaf24@8533 88
kaf24@5011 89 extern unsigned long cpu0_stack[];
kaf24@5011 90
kaf24@5214 91 struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
kaf24@1452 92
kaf24@5237 93 #if CONFIG_PAGING_LEVELS > 2
kaf24@1670 94 unsigned long mmu_cr4_features = X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE;
kaf24@1670 95 #else
kaf24@5593 96 unsigned long mmu_cr4_features = X86_CR4_PSE;
kaf24@1670 97 #endif
kaf24@1452 98 EXPORT_SYMBOL(mmu_cr4_features);
kaf24@1452 99
kaf24@4818 100 int acpi_disabled;
kaf24@1452 101
kaf24@4850 102 int acpi_force;
kaf24@4850 103 char acpi_param[10] = "";
kaf24@4850 104 static void parse_acpi_param(char *s)
kaf24@4850 105 {
kaf24@4850 106 /* Save the parameter so it can be propagated to domain0. */
kaf24@4850 107 strncpy(acpi_param, s, sizeof(acpi_param));
kaf24@4850 108 acpi_param[sizeof(acpi_param)-1] = '\0';
kaf24@4850 109
kaf24@4850 110 /* Interpret the parameter for use within Xen. */
kaf24@4850 111 if ( !strcmp(s, "off") )
kaf24@4850 112 {
kaf24@4850 113 disable_acpi();
kaf24@4850 114 }
kaf24@4850 115 else if ( !strcmp(s, "force") )
kaf24@4850 116 {
kaf24@4850 117 acpi_force = 1;
kaf24@4850 118 acpi_ht = 1;
kaf24@4850 119 acpi_disabled = 0;
kaf24@4850 120 }
kaf24@4850 121 else if ( !strcmp(s, "strict") )
kaf24@4850 122 {
kaf24@4850 123 acpi_strict = 1;
kaf24@4850 124 }
kaf24@4850 125 else if ( !strcmp(s, "ht") )
kaf24@4850 126 {
kaf24@4850 127 if ( !acpi_force )
kaf24@4850 128 disable_acpi();
kaf24@4850 129 acpi_ht = 1;
kaf24@4850 130 }
kaf24@4850 131 else if ( !strcmp(s, "noirq") )
kaf24@4850 132 {
kaf24@4850 133 acpi_noirq_set();
kaf24@4850 134 }
kaf24@4850 135 }
kaf24@4850 136
kaf24@1452 137 static void __init do_initcalls(void)
kaf24@1452 138 {
kaf24@1452 139 initcall_t *call;
kaf24@1452 140 for ( call = &__initcall_start; call < &__initcall_end; call++ )
kaf24@1452 141 (*call)();
kaf24@1452 142 }
kaf24@1452 143
kaf24@8459 144 #define EARLY_FAIL() for ( ; ; ) __asm__ __volatile__ ( "hlt" )
kaf24@8459 145
kaf24@8459 146 static struct e820entry e820_raw[E820MAX];
kaf24@8459 147
kaf24@9067 148 static unsigned long initial_images_start, initial_images_end;
kaf24@9067 149
kaf24@9067 150 unsigned long initial_images_nrpages(void)
kaf24@9067 151 {
kaf24@9067 152 unsigned long s = initial_images_start + PAGE_SIZE - 1;
kaf24@9067 153 unsigned long e = initial_images_end;
kaf24@9067 154 return ((e >> PAGE_SHIFT) - (s >> PAGE_SHIFT));
kaf24@9067 155 }
kaf24@9067 156
kaf24@9067 157 void discard_initial_images(void)
kaf24@9067 158 {
kaf24@9067 159 init_domheap_pages(initial_images_start, initial_images_end);
kaf24@9067 160 }
kaf24@9067 161
kaf24@9818 162 extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[];
kaf24@9818 163
kfraser@11241 164 static void __init percpu_init_areas(void)
kaf24@9818 165 {
kaf24@9818 166 unsigned int i, data_size = __per_cpu_data_end - __per_cpu_start;
kaf24@9818 167
kaf24@9818 168 BUG_ON(data_size > PERCPU_SIZE);
kaf24@9818 169
kfraser@11241 170 for_each_cpu ( i )
kfraser@11241 171 {
kfraser@11241 172 memguard_unguard_range(__per_cpu_start + (i << PERCPU_SHIFT),
kfraser@11241 173 1 << PERCPU_SHIFT);
kfraser@11241 174 if ( i != 0 )
kfraser@11241 175 memcpy(__per_cpu_start + (i << PERCPU_SHIFT),
kfraser@11241 176 __per_cpu_start,
kfraser@11241 177 data_size);
kfraser@11241 178 }
kaf24@9818 179 }
kaf24@9818 180
kfraser@11241 181 static void __init percpu_guard_areas(void)
kfraser@11241 182 {
kfraser@11241 183 memguard_guard_range(__per_cpu_start, __per_cpu_end - __per_cpu_start);
kfraser@11241 184 }
kfraser@11241 185
kfraser@11241 186 static void __init percpu_free_unused_areas(void)
kaf24@9818 187 {
kaf24@9818 188 unsigned int i, first_unused;
kaf24@9818 189
kaf24@9818 190 /* Find first unused CPU number. */
kaf24@9818 191 for ( i = 0; i < NR_CPUS; i++ )
kaf24@9818 192 if ( !cpu_online(i) )
kaf24@9818 193 break;
kaf24@9818 194 first_unused = i;
kaf24@9818 195
kaf24@9818 196 /* Check that there are no holes in cpu_online_map. */
kaf24@9818 197 for ( ; i < NR_CPUS; i++ )
kaf24@9818 198 BUG_ON(cpu_online(i));
kaf24@9818 199
kfraser@11241 200 #ifndef MEMORY_GUARD
kaf24@9818 201 init_xenheap_pages(__pa(__per_cpu_start) + (first_unused << PERCPU_SHIFT),
kaf24@9818 202 __pa(__per_cpu_end));
kfraser@11241 203 #endif
kaf24@9818 204 }
kaf24@9818 205
kfraser@11241 206 static void __init init_idle_domain(void)
kfraser@11240 207 {
kfraser@11240 208 struct domain *idle_domain;
kfraser@11240 209
kfraser@11240 210 /* Domain creation requires that scheduler structures are initialised. */
kfraser@11240 211 scheduler_init();
kfraser@11240 212
kfraser@11240 213 idle_domain = domain_create(IDLE_DOMAIN_ID);
kfraser@11240 214 if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
kfraser@11240 215 BUG();
kfraser@11240 216
kfraser@11240 217 set_current(idle_domain->vcpu[0]);
kfraser@11240 218 idle_vcpu[0] = this_cpu(curr_vcpu) = current;
kfraser@11240 219
kfraser@11240 220 setup_idle_pagetable();
kfraser@11240 221 }
kfraser@11240 222
kaf24@8463 223 void __init __start_xen(multiboot_info_t *mbi)
kaf24@1452 224 {
kaf24@9823 225 char __cmdline[] = "", *cmdline = __cmdline;
kaf24@8457 226 unsigned long _initrd_start = 0, _initrd_len = 0;
kaf24@8457 227 unsigned int initrdidx = 1;
kaf24@8457 228 module_t *mod = (module_t *)__va(mbi->mods_addr);
kaf24@6111 229 unsigned long nr_pages, modules_length;
kaf24@8726 230 paddr_t s, e;
kaf24@8402 231 int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0;
kaf24@5776 232 struct ns16550_defaults ns16550 = {
kaf24@5776 233 .data_bits = 8,
kaf24@5776 234 .parity = 'n',
kaf24@5776 235 .stop_bits = 1
kaf24@5776 236 };
kaf24@3338 237
kaf24@3338 238 /* Parse the command-line options. */
kaf24@3344 239 if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
kaf24@9823 240 cmdline = __va(mbi->cmdline);
kaf24@9823 241 cmdline_parse(cmdline);
kaf24@3338 242
kaf24@8534 243 set_current((struct vcpu *)0xfffff000); /* debug sanity */
kfraser@11240 244 idle_vcpu[0] = current;
kaf24@8534 245 set_processor_id(0); /* needed early, for smp_processor_id() */
kaf24@3338 246
kaf24@5146 247 smp_prepare_boot_cpu();
kaf24@5146 248
kaf24@3338 249 /* We initialise the serial devices very early so we can get debugging. */
kaf24@5776 250 ns16550.io_base = 0x3f8;
kaf24@5776 251 ns16550.irq = 4;
kaf24@5776 252 ns16550_init(0, &ns16550);
kaf24@5776 253 ns16550.io_base = 0x2f8;
kaf24@5776 254 ns16550.irq = 3;
kaf24@5776 255 ns16550_init(1, &ns16550);
kaf24@5195 256 serial_init_preirq();
kaf24@3338 257
kaf24@3338 258 init_console();
kaf24@3338 259
kaf24@9823 260 printf("Command line: %s\n", cmdline);
kaf24@9823 261
kaf24@3344 262 /* Check that we have at least one Multiboot module. */
kaf24@3344 263 if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
kaf24@3338 264 {
kaf24@5542 265 printk("FATAL ERROR: dom0 kernel not specified."
kaf24@5542 266 " Check bootloader configuration.\n");
kaf24@5011 267 EARLY_FAIL();
kaf24@5011 268 }
kaf24@5011 269
kaf24@5011 270 if ( ((unsigned long)cpu0_stack & (STACK_SIZE-1)) != 0 )
kaf24@5011 271 {
kaf24@5011 272 printk("FATAL ERROR: Misaligned CPU0 stack.\n");
kaf24@5011 273 EARLY_FAIL();
kaf24@3338 274 }
kaf24@3338 275
kaf24@3338 276 xenheap_phys_end = opt_xenheap_megabytes << 20;
kaf24@3338 277
kaf24@3344 278 if ( mbi->flags & MBI_MEMMAP )
kaf24@3344 279 {
kaf24@3344 280 while ( bytes < mbi->mmap_length )
kaf24@3344 281 {
kaf24@3344 282 memory_map_t *map = __va(mbi->mmap_addr + bytes);
kaf24@8402 283
kaf24@8402 284 /*
kaf24@8403 285 * This is a gross workaround for a BIOS bug. Some bootloaders do
kaf24@8402 286 * not write e820 map entries into pre-zeroed memory. This is
kaf24@8402 287 * okay if the BIOS fills in all fields of the map entry, but
kaf24@8402 288 * some broken BIOSes do not bother to write the high word of
kaf24@8402 289 * the length field if the length is smaller than 4GB. We
kaf24@8402 290 * detect and fix this by flagging sections below 4GB that
kaf24@8403 291 * appear to be larger than 4GB in size.
kaf24@8402 292 */
kaf24@8403 293 if ( (map->base_addr_high == 0) && (map->length_high != 0) )
kaf24@8402 294 {
kaf24@8402 295 e820_warn = 1;
kaf24@8402 296 map->length_high = 0;
kaf24@8402 297 }
kaf24@8402 298
kaf24@3344 299 e820_raw[e820_raw_nr].addr =
kaf24@3344 300 ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;
kaf24@3344 301 e820_raw[e820_raw_nr].size =
kaf24@3344 302 ((u64)map->length_high << 32) | (u64)map->length_low;
kaf24@3344 303 e820_raw[e820_raw_nr].type =
kaf24@3346 304 (map->type > E820_SHARED_PAGE) ? E820_RESERVED : map->type;
kaf24@3344 305 e820_raw_nr++;
kaf24@8402 306
kaf24@3344 307 bytes += map->size + 4;
kaf24@3344 308 }
kaf24@3344 309 }
kaf24@3344 310 else if ( mbi->flags & MBI_MEMLIMITS )
kaf24@3344 311 {
kaf24@3344 312 e820_raw[0].addr = 0;
kaf24@3344 313 e820_raw[0].size = mbi->mem_lower << 10;
kaf24@3344 314 e820_raw[0].type = E820_RAM;
kaf24@3354 315 e820_raw[1].addr = 0x100000;
kaf24@3354 316 e820_raw[1].size = mbi->mem_upper << 10;
kaf24@3354 317 e820_raw[1].type = E820_RAM;
kaf24@3344 318 e820_raw_nr = 2;
kaf24@3344 319 }
kaf24@3344 320 else
kaf24@3344 321 {
kaf24@3344 322 printk("FATAL ERROR: Bootloader provided no memory information.\n");
kaf24@3344 323 for ( ; ; ) ;
kaf24@3344 324 }
kaf24@3344 325
kaf24@8402 326 if ( e820_warn )
kaf24@8402 327 printk("WARNING: Buggy e820 map detected and fixed "
kaf24@8402 328 "(truncated length fields).\n");
kaf24@8402 329
kaf24@4950 330 max_page = init_e820(e820_raw, &e820_raw_nr);
kaf24@3338 331
kaf24@6111 332 modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
kaf24@3338 333
kaf24@6111 334 /* Find a large enough RAM extent to stash the DOM0 modules. */
kaf24@6111 335 for ( i = 0; ; i++ )
kaf24@3338 336 {
kaf24@6111 337 if ( i == e820.nr_map )
kaf24@6111 338 {
kaf24@6111 339 printk("Not enough memory to stash the DOM0 kernel image.\n");
kaf24@6111 340 for ( ; ; ) ;
kaf24@6111 341 }
kaf24@6134 342
kaf24@6134 343 if ( (e820.map[i].type == E820_RAM) &&
kaf24@6134 344 (e820.map[i].size >= modules_length) &&
kaf24@6134 345 ((e820.map[i].addr + e820.map[i].size) >=
kaf24@6134 346 (xenheap_phys_end + modules_length)) )
kaf24@6134 347 break;
kaf24@3338 348 }
kaf24@6111 349
kaf24@6134 350 /* Stash as near as possible to the beginning of the RAM extent. */
kaf24@6134 351 initial_images_start = e820.map[i].addr;
kaf24@6134 352 if ( initial_images_start < xenheap_phys_end )
kaf24@6134 353 initial_images_start = xenheap_phys_end;
kaf24@6134 354 initial_images_end = initial_images_start + modules_length;
kaf24@6134 355
kaf24@4950 356 #if defined(CONFIG_X86_32)
kaf24@3338 357 memmove((void *)initial_images_start, /* use low mapping */
kaf24@3338 358 (void *)mod[0].mod_start, /* use low mapping */
kaf24@3338 359 mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
kaf24@4950 360 #elif defined(CONFIG_X86_64)
kaf24@3338 361 memmove(__va(initial_images_start),
kaf24@3338 362 __va(mod[0].mod_start),
kaf24@3338 363 mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
kaf24@3338 364 #endif
kaf24@3338 365
kaf24@3354 366 /* Initialise boot-time allocator with all RAM situated after modules. */
kaf24@5003 367 xenheap_phys_start = init_boot_allocator(__pa(&_end));
kaf24@6111 368 nr_pages = 0;
kaf24@3354 369 for ( i = 0; i < e820.nr_map; i++ )
kaf24@3354 370 {
kaf24@3354 371 if ( e820.map[i].type != E820_RAM )
kaf24@3354 372 continue;
kaf24@6111 373
kaf24@3354 374 nr_pages += e820.map[i].size >> PAGE_SHIFT;
kaf24@6111 375
kaf24@6111 376 /* Initialise boot heap, skipping Xen heap and dom0 modules. */
kaf24@6111 377 s = e820.map[i].addr;
kaf24@6111 378 e = s + e820.map[i].size;
kaf24@6111 379 if ( s < xenheap_phys_end )
kaf24@6111 380 s = xenheap_phys_end;
kaf24@6111 381 if ( (s < initial_images_end) && (e > initial_images_start) )
kaf24@6111 382 s = initial_images_end;
kaf24@6111 383 init_boot_pages(s, e);
kaf24@6111 384
kaf24@5003 385 #if defined (CONFIG_X86_64)
kaf24@5003 386 /*
kaf24@5003 387 * x86/64 maps all registered RAM. Points to note:
kaf24@9783 388 * 1. The initial pagetable already maps low 1GB, so skip that.
kaf24@5003 389 * 2. We must map *only* RAM areas, taking care to avoid I/O holes.
kaf24@5003 390 * Failure to do this can cause coherency problems and deadlocks
kaf24@5003 391 * due to cache-attribute mismatches (e.g., AMD/AGP Linux bug).
kaf24@5003 392 */
kaf24@5003 393 {
kaf24@5004 394 /* Calculate page-frame range, discarding partial frames. */
kaf24@5004 395 unsigned long start, end;
kaf24@9783 396 unsigned long init_mapped = 1UL << (30 - PAGE_SHIFT); /* 1GB */
kaf24@5005 397 start = PFN_UP(e820.map[i].addr);
kaf24@5005 398 end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
kaf24@9800 399 /* Clip the range to exclude what the bootstrapper initialised. */
kaf24@9783 400 if ( end < init_mapped )
kaf24@5004 401 continue;
kaf24@9783 402 if ( start < init_mapped )
kaf24@9783 403 start = init_mapped;
kaf24@5004 404 /* Request the mapping. */
kaf24@5003 405 map_pages_to_xen(
kaf24@5004 406 PAGE_OFFSET + (start << PAGE_SHIFT),
kaf24@5004 407 start, end-start, PAGE_HYPERVISOR);
kaf24@5003 408 }
kaf24@5003 409 #endif
kaf24@3354 410 }
kaf24@3354 411
kaf24@5003 412 memguard_init();
kfraser@11241 413 percpu_guard_areas();
kaf24@4950 414
kaf24@3354 415 printk("System RAM: %luMB (%lukB)\n",
kaf24@3354 416 nr_pages >> (20 - PAGE_SHIFT),
kaf24@3354 417 nr_pages << (PAGE_SHIFT - 10));
kaf24@7220 418 total_pages = nr_pages;
kaf24@3354 419
kfraser@11296 420 /* Sanity check for unwanted bloat of certain hypercall structures. */
kfraser@11296 421 BUILD_BUG_ON(sizeof(((struct xen_platform_op *)0)->u) !=
kfraser@11296 422 sizeof(((struct xen_platform_op *)0)->u.pad));
kfraser@11296 423 BUILD_BUG_ON(sizeof(((struct xen_domctl *)0)->u) !=
kfraser@11296 424 sizeof(((struct xen_domctl *)0)->u.pad));
kfraser@11296 425 BUILD_BUG_ON(sizeof(((struct xen_sysctl *)0)->u) !=
kfraser@11296 426 sizeof(((struct xen_sysctl *)0)->u.pad));
kaf24@7388 427
kaf24@9878 428 BUILD_BUG_ON(sizeof(start_info_t) > PAGE_SIZE);
kaf24@9878 429 BUILD_BUG_ON(sizeof(shared_info_t) > PAGE_SIZE);
kaf24@9878 430 BUILD_BUG_ON(sizeof(vcpu_info_t) != 64);
kaf24@7744 431
kfraser@10492 432 /* Check definitions in public headers match internal defs. */
kaf24@9878 433 BUILD_BUG_ON(__HYPERVISOR_VIRT_START != HYPERVISOR_VIRT_START);
kaf24@8521 434 #ifdef HYPERVISOR_VIRT_END
kaf24@9878 435 BUILD_BUG_ON(__HYPERVISOR_VIRT_END != HYPERVISOR_VIRT_END);
kaf24@8521 436 #endif
kfraser@10492 437 BUILD_BUG_ON(MACH2PHYS_VIRT_START != RO_MPT_VIRT_START);
kfraser@10492 438 BUILD_BUG_ON(MACH2PHYS_VIRT_END != RO_MPT_VIRT_END);
kaf24@8521 439
kaf24@3354 440 init_frametable();
kaf24@3338 441
kaf24@3354 442 end_boot_allocator();
kaf24@3354 443
kaf24@6111 444 /* Initialise the Xen heap, skipping RAM holes. */
kaf24@6111 445 nr_pages = 0;
kaf24@6111 446 for ( i = 0; i < e820.nr_map; i++ )
kaf24@6111 447 {
kaf24@6111 448 if ( e820.map[i].type != E820_RAM )
kaf24@6111 449 continue;
kaf24@6111 450
kaf24@6111 451 s = e820.map[i].addr;
kaf24@6111 452 e = s + e820.map[i].size;
kaf24@6111 453 if ( s < xenheap_phys_start )
kaf24@6111 454 s = xenheap_phys_start;
kaf24@6111 455 if ( e > xenheap_phys_end )
kaf24@6111 456 e = xenheap_phys_end;
kaf24@6111 457
kaf24@6111 458 if ( s < e )
kaf24@6111 459 {
kaf24@6111 460 nr_pages += (e - s) >> PAGE_SHIFT;
kaf24@6111 461 init_xenheap_pages(s, e);
kaf24@6111 462 }
kaf24@6111 463 }
kaf24@6111 464
kaf24@6111 465 printk("Xen heap: %luMB (%lukB)\n",
kaf24@6111 466 nr_pages >> (20 - PAGE_SHIFT),
kaf24@6111 467 nr_pages << (PAGE_SHIFT - 10));
kaf24@3338 468
kaf24@3594 469 early_boot = 0;
kaf24@3338 470
kaf24@8459 471 early_cpu_init();
kaf24@8459 472
kaf24@8459 473 paging_init();
kaf24@8459 474
kaf24@8459 475 /* Unmap the first page of CPU0's stack. */
kaf24@8459 476 memguard_guard_stack(cpu0_stack);
kaf24@8459 477
kaf24@8459 478 open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
kaf24@8459 479
kaf24@8459 480 if ( opt_watchdog )
kaf24@8459 481 nmi_watchdog = NMI_LOCAL_APIC;
kaf24@8459 482
kaf24@8459 483 sort_exception_tables();
kaf24@8459 484
kaf24@8459 485 find_smp_config();
kaf24@8459 486
kaf24@8459 487 smp_alloc_memory();
kaf24@8459 488
kaf24@8459 489 dmi_scan_machine();
kaf24@8459 490
kaf24@8459 491 generic_apic_probe();
kaf24@8459 492
kaf24@8459 493 acpi_boot_table_init();
kaf24@8459 494 acpi_boot_init();
kaf24@8459 495
kfraser@11241 496 if ( smp_found_config )
kaf24@8459 497 get_smp_config();
kaf24@8459 498
kaf24@8459 499 init_apic_mappings();
kaf24@8459 500
kaf24@8459 501 init_IRQ();
kaf24@8459 502
kfraser@11241 503 percpu_init_areas();
kfraser@11241 504
kfraser@11240 505 init_idle_domain();
kfraser@11240 506
kaf24@8459 507 trap_init();
kaf24@8459 508
kaf24@8586 509 timer_init();
kaf24@8459 510
kaf24@8459 511 early_time_init();
kaf24@8459 512
kaf24@8459 513 arch_init_memory();
kaf24@8459 514
kaf24@8459 515 identify_cpu(&boot_cpu_data);
kaf24@8459 516 if ( cpu_has_fxsr )
kaf24@8459 517 set_in_cr4(X86_CR4_OSFXSR);
kaf24@8459 518 if ( cpu_has_xmm )
kaf24@8459 519 set_in_cr4(X86_CR4_OSXMMEXCPT);
kaf24@8459 520
kaf24@8459 521 if ( opt_nosmp )
kaf24@8459 522 max_cpus = 0;
kaf24@8459 523
kaf24@8459 524 smp_prepare_cpus(max_cpus);
kaf24@8459 525
kaf24@8459 526 /*
kaf24@8459 527 * Initialise higher-level timer functions. We do this fairly late
kaf24@8459 528 * (post-SMP) because the time bases and scale factors need to be updated
kaf24@8459 529 * regularly, and SMP initialisation can cause a long delay with
kaf24@8459 530 * interrupts not yet enabled.
kaf24@8459 531 */
kaf24@8459 532 init_xen_time();
kaf24@8459 533
kaf24@8459 534 initialize_keytable();
kaf24@8459 535
kaf24@8459 536 serial_init_postirq();
kaf24@8459 537
kaf24@8459 538 BUG_ON(!local_irq_is_enabled());
kaf24@8459 539
kaf24@8459 540 for_each_present_cpu ( i )
kaf24@8459 541 {
kaf24@8459 542 if ( num_online_cpus() >= max_cpus )
kaf24@8459 543 break;
kaf24@8459 544 if ( !cpu_online(i) )
kaf24@8459 545 __cpu_up(i);
kaf24@8459 546 }
kaf24@8459 547
kaf24@8459 548 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
kaf24@8459 549 smp_cpus_done(max_cpus);
kaf24@8459 550
kaf24@9818 551 percpu_free_unused_areas();
kaf24@9818 552
kaf24@9117 553 initialise_gdb(); /* could be moved earlier */
kaf24@9117 554
kaf24@8459 555 do_initcalls();
kaf24@8459 556
kaf24@8459 557 schedulers_start();
kaf24@8459 558
kaf24@8594 559 if ( opt_watchdog )
kaf24@8594 560 watchdog_enable();
kaf24@8459 561
kaf24@8459 562 /* initialize access control security module */
kaf24@8459 563 acm_init(&initrdidx, mbi, initial_images_start);
kaf24@8459 564
kaf24@8459 565 /* Create initial domain 0. */
kfraser@10655 566 dom0 = domain_create(0);
kfraser@10655 567 if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
kaf24@8459 568 panic("Error creating domain 0\n");
kaf24@8459 569
kaf24@8459 570 set_bit(_DOMF_privileged, &dom0->domain_flags);
kaf24@8459 571 /* post-create hooks sets security label */
kaf24@8459 572 acm_post_domain0_create(dom0->domain_id);
kaf24@8459 573
kaf24@8459 574 /* Grab the DOM0 command line. */
kaf24@8459 575 cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
kaf24@8459 576 if ( cmdline != NULL )
kaf24@8459 577 {
kaf24@8459 578 static char dom0_cmdline[MAX_GUEST_CMDLINE];
kaf24@8459 579
kaf24@8459 580 /* Skip past the image name and copy to a local buffer. */
kaf24@8459 581 while ( *cmdline == ' ' ) cmdline++;
kaf24@8459 582 if ( (cmdline = strchr(cmdline, ' ')) != NULL )
kaf24@8459 583 {
kaf24@8459 584 while ( *cmdline == ' ' ) cmdline++;
kaf24@8459 585 strcpy(dom0_cmdline, cmdline);
kaf24@8459 586 }
kaf24@8459 587
kaf24@8459 588 cmdline = dom0_cmdline;
kaf24@8459 589
kaf24@8459 590 /* Append any extra parameters. */
kaf24@8459 591 if ( skip_ioapic_setup && !strstr(cmdline, "noapic") )
kaf24@8459 592 strcat(cmdline, " noapic");
kaf24@8459 593 if ( acpi_skip_timer_override &&
kaf24@8459 594 !strstr(cmdline, "acpi_skip_timer_override") )
kaf24@8459 595 strcat(cmdline, " acpi_skip_timer_override");
kaf24@8459 596 if ( (strlen(acpi_param) != 0) && !strstr(cmdline, "acpi=") )
kaf24@8459 597 {
kaf24@8459 598 strcat(cmdline, " acpi=");
kaf24@8459 599 strcat(cmdline, acpi_param);
kaf24@8459 600 }
kaf24@8459 601 }
kaf24@8459 602
kaf24@8459 603 if ( (initrdidx > 0) && (initrdidx < mbi->mods_count) )
kaf24@8459 604 {
kaf24@8459 605 _initrd_start = initial_images_start +
kaf24@8459 606 (mod[initrdidx].mod_start - mod[0].mod_start);
kaf24@8459 607 _initrd_len = mod[initrdidx].mod_end - mod[initrdidx].mod_start;
kaf24@8459 608 }
kaf24@8459 609
kaf24@8459 610 /*
kaf24@8459 611 * We're going to setup domain0 using the module(s) that we stashed safely
kaf24@8459 612 * above our heap. The second module, if present, is an initrd ramdisk.
kaf24@8459 613 */
kaf24@8459 614 if ( construct_dom0(dom0,
kaf24@8459 615 initial_images_start,
kaf24@8459 616 mod[0].mod_end-mod[0].mod_start,
kaf24@8459 617 _initrd_start,
kaf24@8459 618 _initrd_len,
kaf24@8459 619 cmdline) != 0)
kaf24@8459 620 panic("Could not set up DOM0 guest OS\n");
kaf24@8459 621
kaf24@8459 622 /* Scrub RAM that is still free and so may go to an unprivileged domain. */
kaf24@8459 623 scrub_heap_pages();
kaf24@8459 624
kaf24@8459 625 init_trace_bufs();
kaf24@8459 626
kaf24@10502 627 console_endboot();
kaf24@8459 628
kaf24@8459 629 /* Hide UART from DOM0 if we're using it */
kaf24@8459 630 serial_endboot();
kaf24@8459 631
kaf24@8459 632 domain_unpause_by_systemcontroller(dom0);
kaf24@8459 633
kaf24@8459 634 startup_cpu_idle_loop();
kaf24@8459 635 }
kaf24@8459 636
kaf24@6725 637 void arch_get_xen_caps(xen_capabilities_info_t info)
iap10@6721 638 {
kaf24@6725 639 char *p = info;
kfraser@10890 640 int major = xen_major_version();
kfraser@10890 641 int minor = xen_minor_version();
iap10@6721 642
kaf24@6725 643 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
kaf24@6725 644
kfraser@10890 645 p += sprintf(p, "xen-%d.%d-x86_32 ", major, minor);
kaf24@6725 646 if ( hvm_enabled )
kfraser@10890 647 p += sprintf(p, "hvm-%d.%d-x86_32 ", major, minor);
kaf24@6725 648
kaf24@6725 649 #elif defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE)
kaf24@6725 650
kfraser@10890 651 p += sprintf(p, "xen-%d.%d-x86_32p ", major, minor);
kaf24@6725 652 if ( hvm_enabled )
iap10@6721 653 {
kfraser@10890 654 p += sprintf(p, "hvm-%d.%d-x86_32 ", major, minor);
kfraser@10890 655 p += sprintf(p, "hvm-%d.%d-x86_32p ", major, minor);
iap10@6721 656 }
iap10@6721 657
kaf24@6725 658 #elif defined(CONFIG_X86_64)
iap10@6721 659
kfraser@10890 660 p += sprintf(p, "xen-%d.%d-x86_64 ", major, minor);
kaf24@6725 661 if ( hvm_enabled )
iap10@6721 662 {
kfraser@10890 663 p += sprintf(p, "hvm-%d.%d-x86_32 ", major, minor);
kfraser@10890 664 p += sprintf(p, "hvm-%d.%d-x86_32p ", major, minor);
kfraser@10890 665 p += sprintf(p, "hvm-%d.%d-x86_64 ", major, minor);
iap10@6721 666 }
kaf24@6725 667
kaf24@6725 668 #else
kaf24@6725 669
kaf24@6725 670 p++;
kaf24@6725 671
iap10@6721 672 #endif
kaf24@8246 673
kaf24@6725 674 *(p-1) = 0;
iap10@6721 675
shand@6734 676 BUG_ON((p - info) > sizeof(xen_capabilities_info_t));
iap10@6721 677 }
iap10@6721 678
kaf24@3914 679 /*
kaf24@3914 680 * Local variables:
kaf24@3914 681 * mode: C
kaf24@3914 682 * c-set-style: "BSD"
kaf24@3914 683 * c-basic-offset: 4
kaf24@3914 684 * tab-width: 4
kaf24@3914 685 * indent-tabs-mode: nil
kaf24@3988 686 * End:
kaf24@3914 687 */