ia64/xen-unstable

annotate xen/arch/x86/setup.c @ 15426:799b3e4bfeac

kernel command line extension

In order to allow appending to the dom0 command line even with boot
loaders that only allow editing the kernel (i.e. Xen in our case)
command line, support a '--' separator option.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Jun 20 16:52:01 2007 +0100 (2007-06-20)
parents 499bab040137
children 296fd2598e00
rev   line source
kaf24@1452 1 #include <xen/config.h>
kaf24@1452 2 #include <xen/init.h>
kaf24@1452 3 #include <xen/lib.h>
kaf24@1452 4 #include <xen/sched.h>
cl349@5247 5 #include <xen/domain.h>
kaf24@1452 6 #include <xen/serial.h>
kaf24@1506 7 #include <xen/softirq.h>
kaf24@1452 8 #include <xen/acpi.h>
kaf24@3338 9 #include <xen/console.h>
iap10@4287 10 #include <xen/serial.h>
kaf24@3338 11 #include <xen/trace.h>
kaf24@3338 12 #include <xen/multiboot.h>
kaf24@5356 13 #include <xen/domain_page.h>
kfraser@10890 14 #include <xen/version.h>
kaf24@9117 15 #include <xen/gdbstub.h>
kaf24@9818 16 #include <xen/percpu.h>
kfraser@11296 17 #include <xen/hypercall.h>
kfraser@11601 18 #include <xen/keyhandler.h>
kfraser@11971 19 #include <xen/numa.h>
kaf24@13662 20 #include <xen/rcupdate.h>
keir@15298 21 #include <xen/vga.h>
iap10@6721 22 #include <public/version.h>
ack@13291 23 #ifdef CONFIG_COMPAT
ack@13291 24 #include <compat/platform.h>
ack@13291 25 #include <compat/xen.h>
ack@13291 26 #endif
kaf24@1452 27 #include <asm/bitops.h>
kaf24@1452 28 #include <asm/smp.h>
kaf24@1452 29 #include <asm/processor.h>
kaf24@1452 30 #include <asm/mpspec.h>
kaf24@1452 31 #include <asm/apic.h>
kaf24@1452 32 #include <asm/desc.h>
Tim@13909 33 #include <asm/paging.h>
kaf24@3344 34 #include <asm/e820.h>
kaf24@5536 35 #include <acm/acm_hooks.h>
ian@12677 36 #include <xen/kexec.h>
kfraser@15336 37 #include <asm/edd.h>
kaf24@3338 38
kfraser@15074 39 #if defined(CONFIG_X86_64)
kfraser@15074 40 #define BOOTSTRAP_DIRECTMAP_END (1UL << 32)
kfraser@15074 41 #define maddr_to_bootstrap_virt(m) maddr_to_virt(m)
kfraser@15074 42 #else
kfraser@15074 43 #define BOOTSTRAP_DIRECTMAP_END HYPERVISOR_VIRT_START
kfraser@15074 44 #define maddr_to_bootstrap_virt(m) ((void *)(long)(m))
kfraser@15074 45 #endif
kfraser@15074 46
kaf24@5157 47 extern void dmi_scan_machine(void);
kaf24@5211 48 extern void generic_apic_probe(void);
kfraser@11971 49 extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn);
kaf24@5157 50
kfraser@15330 51 extern u16 boot_edid_caps;
kfraser@15330 52 extern u8 boot_edid_info[128];
kfraser@15330 53 extern struct boot_video_info boot_vid_info;
kfraser@15330 54
kaf24@3338 55 /*
kaf24@3338 56 * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the
kaf24@8726 57 * page_info table and allocation bitmap.
kaf24@3338 58 */
kaf24@3338 59 static unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
kaf24@4950 60 #if defined(CONFIG_X86_64)
kaf24@3338 61 integer_param("xenheap_megabytes", opt_xenheap_megabytes);
kaf24@3354 62 #endif
kaf24@1452 63
kaf24@5146 64 /* opt_nosmp: If true, secondary processors are ignored. */
kaf24@5900 65 static int opt_nosmp = 0;
kaf24@5146 66 boolean_param("nosmp", opt_nosmp);
kaf24@5146 67
kaf24@5146 68 /* maxcpus: maximum number of CPUs to activate. */
kaf24@5146 69 static unsigned int max_cpus = NR_CPUS;
shand@11156 70 integer_param("maxcpus", max_cpus);
kaf24@5146 71
kaf24@3334 72 /* opt_watchdog: If true, run a watchdog NMI on each processor. */
kaf24@3334 73 static int opt_watchdog = 0;
kaf24@3334 74 boolean_param("watchdog", opt_watchdog);
kaf24@3334 75
kaf24@4850 76 /* **** Linux config option: propagated to domain0. */
kaf24@4850 77 /* "acpi=off": Sisables both ACPI table parsing and interpreter. */
kaf24@4850 78 /* "acpi=force": Override the disable blacklist. */
kaf24@4850 79 /* "acpi=strict": Disables out-of-spec workarounds. */
kaf24@4850 80 /* "acpi=ht": Limit ACPI just to boot-time to enable HT. */
kaf24@4850 81 /* "acpi=noirq": Disables ACPI interrupt routing. */
kaf24@4850 82 static void parse_acpi_param(char *s);
kaf24@4850 83 custom_param("acpi", parse_acpi_param);
kaf24@4850 84
kaf24@4850 85 /* **** Linux config option: propagated to domain0. */
kaf24@4850 86 /* acpi_skip_timer_override: Skip IRQ0 overrides. */
kaf24@4850 87 extern int acpi_skip_timer_override;
kaf24@4850 88 boolean_param("acpi_skip_timer_override", acpi_skip_timer_override);
kaf24@4850 89
kaf24@4850 90 /* **** Linux config option: propagated to domain0. */
kaf24@4850 91 /* noapic: Disable IOAPIC setup. */
kaf24@4850 92 extern int skip_ioapic_setup;
kaf24@4850 93 boolean_param("noapic", skip_ioapic_setup);
kaf24@4850 94
kaf24@3594 95 int early_boot = 1;
kaf24@3594 96
kaf24@5146 97 cpumask_t cpu_present_map;
kaf24@5146 98
kfraser@15074 99 unsigned long xen_phys_start;
kfraser@15074 100
kaf24@5003 101 /* Limits of Xen heap, used to initialise the allocator. */
kaf24@5003 102 unsigned long xenheap_phys_start, xenheap_phys_end;
kaf24@3338 103
kaf24@2298 104 extern void arch_init_memory(void);
kaf24@1589 105 extern void init_IRQ(void);
kaf24@1589 106 extern void trap_init(void);
kaf24@5604 107 extern void early_time_init(void);
kaf24@5167 108 extern void early_cpu_init(void);
kaf24@1589 109
kaf24@8533 110 struct tss_struct init_tss[NR_CPUS];
kaf24@8533 111
kfraser@15074 112 char __attribute__ ((__section__(".bss.page_aligned"))) cpu0_stack[STACK_SIZE];
kaf24@5011 113
kaf24@5214 114 struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
kaf24@1452 115
kaf24@5237 116 #if CONFIG_PAGING_LEVELS > 2
kaf24@1670 117 unsigned long mmu_cr4_features = X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE;
kaf24@1670 118 #else
kaf24@5593 119 unsigned long mmu_cr4_features = X86_CR4_PSE;
kaf24@1670 120 #endif
kaf24@1452 121 EXPORT_SYMBOL(mmu_cr4_features);
kaf24@1452 122
kaf24@4818 123 int acpi_disabled;
kaf24@1452 124
kaf24@4850 125 int acpi_force;
kaf24@4850 126 char acpi_param[10] = "";
kfraser@15074 127 static void __init parse_acpi_param(char *s)
kaf24@4850 128 {
kaf24@4850 129 /* Save the parameter so it can be propagated to domain0. */
kfraser@13689 130 safe_strcpy(acpi_param, s);
kaf24@4850 131
kaf24@4850 132 /* Interpret the parameter for use within Xen. */
kaf24@4850 133 if ( !strcmp(s, "off") )
kaf24@4850 134 {
kaf24@4850 135 disable_acpi();
kaf24@4850 136 }
kaf24@4850 137 else if ( !strcmp(s, "force") )
kaf24@4850 138 {
kaf24@4850 139 acpi_force = 1;
kaf24@4850 140 acpi_ht = 1;
kaf24@4850 141 acpi_disabled = 0;
kaf24@4850 142 }
kaf24@4850 143 else if ( !strcmp(s, "strict") )
kaf24@4850 144 {
kaf24@4850 145 acpi_strict = 1;
kaf24@4850 146 }
kaf24@4850 147 else if ( !strcmp(s, "ht") )
kaf24@4850 148 {
kaf24@4850 149 if ( !acpi_force )
kaf24@4850 150 disable_acpi();
kaf24@4850 151 acpi_ht = 1;
kaf24@4850 152 }
kaf24@4850 153 else if ( !strcmp(s, "noirq") )
kaf24@4850 154 {
kaf24@4850 155 acpi_noirq_set();
kaf24@4850 156 }
kaf24@4850 157 }
kaf24@4850 158
kaf24@1452 159 static void __init do_initcalls(void)
kaf24@1452 160 {
kaf24@1452 161 initcall_t *call;
kaf24@1452 162 for ( call = &__initcall_start; call < &__initcall_end; call++ )
kaf24@1452 163 (*call)();
kaf24@1452 164 }
kaf24@1452 165
kfraser@15074 166 #define EARLY_FAIL(f, a...) do { \
kfraser@15074 167 printk( f , ## a ); \
kfraser@15074 168 for ( ; ; ) __asm__ __volatile__ ( "hlt" ); \
kfraser@15074 169 } while (0)
kaf24@8459 170
kfraser@15074 171 static unsigned long __initdata initial_images_start, initial_images_end;
kaf24@9067 172
kfraser@15074 173 unsigned long __init initial_images_nrpages(void)
kaf24@9067 174 {
kaf24@9067 175 unsigned long s = initial_images_start + PAGE_SIZE - 1;
kaf24@9067 176 unsigned long e = initial_images_end;
kaf24@9067 177 return ((e >> PAGE_SHIFT) - (s >> PAGE_SHIFT));
kaf24@9067 178 }
kaf24@9067 179
kfraser@15074 180 void __init discard_initial_images(void)
kaf24@9067 181 {
kaf24@9067 182 init_domheap_pages(initial_images_start, initial_images_end);
kaf24@9067 183 }
kaf24@9067 184
kaf24@9818 185 extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[];
kaf24@9818 186
kfraser@11241 187 static void __init percpu_init_areas(void)
kaf24@9818 188 {
kaf24@9818 189 unsigned int i, data_size = __per_cpu_data_end - __per_cpu_start;
kfraser@15074 190 unsigned int first_unused;
kaf24@9818 191
kaf24@9818 192 BUG_ON(data_size > PERCPU_SIZE);
kaf24@9818 193
kfraser@15074 194 /* Initialise per-cpu data area for all possible secondary CPUs. */
kfraser@15074 195 for ( i = 1; (i < NR_CPUS) && cpu_possible(i); i++ )
kfraser@15074 196 memcpy(__per_cpu_start + (i << PERCPU_SHIFT),
kfraser@15074 197 __per_cpu_start,
kfraser@15074 198 data_size);
kaf24@9818 199 first_unused = i;
kaf24@9818 200
kfraser@14340 201 /* Check that there are no holes in cpu_possible_map. */
kaf24@9818 202 for ( ; i < NR_CPUS; i++ )
kfraser@14340 203 BUG_ON(cpu_possible(i));
kaf24@9818 204
kfraser@11241 205 #ifndef MEMORY_GUARD
kaf24@9818 206 init_xenheap_pages(__pa(__per_cpu_start) + (first_unused << PERCPU_SHIFT),
kaf24@9818 207 __pa(__per_cpu_end));
kfraser@11241 208 #endif
keir@15082 209 memguard_guard_range(&__per_cpu_start[first_unused << PERCPU_SHIFT],
keir@15082 210 (NR_CPUS - first_unused) << PERCPU_SHIFT);
keir@15082 211 #if defined(CONFIG_X86_64)
keir@15082 212 /* Also zap the mapping in the 1:1 area. */
keir@15082 213 memguard_guard_range(__va(__pa(__per_cpu_start)) +
keir@15082 214 (first_unused << PERCPU_SHIFT),
keir@15082 215 (NR_CPUS - first_unused) << PERCPU_SHIFT);
keir@15082 216 #endif
kaf24@9818 217 }
kaf24@9818 218
kfraser@11881 219 /* Fetch acm policy module from multiboot modules. */
kfraser@15074 220 static void __init extract_acm_policy(
kfraser@11881 221 multiboot_info_t *mbi,
kfraser@11881 222 unsigned int *initrdidx,
kfraser@11881 223 char **_policy_start,
kfraser@11881 224 unsigned long *_policy_len)
kfraser@11881 225 {
kfraser@11881 226 int i;
kfraser@11881 227 module_t *mod = (module_t *)__va(mbi->mods_addr);
kfraser@11881 228 unsigned long start, policy_len;
kfraser@11881 229 char *policy_start;
kfraser@11881 230
kfraser@11881 231 /*
kfraser@11881 232 * Try all modules and see whichever could be the binary policy.
kfraser@11881 233 * Adjust the initrdidx if module[1] is the binary policy.
kfraser@11881 234 */
kfraser@11881 235 for ( i = mbi->mods_count-1; i >= 1; i-- )
kfraser@11881 236 {
kfraser@11881 237 start = initial_images_start + (mod[i].mod_start-mod[0].mod_start);
kfraser@15074 238 policy_start = maddr_to_bootstrap_virt(start);
kfraser@11881 239 policy_len = mod[i].mod_end - mod[i].mod_start;
kfraser@11881 240 if ( acm_is_policy(policy_start, policy_len) )
kfraser@11881 241 {
kfraser@11881 242 printk("Policy len 0x%lx, start at %p - module %d.\n",
kfraser@11881 243 policy_len, policy_start, i);
kfraser@11881 244 *_policy_start = policy_start;
kfraser@11881 245 *_policy_len = policy_len;
kfraser@11881 246 if ( i == 1 )
kfraser@11881 247 *initrdidx = (mbi->mods_count > 2) ? 2 : 0;
kfraser@11881 248 break;
kfraser@11881 249 }
kfraser@11881 250 }
kfraser@11881 251 }
kfraser@11881 252
kfraser@11241 253 static void __init init_idle_domain(void)
kfraser@11240 254 {
kfraser@11240 255 struct domain *idle_domain;
kfraser@11240 256
kfraser@11240 257 /* Domain creation requires that scheduler structures are initialised. */
kfraser@11240 258 scheduler_init();
kfraser@11240 259
kfraser@14911 260 idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
kfraser@11240 261 if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
kfraser@11240 262 BUG();
kfraser@11240 263
kfraser@11240 264 set_current(idle_domain->vcpu[0]);
kfraser@11240 265 idle_vcpu[0] = this_cpu(curr_vcpu) = current;
kfraser@11240 266
kfraser@11240 267 setup_idle_pagetable();
kfraser@11240 268 }
kfraser@11240 269
kfraser@15074 270 static void __init srat_detect_node(int cpu)
kfraser@11971 271 {
kfraser@11998 272 unsigned node;
kfraser@11998 273 u8 apicid = x86_cpu_to_apicid[cpu];
kfraser@11971 274
kfraser@11998 275 node = apicid_to_node[apicid];
kfraser@11998 276 if ( node == NUMA_NO_NODE )
kfraser@11998 277 node = 0;
kfraser@11998 278 numa_set_node(cpu, node);
kfraser@11971 279
kfraser@11998 280 if ( acpi_numa > 0 )
kfraser@11998 281 printk(KERN_INFO "CPU %d APIC %d -> Node %d\n", cpu, apicid, node);
kfraser@11971 282 }
kfraser@11971 283
kfraser@15074 284 static void __init move_memory(
kfraser@15074 285 unsigned long dst, unsigned long src_start, unsigned long src_end)
ian@12677 286 {
kfraser@15074 287 memmove(maddr_to_bootstrap_virt(dst),
kfraser@15074 288 maddr_to_bootstrap_virt(src_start),
ian@12677 289 src_end - src_start);
kfraser@15074 290 }
kfraser@15074 291
kfraser@15074 292 /* A temporary copy of the e820 map that we can mess with during bootstrap. */
kfraser@15074 293 static struct e820map __initdata boot_e820;
kfraser@15074 294
kfraser@15074 295 /* Reserve area (@s,@e) in the temporary bootstrap e820 map. */
kfraser@15074 296 static void __init reserve_in_boot_e820(unsigned long s, unsigned long e)
kfraser@15074 297 {
kfraser@15403 298 uint64_t rs, re;
kfraser@15074 299 int i;
kfraser@15074 300
kfraser@15074 301 for ( i = 0; i < boot_e820.nr_map; i++ )
kfraser@15074 302 {
kfraser@15074 303 /* Have we found the e820 region that includes the specified range? */
kfraser@15074 304 rs = boot_e820.map[i].addr;
kfraser@15403 305 re = rs + boot_e820.map[i].size;
kfraser@15074 306 if ( (s < rs) || (e > re) )
kfraser@15074 307 continue;
kfraser@15074 308
kfraser@15074 309 /* Start fragment. */
kfraser@15074 310 boot_e820.map[i].size = s - rs;
kfraser@15074 311
kfraser@15074 312 /* End fragment. */
kfraser@15074 313 if ( e < re )
kfraser@15074 314 {
kfraser@15074 315 memmove(&boot_e820.map[i+1], &boot_e820.map[i],
kfraser@15074 316 (boot_e820.nr_map-i) * sizeof(boot_e820.map[0]));
kfraser@15074 317 boot_e820.nr_map++;
kfraser@15074 318 i++;
kfraser@15074 319 boot_e820.map[i].addr = e;
kfraser@15074 320 boot_e820.map[i].size = re - e;
kfraser@15074 321 }
kfraser@15074 322 }
ian@12677 323 }
ian@12677 324
keir@15298 325 struct boot_video_info {
keir@15298 326 u8 orig_x; /* 0x00 */
keir@15298 327 u8 orig_y; /* 0x01 */
keir@15298 328 u8 orig_video_mode; /* 0x02 */
keir@15298 329 u8 orig_video_cols; /* 0x03 */
keir@15298 330 u8 orig_video_lines; /* 0x04 */
keir@15298 331 u8 orig_video_isVGA; /* 0x05 */
keir@15298 332 u16 orig_video_points; /* 0x06 */
keir@15298 333
keir@15298 334 /* VESA graphic mode -- linear frame buffer */
keir@15298 335 u32 capabilities; /* 0x08 */
keir@15298 336 u16 lfb_linelength; /* 0x0c */
keir@15298 337 u16 lfb_width; /* 0x0e */
keir@15298 338 u16 lfb_height; /* 0x10 */
keir@15298 339 u16 lfb_depth; /* 0x12 */
keir@15298 340 u32 lfb_base; /* 0x14 */
keir@15298 341 u32 lfb_size; /* 0x18 */
keir@15298 342 u8 red_size; /* 0x1c */
keir@15298 343 u8 red_pos; /* 0x1d */
keir@15298 344 u8 green_size; /* 0x1e */
keir@15298 345 u8 green_pos; /* 0x1f */
keir@15298 346 u8 blue_size; /* 0x20 */
keir@15298 347 u8 blue_pos; /* 0x21 */
keir@15298 348 u8 rsvd_size; /* 0x22 */
keir@15298 349 u8 rsvd_pos; /* 0x23 */
keir@15298 350 u16 vesapm_seg; /* 0x24 */
keir@15298 351 u16 vesapm_off; /* 0x26 */
keir@15298 352 };
keir@15298 353
keir@15298 354 static void __init parse_video_info(void)
keir@15298 355 {
keir@15298 356 struct boot_video_info *bvi = &bootsym(boot_vid_info);
keir@15298 357
keir@15298 358 if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) )
keir@15298 359 {
keir@15298 360 vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
keir@15298 361 vga_console_info.u.text_mode_3.font_height = bvi->orig_video_points;
keir@15298 362 vga_console_info.u.text_mode_3.cursor_x = bvi->orig_x;
keir@15298 363 vga_console_info.u.text_mode_3.cursor_y = bvi->orig_y;
keir@15298 364 vga_console_info.u.text_mode_3.rows = bvi->orig_video_lines;
keir@15298 365 vga_console_info.u.text_mode_3.columns = bvi->orig_video_cols;
keir@15298 366 }
keir@15298 367 else if ( bvi->orig_video_isVGA == 0x23 )
keir@15298 368 {
keir@15298 369 vga_console_info.video_type = XEN_VGATYPE_VESA_LFB;
keir@15298 370 vga_console_info.u.vesa_lfb.width = bvi->lfb_width;
keir@15298 371 vga_console_info.u.vesa_lfb.height = bvi->lfb_height;
keir@15298 372 vga_console_info.u.vesa_lfb.bytes_per_line = bvi->lfb_linelength;
keir@15298 373 vga_console_info.u.vesa_lfb.bits_per_pixel = bvi->lfb_depth;
keir@15298 374 vga_console_info.u.vesa_lfb.lfb_base = bvi->lfb_base;
keir@15298 375 vga_console_info.u.vesa_lfb.lfb_size = bvi->lfb_size;
keir@15298 376 vga_console_info.u.vesa_lfb.red_pos = bvi->red_pos;
keir@15298 377 vga_console_info.u.vesa_lfb.red_size = bvi->red_size;
keir@15298 378 vga_console_info.u.vesa_lfb.green_pos = bvi->green_pos;
keir@15298 379 vga_console_info.u.vesa_lfb.green_size = bvi->green_size;
keir@15298 380 vga_console_info.u.vesa_lfb.blue_pos = bvi->blue_pos;
keir@15298 381 vga_console_info.u.vesa_lfb.blue_size = bvi->blue_size;
keir@15298 382 vga_console_info.u.vesa_lfb.rsvd_pos = bvi->rsvd_pos;
keir@15298 383 vga_console_info.u.vesa_lfb.rsvd_size = bvi->rsvd_size;
keir@15298 384 }
keir@15298 385 }
keir@15298 386
keir@15082 387 void init_done(void)
keir@15082 388 {
keir@15082 389 extern char __init_begin[], __init_end[];
keir@15082 390
keir@15082 391 /* Free (or page-protect) the init areas. */
keir@15082 392 #ifndef MEMORY_GUARD
keir@15082 393 init_xenheap_pages(__pa(__init_begin), __pa(__init_end));
keir@15082 394 #endif
keir@15082 395 memguard_guard_range(__init_begin, __init_end - __init_begin);
keir@15082 396 #if defined(CONFIG_X86_64)
keir@15082 397 /* Also zap the mapping in the 1:1 area. */
keir@15082 398 memguard_guard_range(__va(__pa(__init_begin)), __init_end - __init_begin);
keir@15082 399 #endif
keir@15082 400 printk("Freed %ldkB init memory.\n", (long)(__init_end-__init_begin)>>10);
keir@15082 401
keir@15082 402 startup_cpu_idle_loop();
keir@15082 403 }
keir@15082 404
kfraser@15379 405 void __init __start_xen(unsigned long mbi_p)
kaf24@1452 406 {
kfraser@15293 407 char *memmap_type = NULL;
kfraser@15426 408 char __cmdline[] = "", *cmdline = __cmdline, *kextra;
kaf24@8457 409 unsigned long _initrd_start = 0, _initrd_len = 0;
kaf24@8457 410 unsigned int initrdidx = 1;
kfraser@11881 411 char *_policy_start = NULL;
kfraser@11881 412 unsigned long _policy_len = 0;
kfraser@15379 413 multiboot_info_t *mbi = __va(mbi_p);
kaf24@8457 414 module_t *mod = (module_t *)__va(mbi->mods_addr);
kaf24@6111 415 unsigned long nr_pages, modules_length;
kfraser@15293 416 int i, e820_warn = 0, bytes = 0;
kaf24@5776 417 struct ns16550_defaults ns16550 = {
kaf24@5776 418 .data_bits = 8,
kaf24@5776 419 .parity = 'n',
kaf24@5776 420 .stop_bits = 1
kaf24@5776 421 };
kaf24@3338 422
kfraser@12853 423 extern void early_page_fault(void);
kfraser@12853 424 set_intr_gate(TRAP_page_fault, &early_page_fault);
kfraser@12853 425
kaf24@3338 426 /* Parse the command-line options. */
kaf24@3344 427 if ( (mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0) )
kaf24@9823 428 cmdline = __va(mbi->cmdline);
kfraser@15426 429 if ( (kextra = strstr(cmdline, " -- ")) != NULL )
kfraser@15426 430 {
kfraser@15426 431 /*
kfraser@15426 432 * Options after ' -- ' separator belong to dom0.
kfraser@15426 433 * 1. Orphan dom0's options from Xen's command line.
kfraser@15426 434 * 2. Skip all but final leading space from dom0's options.
kfraser@15426 435 */
kfraser@15426 436 *kextra = '\0';
kfraser@15426 437 kextra += 3;
kfraser@15426 438 while ( kextra[1] == ' ' ) kextra++;
kfraser@15426 439 }
kaf24@9823 440 cmdline_parse(cmdline);
kaf24@3338 441
keir@15298 442 parse_video_info();
keir@15298 443
kaf24@8534 444 set_current((struct vcpu *)0xfffff000); /* debug sanity */
kfraser@11240 445 idle_vcpu[0] = current;
kaf24@8534 446 set_processor_id(0); /* needed early, for smp_processor_id() */
kaf24@3338 447
kaf24@5146 448 smp_prepare_boot_cpu();
kaf24@5146 449
kaf24@3338 450 /* We initialise the serial devices very early so we can get debugging. */
kaf24@5776 451 ns16550.io_base = 0x3f8;
kaf24@5776 452 ns16550.irq = 4;
kaf24@5776 453 ns16550_init(0, &ns16550);
kaf24@5776 454 ns16550.io_base = 0x2f8;
kaf24@5776 455 ns16550.irq = 3;
kaf24@5776 456 ns16550_init(1, &ns16550);
kaf24@5195 457 serial_init_preirq();
kaf24@3338 458
kaf24@3338 459 init_console();
kaf24@3338 460
kfraser@11947 461 printk("Command line: %s\n", cmdline);
kaf24@9823 462
kfraser@15330 463 printk("Video information:\n");
kfraser@15330 464
kfraser@15330 465 /* Print VGA display mode information. */
keir@15298 466 switch ( vga_console_info.video_type )
keir@15298 467 {
keir@15298 468 case XEN_VGATYPE_TEXT_MODE_3:
kfraser@15330 469 printk(" VGA is text mode %dx%d, font 8x%d\n",
keir@15298 470 vga_console_info.u.text_mode_3.columns,
keir@15298 471 vga_console_info.u.text_mode_3.rows,
keir@15298 472 vga_console_info.u.text_mode_3.font_height);
keir@15298 473 break;
keir@15298 474 case XEN_VGATYPE_VESA_LFB:
kfraser@15330 475 printk(" VGA is graphics mode %dx%d, %d bpp\n",
keir@15298 476 vga_console_info.u.vesa_lfb.width,
keir@15298 477 vga_console_info.u.vesa_lfb.height,
keir@15298 478 vga_console_info.u.vesa_lfb.bits_per_pixel);
keir@15298 479 break;
kfraser@15330 480 default:
kfraser@15330 481 printk(" No VGA detected\n");
kfraser@15330 482 break;
kfraser@15330 483 }
kfraser@15330 484
kfraser@15330 485 /* Print VBE/DDC EDID information. */
kfraser@15330 486 if ( bootsym(boot_edid_caps) != 0x1313 )
kfraser@15330 487 {
kfraser@15330 488 u16 caps = bootsym(boot_edid_caps);
kfraser@15330 489 printk(" VBE/DDC methods:%s%s%s; ",
kfraser@15330 490 (caps & 1) ? " V1" : "",
kfraser@15330 491 (caps & 2) ? " V2" : "",
kfraser@15330 492 !(caps & 3) ? " none" : "");
kfraser@15330 493 printk("EDID transfer time: %d seconds\n", caps >> 8);
kfraser@15330 494 if ( *(u32 *)bootsym(boot_edid_info) == 0x13131313 )
kfraser@15330 495 {
kfraser@15330 496 printk(" EDID info not retrieved because ");
kfraser@15330 497 if ( !(caps & 3) )
kfraser@15330 498 printk("no DDC retrieval method detected\n");
kfraser@15330 499 else if ( (caps >> 8) > 5 )
kfraser@15330 500 printk("takes longer than 5 seconds\n");
kfraser@15330 501 else
kfraser@15330 502 printk("of reasons unknown\n");
kfraser@15330 503 }
keir@15298 504 }
keir@15298 505
kfraser@15336 506 printk("Disc information:\n");
kfraser@15336 507 printk(" Found %d MBR signatures\n",
kfraser@15336 508 bootsym(boot_edd_signature_nr));
kfraser@15336 509 printk(" Found %d EDD information structures\n",
kfraser@15336 510 bootsym(boot_edd_info_nr));
kfraser@15336 511
kaf24@3344 512 /* Check that we have at least one Multiboot module. */
kaf24@3344 513 if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
kfraser@15074 514 EARLY_FAIL("dom0 kernel not specified. "
kfraser@15074 515 "Check bootloader configuration.\n");
kaf24@5011 516
kaf24@5011 517 if ( ((unsigned long)cpu0_stack & (STACK_SIZE-1)) != 0 )
kfraser@15074 518 EARLY_FAIL("Misaligned CPU0 stack.\n");
kaf24@3338 519
kfraser@11618 520 /*
kfraser@11618 521 * Since there are some stubs getting built on the stacks which use
kfraser@11618 522 * direct calls/jumps, the heap must be confined to the lower 2G so
kfraser@11618 523 * that those branches can reach their targets.
kfraser@11618 524 */
kfraser@11618 525 if ( opt_xenheap_megabytes > 2048 )
kfraser@11618 526 opt_xenheap_megabytes = 2048;
kaf24@3338 527
kfraser@15293 528 if ( e820_raw_nr != 0 )
kfraser@15292 529 {
kfraser@15293 530 memmap_type = "Xen-e820";
kfraser@15292 531 }
kfraser@15293 532 else if ( bootsym(lowmem_kb) )
kfraser@15292 533 {
kfraser@15293 534 memmap_type = "Xen-e801";
kfraser@15292 535 e820_raw[0].addr = 0;
kfraser@15293 536 e820_raw[0].size = bootsym(lowmem_kb) << 10;
kfraser@15292 537 e820_raw[0].type = E820_RAM;
kfraser@15292 538 e820_raw[1].addr = 0x100000;
kfraser@15293 539 e820_raw[1].size = bootsym(highmem_kb) << 10;
kfraser@15292 540 e820_raw[1].type = E820_RAM;
kfraser@15292 541 e820_raw_nr = 2;
kfraser@15292 542 }
kfraser@15292 543 else if ( mbi->flags & MBI_MEMMAP )
kaf24@3344 544 {
kfraser@15293 545 memmap_type = "Multiboot-e820";
kaf24@3344 546 while ( bytes < mbi->mmap_length )
kaf24@3344 547 {
kaf24@3344 548 memory_map_t *map = __va(mbi->mmap_addr + bytes);
kaf24@8402 549
kaf24@8402 550 /*
kaf24@8403 551 * This is a gross workaround for a BIOS bug. Some bootloaders do
kaf24@8402 552 * not write e820 map entries into pre-zeroed memory. This is
kaf24@8402 553 * okay if the BIOS fills in all fields of the map entry, but
kaf24@8402 554 * some broken BIOSes do not bother to write the high word of
kaf24@8402 555 * the length field if the length is smaller than 4GB. We
kaf24@8402 556 * detect and fix this by flagging sections below 4GB that
kaf24@8403 557 * appear to be larger than 4GB in size.
kaf24@8402 558 */
kaf24@8403 559 if ( (map->base_addr_high == 0) && (map->length_high != 0) )
kaf24@8402 560 {
kfraser@15292 561 if ( !e820_warn )
kfraser@15292 562 {
kfraser@15292 563 printk("WARNING: Buggy e820 map detected and fixed "
kfraser@15292 564 "(truncated length fields).\n");
kfraser@15292 565 e820_warn = 1;
kfraser@15292 566 }
kaf24@8402 567 map->length_high = 0;
kaf24@8402 568 }
kaf24@8402 569
kaf24@3344 570 e820_raw[e820_raw_nr].addr =
kaf24@3344 571 ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;
kaf24@3344 572 e820_raw[e820_raw_nr].size =
kaf24@3344 573 ((u64)map->length_high << 32) | (u64)map->length_low;
kaf24@3344 574 e820_raw[e820_raw_nr].type =
kfraser@12226 575 (map->type > E820_NVS) ? E820_RESERVED : map->type;
kaf24@3344 576 e820_raw_nr++;
kaf24@8402 577
kaf24@3344 578 bytes += map->size + 4;
kaf24@3344 579 }
kaf24@3344 580 }
kaf24@3344 581 else if ( mbi->flags & MBI_MEMLIMITS )
kaf24@3344 582 {
kfraser@15293 583 memmap_type = "Multiboot-e801";
kaf24@3344 584 e820_raw[0].addr = 0;
kaf24@3344 585 e820_raw[0].size = mbi->mem_lower << 10;
kaf24@3344 586 e820_raw[0].type = E820_RAM;
kaf24@3354 587 e820_raw[1].addr = 0x100000;
kaf24@3354 588 e820_raw[1].size = mbi->mem_upper << 10;
kaf24@3354 589 e820_raw[1].type = E820_RAM;
kaf24@3344 590 e820_raw_nr = 2;
kaf24@3344 591 }
kaf24@3344 592 else
kaf24@3344 593 {
kfraser@15074 594 EARLY_FAIL("Bootloader provided no memory information.\n");
kaf24@3344 595 }
kaf24@3344 596
kaf24@13427 597 /* Ensure that all E820 RAM regions are page-aligned and -sized. */
kaf24@13427 598 for ( i = 0; i < e820_raw_nr; i++ )
kaf24@13427 599 {
kaf24@13427 600 uint64_t s, e;
kfraser@15292 601
kaf24@13427 602 if ( e820_raw[i].type != E820_RAM )
kaf24@13427 603 continue;
kaf24@13427 604 s = PFN_UP(e820_raw[i].addr);
kaf24@13427 605 e = PFN_DOWN(e820_raw[i].addr + e820_raw[i].size);
kaf24@13427 606 e820_raw[i].size = 0; /* discarded later */
kaf24@13427 607 if ( s < e )
kaf24@13427 608 {
kaf24@13427 609 e820_raw[i].addr = s << PAGE_SHIFT;
kaf24@13427 610 e820_raw[i].size = (e - s) << PAGE_SHIFT;
kaf24@13427 611 }
kaf24@13427 612 }
kaf24@13427 613
kaf24@13427 614 /* Sanitise the raw E820 map to produce a final clean version. */
kfraser@15293 615 max_page = init_e820(memmap_type, e820_raw, &e820_raw_nr);
kaf24@3338 616
kfraser@15074 617 /*
kfraser@15074 618 * Create a temporary copy of the E820 map. Truncate it to above 16MB
kfraser@15074 619 * as anything below that is already mapped and has a statically-allocated
kfraser@15074 620 * purpose.
kfraser@15074 621 */
kfraser@15074 622 memcpy(&boot_e820, &e820, sizeof(e820));
kfraser@15074 623 for ( i = 0; i < boot_e820.nr_map; i++ )
kaf24@3338 624 {
kfraser@15074 625 uint64_t s, e, min = 16 << 20; /* 16MB */
kfraser@15074 626 s = boot_e820.map[i].addr;
kfraser@15074 627 e = boot_e820.map[i].addr + boot_e820.map[i].size;
kfraser@15074 628 if ( s >= min )
kfraser@15074 629 continue;
kfraser@15074 630 if ( e > min )
kaf24@6111 631 {
kfraser@15074 632 boot_e820.map[i].addr = min;
kfraser@15074 633 boot_e820.map[i].size = e - min;
kaf24@6111 634 }
kfraser@15074 635 else
kfraser@15074 636 boot_e820.map[i].type = E820_RESERVED;
kaf24@3338 637 }
kaf24@6111 638
kfraser@15074 639 /*
keir@15077 640 * Iterate backwards over all superpage-aligned RAM regions.
kfraser@15074 641 *
kfraser@15074 642 * We require superpage alignment because the boot allocator is not yet
kfraser@15074 643 * initialised. Hence we can only map superpages in the address range
kfraser@15074 644 * 0 to BOOTSTRAP_DIRECTMAP_END, as this is guaranteed not to require
kfraser@15074 645 * dynamic allocation of pagetables.
kfraser@15074 646 *
kfraser@15074 647 * As well as mapping superpages in that range, in preparation for
kfraser@15074 648 * initialising the boot allocator, we also look for a region to which
kfraser@15074 649 * we can relocate the dom0 kernel and other multiboot modules. Also, on
kfraser@15074 650 * x86/64, we relocate Xen to higher memory.
kfraser@15074 651 */
kfraser@15074 652 modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
keir@15077 653 for ( i = boot_e820.nr_map-1; i >= 0; i-- )
kfraser@15074 654 {
kfraser@15074 655 uint64_t s, e, mask = (1UL << L2_PAGETABLE_SHIFT) - 1;
kaf24@6134 656
kfraser@15074 657 /* Superpage-aligned chunks up to BOOTSTRAP_DIRECTMAP_END, please. */
kfraser@15074 658 s = (boot_e820.map[i].addr + mask) & ~mask;
kfraser@15074 659 e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
kfraser@15074 660 e = min_t(uint64_t, e, BOOTSTRAP_DIRECTMAP_END);
kfraser@15074 661 if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
kaf24@3354 662 continue;
kaf24@6111 663
kfraser@15074 664 /* Map the chunk. No memory will need to be allocated to do this. */
kfraser@15074 665 map_pages_to_xen(
kfraser@15074 666 (unsigned long)maddr_to_bootstrap_virt(s),
kfraser@15074 667 s >> PAGE_SHIFT, (e-s) >> PAGE_SHIFT, PAGE_HYPERVISOR);
kaf24@6111 668
kfraser@14084 669 #if defined(CONFIG_X86_64)
kfraser@15074 670 /* Is the region suitable for relocating Xen? */
kfraser@15074 671 if ( !xen_phys_start && (((e-s) >> 20) >= opt_xenheap_megabytes) )
kaf24@5003 672 {
kfraser@15074 673 extern l2_pgentry_t l2_xenmap[];
kfraser@15074 674 l4_pgentry_t *pl4e;
kfraser@15074 675 l3_pgentry_t *pl3e;
kfraser@15074 676 l2_pgentry_t *pl2e;
kfraser@15074 677 int i, j;
kfraser@15074 678
kfraser@15074 679 /* Select relocation address. */
kfraser@15074 680 e = (e - (opt_xenheap_megabytes << 20)) & ~mask;
kfraser@15074 681 xen_phys_start = e;
kfraser@15292 682 bootsym(trampoline_xen_phys_start) = e;
kfraser@15074 683
kfraser@15074 684 /*
kfraser@15074 685 * Perform relocation to new physical address.
kfraser@15074 686 * Before doing so we must sync static/global data with main memory
kfraser@15074 687 * with a barrier(). After this we must *not* modify static/global
kfraser@15074 688 * data until after we have switched to the relocated pagetables!
kfraser@15074 689 */
kfraser@15074 690 barrier();
kfraser@15074 691 move_memory(e, 0, __pa(&_end) - xen_phys_start);
kfraser@15074 692
kfraser@15379 693 /* Poison low 1MB to detect stray pointers to physical 0-1MB. */
kfraser@15379 694 memset(maddr_to_bootstrap_virt(e), 0x55, 1U<<20);
kfraser@15379 695
kfraser@15074 696 /* Walk initial pagetables, relocating page directory entries. */
kfraser@15074 697 pl4e = __va(__pa(idle_pg_table));
kfraser@15074 698 for ( i = 0 ; i < L4_PAGETABLE_ENTRIES; i++, pl4e++ )
kfraser@15074 699 {
kfraser@15074 700 if ( !(l4e_get_flags(*pl4e) & _PAGE_PRESENT) )
kfraser@15074 701 continue;
kfraser@15074 702 *pl4e = l4e_from_intpte(l4e_get_intpte(*pl4e) +
kfraser@15074 703 xen_phys_start);
kfraser@15074 704 pl3e = l4e_to_l3e(*pl4e);
kfraser@15074 705 for ( j = 0; j < L3_PAGETABLE_ENTRIES; j++, pl3e++ )
kfraser@15074 706 {
kfraser@15074 707 /* Not present or already relocated? */
kfraser@15074 708 if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) ||
kfraser@15074 709 (l3e_get_pfn(*pl3e) > 0x1000) )
kfraser@15074 710 continue;
kfraser@15074 711 *pl3e = l3e_from_intpte(l3e_get_intpte(*pl3e) +
kfraser@15074 712 xen_phys_start);
kfraser@15074 713 }
kfraser@15074 714 }
kfraser@15074 715
kfraser@15074 716 /* The only data mappings to be relocated are in the Xen area. */
kfraser@15074 717 pl2e = __va(__pa(l2_xenmap));
kfraser@15074 718 for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++, pl2e++ )
kfraser@15074 719 {
kfraser@15074 720 if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
kfraser@15074 721 continue;
kfraser@15074 722 *pl2e = l2e_from_intpte(l2e_get_intpte(*pl2e) +
kfraser@15074 723 xen_phys_start);
kfraser@15074 724 }
kfraser@15074 725
kfraser@15074 726 /* Re-sync the stack and then switch to relocated pagetables. */
kfraser@15074 727 asm volatile (
kfraser@15074 728 "rep movsb ; " /* re-sync the stack */
kfraser@15074 729 "movq %%cr4,%%rsi ; "
kfraser@15074 730 "andb $0x7f,%%sil ; "
kfraser@15074 731 "movq %%rsi,%%cr4 ; " /* CR4.PGE == 0 */
kfraser@15074 732 "movq %0,%%cr3 ; " /* CR3 == new pagetables */
kfraser@15074 733 "orb $0x80,%%sil ; "
kfraser@15074 734 "movq %%rsi,%%cr4 " /* CR4.PGE == 1 */
kfraser@15074 735 : : "r" (__pa(idle_pg_table)), "S" (cpu0_stack),
kfraser@15074 736 "D" (__va(__pa(cpu0_stack))), "c" (STACK_SIZE) : "memory" );
kaf24@5003 737 }
kaf24@5003 738 #endif
keir@15077 739
keir@15077 740 /* Is the region suitable for relocating the multiboot modules? */
keir@15077 741 if ( !initial_images_start && (s < e) && ((e-s) >= modules_length) )
keir@15077 742 {
keir@15077 743 e -= modules_length;
keir@15077 744 initial_images_start = e;
keir@15077 745 initial_images_end = initial_images_start + modules_length;
keir@15077 746 move_memory(initial_images_start,
keir@15077 747 mod[0].mod_start, mod[mbi->mods_count-1].mod_end);
keir@15077 748 }
kaf24@3354 749 }
kaf24@3354 750
kfraser@15074 751 if ( !initial_images_start )
kfraser@15074 752 EARLY_FAIL("Not enough memory to relocate the dom0 kernel image.\n");
kfraser@15074 753 reserve_in_boot_e820(initial_images_start, initial_images_end);
kfraser@15074 754
kfraser@15074 755 /*
kfraser@15074 756 * With modules (and Xen itself, on x86/64) relocated out of the way, we
kfraser@15074 757 * can now initialise the boot allocator with some memory.
kfraser@15074 758 */
kfraser@15074 759 xenheap_phys_start = init_boot_allocator(__pa(&_end));
kfraser@15074 760 xenheap_phys_end = opt_xenheap_megabytes << 20;
kfraser@15074 761 #if defined(CONFIG_X86_64)
kfraser@15074 762 if ( !xen_phys_start )
kfraser@15074 763 EARLY_FAIL("Not enough memory to relocate Xen.\n");
kfraser@15074 764 xenheap_phys_end += xen_phys_start;
kfraser@15074 765 reserve_in_boot_e820(xen_phys_start,
kfraser@15074 766 xen_phys_start + (opt_xenheap_megabytes<<20));
kfraser@15074 767 init_boot_pages(1<<20, 16<<20); /* Initial seed: 15MB */
kfraser@15074 768 #else
kfraser@15074 769 init_boot_pages(xenheap_phys_end, 16<<20); /* Initial seed: 4MB */
kfraser@15074 770 #endif
kfraser@15074 771
kfraser@15074 772 /*
kfraser@15074 773 * With the boot allocator now seeded, we can walk every RAM region and
kfraser@15074 774 * map it in its entirety (on x86/64, at least) and notify it to the
kfraser@15074 775 * boot allocator.
kfraser@15074 776 */
kfraser@15074 777 for ( i = 0; i < boot_e820.nr_map; i++ )
kfraser@15074 778 {
kfraser@15074 779 uint64_t s, e, map_e, mask = PAGE_SIZE - 1;
kfraser@15074 780
kfraser@15074 781 /* Only page alignment required now. */
kfraser@15074 782 s = (boot_e820.map[i].addr + mask) & ~mask;
kfraser@15074 783 e = (boot_e820.map[i].addr + boot_e820.map[i].size) & ~mask;
kfraser@15074 784 if ( (boot_e820.map[i].type != E820_RAM) || (s >= e) )
kfraser@15074 785 continue;
kfraser@15074 786
kfraser@15074 787 /* Perform the mapping (truncated in 32-bit mode). */
kfraser@15074 788 map_e = e;
kfraser@15074 789 #if defined(CONFIG_X86_32)
kfraser@15074 790 map_e = min_t(uint64_t, map_e, BOOTSTRAP_DIRECTMAP_END);
kfraser@15074 791 #endif
kfraser@15074 792 if ( s < map_e )
kfraser@15074 793 map_pages_to_xen(
kfraser@15074 794 (unsigned long)maddr_to_bootstrap_virt(s),
kfraser@15074 795 s >> PAGE_SHIFT, (map_e-s) >> PAGE_SHIFT, PAGE_HYPERVISOR);
kfraser@15074 796
kfraser@15074 797 init_boot_pages(s, e);
kfraser@15074 798 }
kfraser@15074 799
kfraser@15074 800 if ( (kexec_crash_area.size > 0) && (kexec_crash_area.start > 0) )
ian@12681 801 {
ian@12677 802 unsigned long kdump_start, kdump_size, k;
ian@12677 803
ian@12681 804 /* Mark images pages as free for now. */
ian@12677 805 init_boot_pages(initial_images_start, initial_images_end);
ian@12677 806
ian@12713 807 kdump_start = kexec_crash_area.start;
ian@12713 808 kdump_size = kexec_crash_area.size;
ian@12677 809
ian@12681 810 printk("Kdump: %luMB (%lukB) at 0x%lx\n",
ian@12677 811 kdump_size >> 20,
ian@12677 812 kdump_size >> 10,
ian@12677 813 kdump_start);
ian@12677 814
ian@12681 815 if ( (kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK) )
ian@12677 816 panic("Kdump parameters not page aligned\n");
ian@12677 817
ian@12677 818 kdump_start >>= PAGE_SHIFT;
ian@12677 819 kdump_size >>= PAGE_SHIFT;
ian@12677 820
kfraser@12853 821 /* Allocate pages for Kdump memory area. */
kfraser@14083 822 if ( !reserve_boot_pages(kdump_start, kdump_size) )
ian@12677 823 panic("Unable to reserve Kdump memory\n");
ian@12677 824
kfraser@12853 825 /* Allocate pages for relocated initial images. */
ian@12677 826 k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
ian@12677 827 k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
ian@12677 828
kfraser@14084 829 #if defined(CONFIG_X86_32)
kfraser@14084 830 /* Must allocate within bootstrap 1:1 limits. */
kfraser@15074 831 k = alloc_boot_low_pages(k, 1); /* 0x0 - BOOTSTRAP_DIRECTMAP_END */
kfraser@14084 832 #else
kfraser@14084 833 k = alloc_boot_pages(k, 1);
kfraser@14084 834 #endif
kfraser@12853 835 if ( k == 0 )
ian@12677 836 panic("Unable to allocate initial images memory\n");
ian@12677 837
ian@12677 838 move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
ian@12677 839
ian@12677 840 initial_images_end -= initial_images_start;
ian@12677 841 initial_images_start = k << PAGE_SHIFT;
ian@12677 842 initial_images_end += initial_images_start;
ian@12681 843 }
ian@12677 844
kaf24@5003 845 memguard_init();
kaf24@4950 846
kfraser@15074 847 nr_pages = 0;
kfraser@15074 848 for ( i = 0; i < e820.nr_map; i++ )
kfraser@15074 849 if ( e820.map[i].type == E820_RAM )
kfraser@15074 850 nr_pages += e820.map[i].size >> PAGE_SHIFT;
ian@12681 851 printk("System RAM: %luMB (%lukB)\n",
kaf24@3354 852 nr_pages >> (20 - PAGE_SHIFT),
kaf24@3354 853 nr_pages << (PAGE_SHIFT - 10));
kaf24@7220 854 total_pages = nr_pages;
kaf24@3354 855
kfraser@11296 856 /* Sanity check for unwanted bloat of certain hypercall structures. */
kfraser@11296 857 BUILD_BUG_ON(sizeof(((struct xen_platform_op *)0)->u) !=
kfraser@11296 858 sizeof(((struct xen_platform_op *)0)->u.pad));
kfraser@11296 859 BUILD_BUG_ON(sizeof(((struct xen_domctl *)0)->u) !=
kfraser@11296 860 sizeof(((struct xen_domctl *)0)->u.pad));
kfraser@11296 861 BUILD_BUG_ON(sizeof(((struct xen_sysctl *)0)->u) !=
kfraser@11296 862 sizeof(((struct xen_sysctl *)0)->u.pad));
kaf24@7388 863
kaf24@9878 864 BUILD_BUG_ON(sizeof(start_info_t) > PAGE_SIZE);
kaf24@9878 865 BUILD_BUG_ON(sizeof(shared_info_t) > PAGE_SIZE);
ack@13292 866 BUILD_BUG_ON(sizeof(struct vcpu_info) != 64);
kaf24@7744 867
ack@13291 868 #ifdef CONFIG_COMPAT
ack@13291 869 BUILD_BUG_ON(sizeof(((struct compat_platform_op *)0)->u) !=
ack@13291 870 sizeof(((struct compat_platform_op *)0)->u.pad));
ack@13291 871 BUILD_BUG_ON(sizeof(start_info_compat_t) > PAGE_SIZE);
ack@13292 872 BUILD_BUG_ON(sizeof(struct compat_vcpu_info) != 64);
ack@13291 873 #endif
ack@13291 874
kfraser@10492 875 /* Check definitions in public headers match internal defs. */
kaf24@9878 876 BUILD_BUG_ON(__HYPERVISOR_VIRT_START != HYPERVISOR_VIRT_START);
kaf24@8521 877 #ifdef HYPERVISOR_VIRT_END
kaf24@9878 878 BUILD_BUG_ON(__HYPERVISOR_VIRT_END != HYPERVISOR_VIRT_END);
kaf24@8521 879 #endif
kfraser@10492 880 BUILD_BUG_ON(MACH2PHYS_VIRT_START != RO_MPT_VIRT_START);
kfraser@10492 881 BUILD_BUG_ON(MACH2PHYS_VIRT_END != RO_MPT_VIRT_END);
kaf24@8521 882
kaf24@3354 883 init_frametable();
kaf24@3338 884
kfraser@11971 885 acpi_boot_table_init();
kfraser@11971 886
kfraser@11971 887 acpi_numa_init();
kfraser@11971 888
kfraser@11971 889 numa_initmem_init(0, max_page);
kfraser@11971 890
kaf24@6111 891 /* Initialise the Xen heap, skipping RAM holes. */
kfraser@15074 892 init_xenheap_pages(xenheap_phys_start, xenheap_phys_end);
kfraser@15074 893 nr_pages = (xenheap_phys_end - xenheap_phys_start) >> PAGE_SHIFT;
kfraser@15074 894 #ifdef __x86_64__
kfraser@15074 895 init_xenheap_pages(xen_phys_start, __pa(&_start));
kfraser@15074 896 nr_pages += (__pa(&_start) - xen_phys_start) >> PAGE_SHIFT;
kfraser@15074 897 #endif
kfraser@15074 898 xenheap_phys_start = xen_phys_start;
kaf24@6111 899 printk("Xen heap: %luMB (%lukB)\n",
kaf24@6111 900 nr_pages >> (20 - PAGE_SHIFT),
kaf24@6111 901 nr_pages << (PAGE_SHIFT - 10));
kaf24@3338 902
keir@14680 903 end_boot_allocator();
keir@14680 904
kaf24@3594 905 early_boot = 0;
kaf24@3338 906
kaf24@8459 907 early_cpu_init();
kaf24@8459 908
kaf24@8459 909 paging_init();
kaf24@8459 910
kaf24@8459 911 /* Unmap the first page of CPU0's stack. */
kaf24@8459 912 memguard_guard_stack(cpu0_stack);
kaf24@8459 913
kaf24@8459 914 open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
kaf24@8459 915
kaf24@8459 916 if ( opt_watchdog )
kaf24@8459 917 nmi_watchdog = NMI_LOCAL_APIC;
kaf24@8459 918
kaf24@8459 919 sort_exception_tables();
kaf24@8459 920
kaf24@8459 921 find_smp_config();
kaf24@8459 922
kaf24@8459 923 dmi_scan_machine();
kaf24@8459 924
kaf24@8459 925 generic_apic_probe();
kaf24@8459 926
kaf24@8459 927 acpi_boot_init();
kaf24@8459 928
kfraser@11971 929 init_cpu_to_node();
kfraser@11971 930
kfraser@11241 931 if ( smp_found_config )
kaf24@8459 932 get_smp_config();
kaf24@8459 933
keir@15083 934 #ifdef CONFIG_X86_64
keir@15083 935 /* Low mappings were only needed for some BIOS table parsing. */
keir@15083 936 zap_low_mappings();
keir@15083 937 #endif
keir@15083 938
kaf24@8459 939 init_apic_mappings();
kaf24@8459 940
kaf24@8459 941 init_IRQ();
kaf24@8459 942
kfraser@11241 943 percpu_init_areas();
kfraser@11241 944
kfraser@11240 945 init_idle_domain();
kfraser@11240 946
kaf24@8459 947 trap_init();
kaf24@8459 948
kaf24@13662 949 rcu_init();
kaf24@13662 950
kaf24@8586 951 timer_init();
kaf24@8459 952
kaf24@8459 953 early_time_init();
kaf24@8459 954
kaf24@8459 955 arch_init_memory();
kaf24@8459 956
kaf24@8459 957 identify_cpu(&boot_cpu_data);
kaf24@8459 958 if ( cpu_has_fxsr )
kaf24@8459 959 set_in_cr4(X86_CR4_OSFXSR);
kaf24@8459 960 if ( cpu_has_xmm )
kaf24@8459 961 set_in_cr4(X86_CR4_OSXMMEXCPT);
kaf24@8459 962
kaf24@8459 963 if ( opt_nosmp )
kaf24@8459 964 max_cpus = 0;
kaf24@8459 965
kaf24@8459 966 smp_prepare_cpus(max_cpus);
kaf24@8459 967
kaf24@8459 968 /*
kaf24@8459 969 * Initialise higher-level timer functions. We do this fairly late
kaf24@8459 970 * (post-SMP) because the time bases and scale factors need to be updated
kaf24@8459 971 * regularly, and SMP initialisation can cause a long delay with
kaf24@8459 972 * interrupts not yet enabled.
kaf24@8459 973 */
kaf24@8459 974 init_xen_time();
kaf24@8459 975
kaf24@8459 976 initialize_keytable();
kaf24@8459 977
kaf24@8459 978 serial_init_postirq();
kaf24@8459 979
kaf24@8459 980 BUG_ON(!local_irq_is_enabled());
kaf24@8459 981
kaf24@8459 982 for_each_present_cpu ( i )
kaf24@8459 983 {
kaf24@8459 984 if ( num_online_cpus() >= max_cpus )
kaf24@8459 985 break;
kaf24@8459 986 if ( !cpu_online(i) )
kaf24@13662 987 {
kaf24@13662 988 rcu_online_cpu(i);
kaf24@8459 989 __cpu_up(i);
kaf24@13662 990 }
kfraser@11971 991
kfraser@11998 992 /* Set up cpu_to_node[]. */
kfraser@11971 993 srat_detect_node(i);
kfraser@11998 994 /* Set up node_to_cpumask based on cpu_to_node[]. */
kfraser@11971 995 numa_add_cpu(i);
kaf24@8459 996 }
kaf24@8459 997
kaf24@8459 998 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
kaf24@8459 999 smp_cpus_done(max_cpus);
kaf24@8459 1000
kaf24@9117 1001 initialise_gdb(); /* could be moved earlier */
kaf24@9117 1002
kaf24@8459 1003 do_initcalls();
kaf24@8459 1004
kaf24@8594 1005 if ( opt_watchdog )
kaf24@8594 1006 watchdog_enable();
kaf24@8459 1007
kfraser@11881 1008 /* Extract policy from multiboot. */
kfraser@11881 1009 extract_acm_policy(mbi, &initrdidx, &_policy_start, &_policy_len);
kfraser@11881 1010
kaf24@8459 1011 /* initialize access control security module */
kfraser@11881 1012 acm_init(_policy_start, _policy_len);
kaf24@8459 1013
kaf24@8459 1014 /* Create initial domain 0. */
kfraser@14911 1015 dom0 = domain_create(0, 0, DOM0_SSIDREF);
kfraser@10655 1016 if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
kaf24@8459 1017 panic("Error creating domain 0\n");
kaf24@8459 1018
kfraser@12210 1019 dom0->is_privileged = 1;
kfraser@12210 1020
kaf24@8459 1021 /* Grab the DOM0 command line. */
kaf24@8459 1022 cmdline = (char *)(mod[0].string ? __va(mod[0].string) : NULL);
kfraser@15426 1023 if ( (cmdline != NULL) || (kextra != NULL) )
kaf24@8459 1024 {
kaf24@8459 1025 static char dom0_cmdline[MAX_GUEST_CMDLINE];
kaf24@8459 1026
kfraser@15426 1027 dom0_cmdline[0] = '\0';
kfraser@15426 1028
kfraser@15426 1029 if ( cmdline != NULL )
kaf24@8459 1030 {
kfraser@15426 1031 /* Skip past the image name and copy to a local buffer. */
kaf24@8459 1032 while ( *cmdline == ' ' ) cmdline++;
kfraser@15426 1033 if ( (cmdline = strchr(cmdline, ' ')) != NULL )
kfraser@15426 1034 {
kfraser@15426 1035 while ( *cmdline == ' ' ) cmdline++;
kfraser@15426 1036 safe_strcpy(dom0_cmdline, cmdline);
kfraser@15426 1037 }
kaf24@8459 1038 }
kaf24@8459 1039
kfraser@15426 1040 if ( kextra != NULL )
kfraser@15426 1041 /* kextra always includes exactly one leading space. */
kfraser@15426 1042 safe_strcat(dom0_cmdline, kextra);
kfraser@15426 1043
kaf24@8459 1044 /* Append any extra parameters. */
kfraser@13691 1045 if ( skip_ioapic_setup && !strstr(dom0_cmdline, "noapic") )
kfraser@13691 1046 safe_strcat(dom0_cmdline, " noapic");
kaf24@8459 1047 if ( acpi_skip_timer_override &&
kfraser@13691 1048 !strstr(dom0_cmdline, "acpi_skip_timer_override") )
kfraser@13691 1049 safe_strcat(dom0_cmdline, " acpi_skip_timer_override");
kfraser@13691 1050 if ( (strlen(acpi_param) != 0) && !strstr(dom0_cmdline, "acpi=") )
kaf24@8459 1051 {
kfraser@13691 1052 safe_strcat(dom0_cmdline, " acpi=");
kfraser@13691 1053 safe_strcat(dom0_cmdline, acpi_param);
kaf24@8459 1054 }
kfraser@13691 1055
kfraser@13691 1056 cmdline = dom0_cmdline;
kaf24@8459 1057 }
kaf24@8459 1058
kaf24@8459 1059 if ( (initrdidx > 0) && (initrdidx < mbi->mods_count) )
kaf24@8459 1060 {
kaf24@8459 1061 _initrd_start = initial_images_start +
kaf24@8459 1062 (mod[initrdidx].mod_start - mod[0].mod_start);
kaf24@8459 1063 _initrd_len = mod[initrdidx].mod_end - mod[initrdidx].mod_start;
kaf24@8459 1064 }
kaf24@8459 1065
kaf24@8459 1066 /*
kaf24@8459 1067 * We're going to setup domain0 using the module(s) that we stashed safely
kaf24@8459 1068 * above our heap. The second module, if present, is an initrd ramdisk.
kaf24@8459 1069 */
kaf24@8459 1070 if ( construct_dom0(dom0,
kaf24@8459 1071 initial_images_start,
kaf24@8459 1072 mod[0].mod_end-mod[0].mod_start,
kaf24@8459 1073 _initrd_start,
kaf24@8459 1074 _initrd_len,
kaf24@8459 1075 cmdline) != 0)
kaf24@8459 1076 panic("Could not set up DOM0 guest OS\n");
kaf24@8459 1077
kaf24@8459 1078 /* Scrub RAM that is still free and so may go to an unprivileged domain. */
kaf24@8459 1079 scrub_heap_pages();
kaf24@8459 1080
kaf24@8459 1081 init_trace_bufs();
kaf24@8459 1082
kaf24@10502 1083 console_endboot();
kaf24@8459 1084
kaf24@8459 1085 /* Hide UART from DOM0 if we're using it */
kaf24@8459 1086 serial_endboot();
kaf24@8459 1087
kaf24@8459 1088 domain_unpause_by_systemcontroller(dom0);
kaf24@8459 1089
keir@15082 1090 reset_stack_and_jump(init_done);
kaf24@8459 1091 }
kaf24@8459 1092
ian@13763 1093 void arch_get_xen_caps(xen_capabilities_info_t *info)
iap10@6721 1094 {
kfraser@14997 1095 /* Interface name is always xen-3.0-* for Xen-3.x. */
kfraser@14997 1096 int major = 3, minor = 0;
keir@13754 1097 char s[32];
keir@13754 1098
ian@13763 1099 (*info)[0] = '\0';
iap10@6721 1100
kaf24@6725 1101 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE)
kaf24@6725 1102
keir@13754 1103 snprintf(s, sizeof(s), "xen-%d.%d-x86_32 ", major, minor);
ian@13763 1104 safe_strcat(*info, s);
keir@13754 1105 if ( hvm_enabled )
keir@13754 1106 {
keir@13754 1107 snprintf(s, sizeof(s), "hvm-%d.%d-x86_32 ", major, minor);
ian@13763 1108 safe_strcat(*info, s);
kfraser@13685 1109 }
kaf24@6725 1110
kaf24@6725 1111 #elif defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE)
kaf24@6725 1112
keir@13754 1113 snprintf(s, sizeof(s), "xen-%d.%d-x86_32p ", major, minor);
ian@13763 1114 safe_strcat(*info, s);
kaf24@6725 1115 if ( hvm_enabled )
iap10@6721 1116 {
keir@13754 1117 snprintf(s, sizeof(s), "hvm-%d.%d-x86_32 ", major, minor);
ian@13763 1118 safe_strcat(*info, s);
keir@13754 1119 snprintf(s, sizeof(s), "hvm-%d.%d-x86_32p ", major, minor);
ian@13763 1120 safe_strcat(*info, s);
iap10@6721 1121 }
iap10@6721 1122
kaf24@6725 1123 #elif defined(CONFIG_X86_64)
iap10@6721 1124
keir@13754 1125 snprintf(s, sizeof(s), "xen-%d.%d-x86_64 ", major, minor);
ian@13763 1126 safe_strcat(*info, s);
ack@13288 1127 #ifdef CONFIG_COMPAT
keir@13754 1128 snprintf(s, sizeof(s), "xen-%d.%d-x86_32p ", major, minor);
ian@13763 1129 safe_strcat(*info, s);
ack@13288 1130 #endif
kaf24@6725 1131 if ( hvm_enabled )
iap10@6721 1132 {
keir@13754 1133 snprintf(s, sizeof(s), "hvm-%d.%d-x86_32 ", major, minor);
ian@13763 1134 safe_strcat(*info, s);
keir@13754 1135 snprintf(s, sizeof(s), "hvm-%d.%d-x86_32p ", major, minor);
ian@13763 1136 safe_strcat(*info, s);
keir@13754 1137 snprintf(s, sizeof(s), "hvm-%d.%d-x86_64 ", major, minor);
ian@13763 1138 safe_strcat(*info, s);
iap10@6721 1139 }
kaf24@6725 1140
iap10@6721 1141 #endif
iap10@6721 1142 }
iap10@6721 1143
kaf24@3914 1144 /*
kaf24@3914 1145 * Local variables:
kaf24@3914 1146 * mode: C
kaf24@3914 1147 * c-set-style: "BSD"
kaf24@3914 1148 * c-basic-offset: 4
kaf24@3914 1149 * tab-width: 4
kaf24@3914 1150 * indent-tabs-mode: nil
kaf24@3988 1151 * End:
kaf24@3914 1152 */