1 | /****************************************************************************** |
---|
2 | * xensetup.c |
---|
3 | * Copyright (c) 2004-2005 Hewlett-Packard Co |
---|
4 | * Dan Magenheimer <dan.magenheimer@hp.com> |
---|
5 | */ |
---|
6 | |
---|
7 | #include <xen/config.h> |
---|
8 | #include <xen/lib.h> |
---|
9 | #include <xen/errno.h> |
---|
10 | //#include <xen/spinlock.h> |
---|
11 | #include <xen/multiboot.h> |
---|
12 | #include <xen/sched.h> |
---|
13 | #include <xen/mm.h> |
---|
14 | #include <public/version.h> |
---|
15 | #include <xen/gdbstub.h> |
---|
16 | #include <xen/version.h> |
---|
17 | #include <xen/console.h> |
---|
18 | #include <xen/domain.h> |
---|
19 | #include <xen/serial.h> |
---|
20 | #include <xen/trace.h> |
---|
21 | #include <xen/keyhandler.h> |
---|
22 | #include <asm/meminit.h> |
---|
23 | #include <asm/page.h> |
---|
24 | #include <asm/setup.h> |
---|
25 | #include <xen/string.h> |
---|
26 | #include <asm/vmx.h> |
---|
27 | #include <linux/efi.h> |
---|
28 | #include <asm/iosapic.h> |
---|
29 | #include <xen/softirq.h> |
---|
30 | #include <xen/rcupdate.h> |
---|
31 | #include <acm/acm_hooks.h> |
---|
32 | |
---|
33 | unsigned long xenheap_phys_end, total_pages; |
---|
34 | |
---|
35 | char saved_command_line[COMMAND_LINE_SIZE]; |
---|
36 | char dom0_command_line[COMMAND_LINE_SIZE]; |
---|
37 | |
---|
38 | cpumask_t cpu_present_map; |
---|
39 | |
---|
40 | extern unsigned long domain0_ready; |
---|
41 | |
---|
42 | int find_max_pfn (unsigned long, unsigned long, void *); |
---|
43 | |
---|
44 | /* FIXME: which header these declarations should be there ? */ |
---|
45 | extern long is_platform_hp_ski(void); |
---|
46 | extern void early_setup_arch(char **); |
---|
47 | extern void late_setup_arch(char **); |
---|
48 | extern void hpsim_serial_init(void); |
---|
49 | extern void alloc_dom0(void); |
---|
50 | extern void setup_per_cpu_areas(void); |
---|
51 | extern void mem_init(void); |
---|
52 | extern void init_IRQ(void); |
---|
53 | extern void trap_init(void); |
---|
54 | extern void xen_patch_kernel(void); |
---|
55 | |
---|
56 | /* opt_nosmp: If true, secondary processors are ignored. */ |
---|
57 | static int opt_nosmp; |
---|
58 | boolean_param("nosmp", opt_nosmp); |
---|
59 | |
---|
60 | /* maxcpus: maximum number of CPUs to activate. */ |
---|
61 | static unsigned int max_cpus = NR_CPUS; |
---|
62 | integer_param("maxcpus", max_cpus); |
---|
63 | |
---|
64 | /* xencons: if true enable xenconsole input (and irq). |
---|
65 | Note: you have to disable 8250 serials in domains (to avoid use of the |
---|
66 | same resource). */ |
---|
67 | static int opt_xencons = 1; |
---|
68 | integer_param("xencons", opt_xencons); |
---|
69 | |
---|
70 | /* Toggle to allow non-legacy xencons UARTs to run in polling mode */ |
---|
71 | static int opt_xencons_poll; |
---|
72 | boolean_param("xencons_poll", opt_xencons_poll); |
---|
73 | |
---|
74 | /* |
---|
75 | * opt_xenheap_megabytes: Size of Xen heap in megabytes, including: |
---|
76 | * xen image |
---|
77 | * bootmap bits |
---|
78 | * xen heap |
---|
79 | * Note: To allow xenheap size configurable, the prerequisite is |
---|
80 | * to configure elilo allowing relocation defaultly. Then since |
---|
81 | * elilo chooses 256M as alignment when relocating, alignment issue |
---|
82 | * on IPF can be addressed. |
---|
83 | */ |
---|
84 | unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB; |
---|
85 | unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE; |
---|
86 | extern long running_on_sim; |
---|
87 | unsigned long xen_pstart; |
---|
88 | void *xen_heap_start __read_mostly; |
---|
89 | |
---|
90 | static int |
---|
91 | xen_count_pages(u64 start, u64 end, void *arg) |
---|
92 | { |
---|
93 | unsigned long *count = arg; |
---|
94 | |
---|
95 | /* FIXME: do we need consider difference between DMA-usable memory and |
---|
96 | * normal memory? Seems that HV has no requirement to operate DMA which |
---|
97 | * is owned by Dom0? */ |
---|
98 | *count += (end - start) >> PAGE_SHIFT; |
---|
99 | return 0; |
---|
100 | } |
---|
101 | |
---|
102 | static void __init do_initcalls(void) |
---|
103 | { |
---|
104 | initcall_t *call; |
---|
105 | for ( call = &__initcall_start; call < &__initcall_end; call++ ) |
---|
106 | (*call)(); |
---|
107 | } |
---|
108 | |
---|
109 | /* |
---|
110 | * IPF loader only supports one commaind line currently, for |
---|
111 | * both xen and guest kernel. This function provides pre-parse |
---|
112 | * to mixed command line, to split it into two parts. |
---|
113 | * |
---|
114 | * User should split the parameters by "--", with strings after |
---|
115 | * spliter for guest kernel. Missing "--" means whole line belongs |
---|
116 | * to guest. Example: |
---|
117 | * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty |
---|
118 | * root=/dev/sda3 ro" |
---|
119 | */ |
---|
120 | static char null[4] = { 0 }; |
---|
121 | |
---|
122 | void early_cmdline_parse(char **cmdline_p) |
---|
123 | { |
---|
124 | char *guest_cmd; |
---|
125 | static const char * const split = "--"; |
---|
126 | |
---|
127 | if (*cmdline_p == NULL) { |
---|
128 | *cmdline_p = &null[0]; |
---|
129 | saved_command_line[0] = '\0'; |
---|
130 | dom0_command_line[0] = '\0'; |
---|
131 | return; |
---|
132 | } |
---|
133 | |
---|
134 | guest_cmd = strstr(*cmdline_p, split); |
---|
135 | /* If no spliter, whole line is for guest */ |
---|
136 | if (guest_cmd == NULL) { |
---|
137 | guest_cmd = *cmdline_p; |
---|
138 | *cmdline_p = &null[0]; |
---|
139 | } else { |
---|
140 | *guest_cmd = '\0'; /* Split boot parameters for xen and guest */ |
---|
141 | guest_cmd += strlen(split); |
---|
142 | while (*guest_cmd == ' ') guest_cmd++; |
---|
143 | } |
---|
144 | |
---|
145 | strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE); |
---|
146 | strlcpy(dom0_command_line, guest_cmd, COMMAND_LINE_SIZE); |
---|
147 | return; |
---|
148 | } |
---|
149 | |
---|
150 | struct ns16550_defaults ns16550_com1 = { |
---|
151 | .data_bits = 8, |
---|
152 | .parity = 'n', |
---|
153 | .stop_bits = 1 |
---|
154 | }; |
---|
155 | |
---|
156 | unsigned int ns16550_com1_gsi; |
---|
157 | unsigned int ns16550_com1_polarity; |
---|
158 | unsigned int ns16550_com1_trigger; |
---|
159 | |
---|
160 | struct ns16550_defaults ns16550_com2 = { |
---|
161 | .data_bits = 8, |
---|
162 | .parity = 'n', |
---|
163 | .stop_bits = 1 |
---|
164 | }; |
---|
165 | |
---|
166 | /* efi_print: print efi table at boot */ |
---|
167 | static int opt_efi_print; |
---|
168 | boolean_param("efi_print", opt_efi_print); |
---|
169 | |
---|
170 | /* print EFI memory map: */ |
---|
171 | static void |
---|
172 | efi_print(void) |
---|
173 | { |
---|
174 | void *efi_map_start, *efi_map_end; |
---|
175 | u64 efi_desc_size; |
---|
176 | |
---|
177 | efi_memory_desc_t *md; |
---|
178 | void *p; |
---|
179 | int i; |
---|
180 | |
---|
181 | if (!opt_efi_print) |
---|
182 | return; |
---|
183 | |
---|
184 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
---|
185 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
---|
186 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
---|
187 | |
---|
188 | for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { |
---|
189 | md = p; |
---|
190 | printk("mem%02u: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) " |
---|
191 | "(%luMB)\n", i, md->type, md->attribute, md->phys_addr, |
---|
192 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), |
---|
193 | md->num_pages >> (20 - EFI_PAGE_SHIFT)); |
---|
194 | } |
---|
195 | } |
---|
196 | |
---|
197 | /* |
---|
198 | * These functions are utility functions for getting and |
---|
199 | * testing memory descriptors for allocating the xenheap area. |
---|
200 | */ |
---|
201 | static efi_memory_desc_t * |
---|
202 | efi_get_md (unsigned long phys_addr) |
---|
203 | { |
---|
204 | void *efi_map_start, *efi_map_end, *p; |
---|
205 | efi_memory_desc_t *md; |
---|
206 | u64 efi_desc_size; |
---|
207 | |
---|
208 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
---|
209 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
---|
210 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
---|
211 | |
---|
212 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
---|
213 | md = p; |
---|
214 | if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) |
---|
215 | return md; |
---|
216 | } |
---|
217 | return 0; |
---|
218 | } |
---|
219 | |
---|
220 | static int |
---|
221 | is_xenheap_usable_memory(efi_memory_desc_t *md) |
---|
222 | { |
---|
223 | if (!(md->attribute & EFI_MEMORY_WB)) |
---|
224 | return 0; |
---|
225 | |
---|
226 | switch (md->type) { |
---|
227 | case EFI_LOADER_CODE: |
---|
228 | case EFI_LOADER_DATA: |
---|
229 | case EFI_BOOT_SERVICES_CODE: |
---|
230 | case EFI_BOOT_SERVICES_DATA: |
---|
231 | case EFI_CONVENTIONAL_MEMORY: |
---|
232 | return 1; |
---|
233 | } |
---|
234 | return 0; |
---|
235 | } |
---|
236 | |
---|
237 | static inline int |
---|
238 | md_overlaps(efi_memory_desc_t *md, unsigned long phys_addr) |
---|
239 | { |
---|
240 | return (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)); |
---|
241 | } |
---|
242 | |
---|
243 | #define MD_SIZE(md) (md->num_pages << EFI_PAGE_SHIFT) |
---|
244 | |
---|
245 | void start_kernel(void) |
---|
246 | { |
---|
247 | char *cmdline; |
---|
248 | unsigned long nr_pages; |
---|
249 | unsigned long dom0_memory_start, dom0_memory_size; |
---|
250 | unsigned long dom0_initrd_start, dom0_initrd_size; |
---|
251 | unsigned long md_end, relo_start, relo_end, relo_size = 0; |
---|
252 | struct domain *idle_domain; |
---|
253 | struct vcpu *dom0_vcpu0; |
---|
254 | efi_memory_desc_t *kern_md, *last_md, *md; |
---|
255 | #ifdef CONFIG_SMP |
---|
256 | int i; |
---|
257 | #endif |
---|
258 | |
---|
259 | /* Be sure the struct shared_info size is <= XSI_SIZE. */ |
---|
260 | BUILD_BUG_ON(sizeof(struct shared_info) > XSI_SIZE); |
---|
261 | |
---|
262 | running_on_sim = is_platform_hp_ski(); |
---|
263 | /* Kernel may be relocated by EFI loader */ |
---|
264 | xen_pstart = ia64_tpa(KERNEL_START); |
---|
265 | |
---|
266 | early_setup_arch(&cmdline); |
---|
267 | |
---|
268 | /* We initialise the serial devices very early so we can get debugging. */ |
---|
269 | if (running_on_sim) |
---|
270 | hpsim_serial_init(); |
---|
271 | else { |
---|
272 | ns16550_init(0, &ns16550_com1); |
---|
273 | ns16550_init(1, &ns16550_com2); |
---|
274 | } |
---|
275 | serial_init_preirq(); |
---|
276 | |
---|
277 | init_console(); |
---|
278 | set_printk_prefix("(XEN) "); |
---|
279 | |
---|
280 | if (running_on_sim || ia64_boot_param->domain_start == 0 || |
---|
281 | ia64_boot_param->domain_size == 0) { |
---|
282 | /* This is possible only with the old elilo, which does not support |
---|
283 | a vmm. Fix now, and continue without initrd. */ |
---|
284 | printk ("Your elilo is not Xen-aware. Bootparams fixed\n"); |
---|
285 | ia64_boot_param->domain_start = ia64_boot_param->initrd_start; |
---|
286 | ia64_boot_param->domain_size = ia64_boot_param->initrd_size; |
---|
287 | ia64_boot_param->initrd_start = 0; |
---|
288 | ia64_boot_param->initrd_size = 0; |
---|
289 | } |
---|
290 | |
---|
291 | printk("Xen command line: %s\n", saved_command_line); |
---|
292 | /* xenheap should be in same TR-covered range with xen image */ |
---|
293 | xenheap_phys_end = xen_pstart + xenheap_size; |
---|
294 | printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n", |
---|
295 | xen_pstart, xenheap_phys_end); |
---|
296 | |
---|
297 | xen_patch_kernel(); |
---|
298 | |
---|
299 | kern_md = md = efi_get_md(xen_pstart); |
---|
300 | md_end = __pa(ia64_imva(&_end)); |
---|
301 | relo_start = xenheap_phys_end; |
---|
302 | |
---|
303 | /* |
---|
304 | * Scan through the memory descriptors after the kernel |
---|
305 | * image to make sure we have enough room for the xenheap |
---|
306 | * area, pushing out whatever may already be there. |
---|
307 | */ |
---|
308 | while (relo_start + relo_size >= md_end) { |
---|
309 | md = efi_get_md(md_end); |
---|
310 | |
---|
311 | BUG_ON(!md); |
---|
312 | BUG_ON(!is_xenheap_usable_memory(md)); |
---|
313 | |
---|
314 | md_end = md->phys_addr + MD_SIZE(md); |
---|
315 | /* |
---|
316 | * The dom0 kernel or initrd could overlap, reserve space |
---|
317 | * at the end to relocate them later. |
---|
318 | */ |
---|
319 | if (md->type == EFI_LOADER_DATA) { |
---|
320 | /* Test for ranges we're not prepared to move */ |
---|
321 | BUG_ON(md_overlaps(md, __pa(ia64_boot_param)) || |
---|
322 | md_overlaps(md, ia64_boot_param->efi_memmap) || |
---|
323 | md_overlaps(md, ia64_boot_param->command_line)); |
---|
324 | |
---|
325 | relo_size += MD_SIZE(md); |
---|
326 | /* If range overlaps the end, push out the relocation start */ |
---|
327 | if (md_end > relo_start) |
---|
328 | relo_start = md_end; |
---|
329 | } |
---|
330 | } |
---|
331 | last_md = md; |
---|
332 | relo_end = relo_start + relo_size; |
---|
333 | |
---|
334 | md_end = __pa(ia64_imva(&_end)); |
---|
335 | |
---|
336 | /* |
---|
337 | * Move any relocated data out into the previously found relocation |
---|
338 | * area. Any extra memory descriptrs are moved out to the end |
---|
339 | * and set to zero pages. |
---|
340 | */ |
---|
341 | for (md = efi_get_md(md_end) ;; md = efi_get_md(md_end)) { |
---|
342 | md_end = md->phys_addr + MD_SIZE(md); |
---|
343 | |
---|
344 | if (md->type == EFI_LOADER_DATA) { |
---|
345 | unsigned long relo_offset; |
---|
346 | |
---|
347 | if (md_overlaps(md, ia64_boot_param->domain_start)) { |
---|
348 | relo_offset = ia64_boot_param->domain_start - md->phys_addr; |
---|
349 | printk("Moving Dom0 kernel image: 0x%lx -> 0x%lx (%ld KiB)\n", |
---|
350 | ia64_boot_param->domain_start, relo_start + relo_offset, |
---|
351 | ia64_boot_param->domain_size >> 10); |
---|
352 | ia64_boot_param->domain_start = relo_start + relo_offset; |
---|
353 | } |
---|
354 | if (ia64_boot_param->initrd_size && |
---|
355 | md_overlaps(md, ia64_boot_param->initrd_start)) { |
---|
356 | relo_offset = ia64_boot_param->initrd_start - md->phys_addr; |
---|
357 | printk("Moving Dom0 initrd image: 0x%lx -> 0x%lx (%ld KiB)\n", |
---|
358 | ia64_boot_param->initrd_start, relo_start + relo_offset, |
---|
359 | ia64_boot_param->initrd_size >> 10); |
---|
360 | ia64_boot_param->initrd_start = relo_start + relo_offset; |
---|
361 | } |
---|
362 | memcpy(__va(relo_start), __va(md->phys_addr), MD_SIZE(md)); |
---|
363 | relo_start += MD_SIZE(md); |
---|
364 | } |
---|
365 | |
---|
366 | if (md == kern_md) |
---|
367 | continue; |
---|
368 | if (md == last_md) |
---|
369 | break; |
---|
370 | |
---|
371 | md->phys_addr = relo_end; |
---|
372 | md->num_pages = 0; |
---|
373 | } |
---|
374 | |
---|
375 | /* Trim the last entry */ |
---|
376 | md->phys_addr = relo_end; |
---|
377 | md->num_pages = (md_end - relo_end) >> EFI_PAGE_SHIFT; |
---|
378 | |
---|
379 | /* |
---|
380 | * Expand the new kernel/xenheap (and maybe dom0/initrd) out to |
---|
381 | * the full size. This range will already be type EFI_LOADER_DATA, |
---|
382 | * therefore the xenheap area is now protected being allocated for |
---|
383 | * use by find_memmap_space() in efi.c |
---|
384 | */ |
---|
385 | kern_md->num_pages = (relo_end - kern_md->phys_addr) >> EFI_PAGE_SHIFT; |
---|
386 | |
---|
387 | reserve_memory(); |
---|
388 | |
---|
389 | /* first find highest page frame number */ |
---|
390 | max_page = 0; |
---|
391 | efi_memmap_walk(find_max_pfn, &max_page); |
---|
392 | printk("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page); |
---|
393 | efi_print(); |
---|
394 | |
---|
395 | xen_heap_start = memguard_init(ia64_imva(&_end)); |
---|
396 | printk("Before xen_heap_start: %p\n", xen_heap_start); |
---|
397 | xen_heap_start = __va(init_boot_allocator(__pa(xen_heap_start))); |
---|
398 | printk("After xen_heap_start: %p\n", xen_heap_start); |
---|
399 | |
---|
400 | efi_memmap_walk(filter_rsvd_memory, init_boot_pages); |
---|
401 | efi_memmap_walk(xen_count_pages, &nr_pages); |
---|
402 | |
---|
403 | printk("System RAM: %luMB (%lukB)\n", |
---|
404 | nr_pages >> (20 - PAGE_SHIFT), |
---|
405 | nr_pages << (PAGE_SHIFT - 10)); |
---|
406 | total_pages = nr_pages; |
---|
407 | |
---|
408 | init_frametable(); |
---|
409 | |
---|
410 | trap_init(); |
---|
411 | |
---|
412 | alloc_dom0(); |
---|
413 | |
---|
414 | end_boot_allocator(); |
---|
415 | |
---|
416 | init_xenheap_pages(__pa(xen_heap_start), xenheap_phys_end); |
---|
417 | printk("Xen heap: %luMB (%lukB)\n", |
---|
418 | (xenheap_phys_end-__pa(xen_heap_start)) >> 20, |
---|
419 | (xenheap_phys_end-__pa(xen_heap_start)) >> 10); |
---|
420 | |
---|
421 | late_setup_arch(&cmdline); |
---|
422 | |
---|
423 | scheduler_init(); |
---|
424 | idle_vcpu[0] = (struct vcpu*) ia64_r13; |
---|
425 | idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0); |
---|
426 | if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) ) |
---|
427 | BUG(); |
---|
428 | |
---|
429 | alloc_dom_xen_and_dom_io(); |
---|
430 | setup_per_cpu_areas(); |
---|
431 | mem_init(); |
---|
432 | |
---|
433 | local_irq_disable(); |
---|
434 | init_IRQ (); |
---|
435 | init_xen_time(); /* initialise the time */ |
---|
436 | timer_init(); |
---|
437 | |
---|
438 | rcu_init(); |
---|
439 | |
---|
440 | #ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK |
---|
441 | open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period); |
---|
442 | #endif |
---|
443 | |
---|
444 | #ifdef CONFIG_SMP |
---|
445 | if ( opt_nosmp ) |
---|
446 | { |
---|
447 | max_cpus = 0; |
---|
448 | smp_num_siblings = 1; |
---|
449 | //boot_cpu_data.x86_num_cores = 1; |
---|
450 | } |
---|
451 | |
---|
452 | /* A vcpu is created for the idle domain on every physical cpu. |
---|
453 | Limit the number of cpus to the maximum number of vcpus. */ |
---|
454 | if (max_cpus > MAX_VIRT_CPUS) |
---|
455 | max_cpus = MAX_VIRT_CPUS; |
---|
456 | |
---|
457 | smp_prepare_cpus(max_cpus); |
---|
458 | |
---|
459 | /* We aren't hotplug-capable yet. */ |
---|
460 | for_each_cpu ( i ) |
---|
461 | cpu_set(i, cpu_present_map); |
---|
462 | |
---|
463 | /* Enable IRQ to receive IPI (needed for ITC sync). */ |
---|
464 | local_irq_enable(); |
---|
465 | |
---|
466 | printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus); |
---|
467 | for_each_present_cpu ( i ) |
---|
468 | { |
---|
469 | if ( num_online_cpus() >= max_cpus ) |
---|
470 | break; |
---|
471 | if ( !cpu_online(i) ) { |
---|
472 | rcu_online_cpu(i); |
---|
473 | __cpu_up(i); |
---|
474 | } |
---|
475 | } |
---|
476 | |
---|
477 | local_irq_disable(); |
---|
478 | |
---|
479 | printk("Brought up %ld CPUs\n", (long)num_online_cpus()); |
---|
480 | smp_cpus_done(max_cpus); |
---|
481 | #endif |
---|
482 | |
---|
483 | initialise_gdb(); /* could be moved earlier */ |
---|
484 | |
---|
485 | do_initcalls(); |
---|
486 | sort_main_extable(); |
---|
487 | |
---|
488 | init_rid_allocator (); |
---|
489 | |
---|
490 | local_irq_enable(); |
---|
491 | |
---|
492 | if (opt_xencons) { |
---|
493 | initialize_keytable(); |
---|
494 | if (ns16550_com1_gsi) { |
---|
495 | if (opt_xencons_poll || |
---|
496 | iosapic_register_intr(ns16550_com1_gsi, |
---|
497 | ns16550_com1_polarity, |
---|
498 | ns16550_com1_trigger) < 0) { |
---|
499 | ns16550_com1.irq = 0; |
---|
500 | ns16550_init(0, &ns16550_com1); |
---|
501 | } |
---|
502 | } |
---|
503 | serial_init_postirq(); |
---|
504 | |
---|
505 | /* Hide the HCDP table from dom0 */ |
---|
506 | efi.hcdp = NULL; |
---|
507 | } |
---|
508 | |
---|
509 | expose_p2m_init(); |
---|
510 | |
---|
511 | /* Create initial domain 0. */ |
---|
512 | dom0 = domain_create(0, 0, DOM0_SSIDREF); |
---|
513 | if (dom0 == NULL) |
---|
514 | panic("Error creating domain 0\n"); |
---|
515 | dom0_vcpu0 = alloc_vcpu(dom0, 0, 0); |
---|
516 | if (dom0_vcpu0 == NULL || vcpu_late_initialise(dom0_vcpu0) != 0) |
---|
517 | panic("Cannot allocate dom0 vcpu 0\n"); |
---|
518 | |
---|
519 | dom0->is_privileged = 1; |
---|
520 | |
---|
521 | /* |
---|
522 | * We're going to setup domain0 using the module(s) that we stashed safely |
---|
523 | * above our heap. The second module, if present, is an initrd ramdisk. |
---|
524 | */ |
---|
525 | dom0_memory_start = (unsigned long) __va(ia64_boot_param->domain_start); |
---|
526 | dom0_memory_size = ia64_boot_param->domain_size; |
---|
527 | dom0_initrd_start = (unsigned long) __va(ia64_boot_param->initrd_start); |
---|
528 | dom0_initrd_size = ia64_boot_param->initrd_size; |
---|
529 | |
---|
530 | if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_size, |
---|
531 | dom0_initrd_start,dom0_initrd_size, |
---|
532 | 0) != 0) |
---|
533 | panic("Could not set up DOM0 guest OS\n"); |
---|
534 | |
---|
535 | if (!running_on_sim) // slow on ski and pages are pre-initialized to zero |
---|
536 | scrub_heap_pages(); |
---|
537 | |
---|
538 | init_trace_bufs(); |
---|
539 | |
---|
540 | if (opt_xencons) { |
---|
541 | console_endboot(); |
---|
542 | serial_endboot(); |
---|
543 | } |
---|
544 | |
---|
545 | domain0_ready = 1; |
---|
546 | |
---|
547 | domain_unpause_by_systemcontroller(dom0); |
---|
548 | |
---|
549 | startup_cpu_idle_loop(); |
---|
550 | } |
---|
551 | |
---|
552 | void arch_get_xen_caps(xen_capabilities_info_t *info) |
---|
553 | { |
---|
554 | /* Interface name is always xen-3.0-* for Xen-3.x. */ |
---|
555 | int major = 3, minor = 0; |
---|
556 | char s[32]; |
---|
557 | |
---|
558 | (*info)[0] = '\0'; |
---|
559 | |
---|
560 | snprintf(s, sizeof(s), "xen-%d.%d-ia64 ", major, minor); |
---|
561 | safe_strcat(*info, s); |
---|
562 | |
---|
563 | snprintf(s, sizeof(s), "xen-%d.%d-ia64be ", major, minor); |
---|
564 | safe_strcat(*info, s); |
---|
565 | |
---|
566 | if (vmx_enabled) |
---|
567 | { |
---|
568 | snprintf(s, sizeof(s), "hvm-%d.%d-ia64 ", major, minor); |
---|
569 | safe_strcat(*info, s); |
---|
570 | } |
---|
571 | } |
---|
572 | |
---|