debuggers.hg

view tools/firmware/hvmloader/hvmloader.c @ 19992:8ce42378828b

hvmloader: Add new test for MSR_SHADOW_GS_BASE validity after SWAPGS instruction.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jul 16 10:30:50 2009 +0100 (2009-07-16)
parents 80839a223746
children 05f3ca68f62d
line source
1 /*
2 * hvmloader.c: HVM bootloader.
3 *
4 * Leendert van Doorn, leendert@watson.ibm.com
5 * Copyright (c) 2005, International Business Machines Corporation.
6 *
7 * Copyright (c) 2006, Keir Fraser, XenSource Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20 * Place - Suite 330, Boston, MA 02111-1307 USA.
21 */
23 #include "roms.h"
24 #include "acpi/acpi2_0.h"
25 #include "util.h"
26 #include "hypercall.h"
27 #include "config.h"
28 #include "apic_regs.h"
29 #include "pci_regs.h"
30 #include "e820.h"
31 #include "option_rom.h"
32 #include <xen/version.h>
33 #include <xen/hvm/params.h>
34 #include <xen/memory.h>
36 asm (
37 " .text \n"
38 " .globl _start \n"
39 "_start: \n"
40 /* C runtime kickoff. */
41 " cld \n"
42 " cli \n"
43 " lgdt gdt_desr \n"
44 " mov $"STR(SEL_DATA32)",%ax \n"
45 " mov %ax,%ds \n"
46 " mov %ax,%es \n"
47 " mov %ax,%fs \n"
48 " mov %ax,%gs \n"
49 " mov %ax,%ss \n"
50 " ljmp $"STR(SEL_CODE32)",$1f \n"
51 "1: movl $stack_top,%esp \n"
52 " movl %esp,%ebp \n"
53 " call main \n"
54 /* Relocate real-mode trampoline to 0x0. */
55 " mov $trampoline_start,%esi \n"
56 " xor %edi,%edi \n"
57 " mov $trampoline_end,%ecx \n"
58 " sub %esi,%ecx \n"
59 " rep movsb \n"
60 /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */
61 " mov $"STR(SEL_DATA16)",%ax \n"
62 " mov %ax,%ds \n"
63 " mov %ax,%es \n"
64 " mov %ax,%fs \n"
65 " mov %ax,%gs \n"
66 " mov %ax,%ss \n"
67 /* Initialise all 32-bit GPRs to zero. */
68 " xor %eax,%eax \n"
69 " xor %ebx,%ebx \n"
70 " xor %ecx,%ecx \n"
71 " xor %edx,%edx \n"
72 " xor %esp,%esp \n"
73 " xor %ebp,%ebp \n"
74 " xor %esi,%esi \n"
75 " xor %edi,%edi \n"
76 /* Enter real mode, reload all segment registers and IDT. */
77 " ljmp $"STR(SEL_CODE16)",$0x0\n"
78 "trampoline_start: .code16 \n"
79 " mov %eax,%cr0 \n"
80 " ljmp $0,$1f-trampoline_start\n"
81 "1: mov %ax,%ds \n"
82 " mov %ax,%es \n"
83 " mov %ax,%fs \n"
84 " mov %ax,%gs \n"
85 " mov %ax,%ss \n"
86 " lidt 1f-trampoline_start \n"
87 " ljmp $0xf000,$0xfff0 \n"
88 "1: .word 0x3ff,0,0 \n"
89 "trampoline_end: .code32 \n"
90 " \n"
91 "gdt_desr: \n"
92 " .word gdt_end - gdt - 1 \n"
93 " .long gdt \n"
94 " \n"
95 " .align 8 \n"
96 "gdt: \n"
97 " .quad 0x0000000000000000 \n"
98 " .quad 0x008f9a000000ffff \n" /* Ring 0 16b code, base 0 limit 4G */
99 " .quad 0x008f92000000ffff \n" /* Ring 0 16b data, base 0 limit 4G */
100 " .quad 0x00cf9a000000ffff \n" /* Ring 0 32b code, base 0 limit 4G */
101 " .quad 0x00cf92000000ffff \n" /* Ring 0 32b data, base 0 limit 4G */
102 " .quad 0x00af9a000000ffff \n" /* Ring 0 64b code */
103 "gdt_end: \n"
104 " \n"
105 " .bss \n"
106 " .align 8 \n"
107 "stack: \n"
108 " .skip 0x4000 \n"
109 "stack_top: \n"
110 " .text \n"
111 );
113 unsigned long pci_mem_start = PCI_MEM_START;
114 unsigned long pci_mem_end = PCI_MEM_END;
116 static enum { VGA_none, VGA_std, VGA_cirrus } virtual_vga = VGA_none;
118 static void init_hypercalls(void)
119 {
120 uint32_t eax, ebx, ecx, edx;
121 unsigned long i;
122 char signature[13];
123 xen_extraversion_t extraversion;
124 uint32_t base;
126 for ( base = 0x40000000; base < 0x40001000; base += 0x100 )
127 {
128 cpuid(base, &eax, &ebx, &ecx, &edx);
130 *(uint32_t *)(signature + 0) = ebx;
131 *(uint32_t *)(signature + 4) = ecx;
132 *(uint32_t *)(signature + 8) = edx;
133 signature[12] = '\0';
135 if ( !strcmp("XenVMMXenVMM", signature) )
136 break;
137 }
139 BUG_ON(strcmp("XenVMMXenVMM", signature) || ((eax - base) < 2));
141 /* Fill in hypercall transfer pages. */
142 cpuid(base + 2, &eax, &ebx, &ecx, &edx);
143 for ( i = 0; i < eax; i++ )
144 wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
146 /* Print version information. */
147 cpuid(base + 1, &eax, &ebx, &ecx, &edx);
148 hypercall_xen_version(XENVER_extraversion, extraversion);
149 printf("Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
150 }
152 static void apic_setup(void)
153 {
154 /* Set the IOAPIC ID to the static value used in the MP/ACPI tables. */
155 ioapic_write(0x00, IOAPIC_ID);
157 /* NMIs are delivered direct to the BSP. */
158 lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF);
159 lapic_write(APIC_LVT0, (APIC_MODE_EXTINT << 8) | APIC_LVT_MASKED);
160 lapic_write(APIC_LVT1, APIC_MODE_NMI << 8);
162 /* 8259A ExtInts are delivered through IOAPIC pin 0 (Virtual Wire Mode). */
163 ioapic_write(0x10, APIC_DM_EXTINT);
164 ioapic_write(0x11, SET_APIC_ID(LAPIC_ID(0)));
165 }
167 static void pci_setup(void)
168 {
169 uint32_t base, devfn, bar_reg, bar_data, bar_sz, cmd, mmio_total = 0;
170 uint16_t class, vendor_id, device_id;
171 unsigned int bar, pin, link, isa_irq;
173 /* Resources assignable to PCI devices via BARs. */
174 struct resource {
175 uint32_t base, max;
176 } *resource, mem_resource, io_resource;
178 /* Create a list of device BARs in descending order of size. */
179 struct bars {
180 uint32_t devfn, bar_reg, bar_sz;
181 } *bars = (struct bars *)SCRATCH_PHYSICAL_ADDRESS;
182 unsigned int i, nr_bars = 0;
184 /* Program PCI-ISA bridge with appropriate link routes. */
185 isa_irq = 0;
186 for ( link = 0; link < 4; link++ )
187 {
188 do { isa_irq = (isa_irq + 1) & 15;
189 } while ( !(PCI_ISA_IRQ_MASK & (1U << isa_irq)) );
190 pci_writeb(PCI_ISA_DEVFN, 0x60 + link, isa_irq);
191 printf("PCI-ISA link %u routed to IRQ%u\n", link, isa_irq);
192 }
194 /* Program ELCR to match PCI-wired IRQs. */
195 outb(0x4d0, (uint8_t)(PCI_ISA_IRQ_MASK >> 0));
196 outb(0x4d1, (uint8_t)(PCI_ISA_IRQ_MASK >> 8));
198 /* Scan the PCI bus and map resources. */
199 for ( devfn = 0; devfn < 128; devfn++ )
200 {
201 class = pci_readw(devfn, PCI_CLASS_DEVICE);
202 vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
203 device_id = pci_readw(devfn, PCI_DEVICE_ID);
204 if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
205 continue;
207 ASSERT((devfn != PCI_ISA_DEVFN) ||
208 ((vendor_id == 0x8086) && (device_id == 0x7000)));
210 switch ( class )
211 {
212 case 0x0300:
213 if ( (vendor_id == 0x1234) && (device_id == 0x1111) )
214 virtual_vga = VGA_std;
215 if ( (vendor_id == 0x1013) && (device_id == 0xb8) )
216 virtual_vga = VGA_cirrus;
217 break;
218 case 0x0680:
219 /* PIIX4 ACPI PM. Special device with special PCI config space. */
220 ASSERT((vendor_id == 0x8086) && (device_id == 0x7113));
221 pci_writew(devfn, 0x20, 0x0000); /* No smb bus IO enable */
222 pci_writew(devfn, 0x22, 0x0000);
223 pci_writew(devfn, 0x3c, 0x0009); /* Hardcoded IRQ9 */
224 pci_writew(devfn, 0x3d, 0x0001);
225 break;
226 case 0x0101:
227 if ( vendor_id == 0x8086 )
228 {
229 /* Intel ICHs since PIIX3: enable IDE legacy mode. */
230 pci_writew(devfn, 0x40, 0x8000); /* enable IDE0 */
231 pci_writew(devfn, 0x42, 0x8000); /* enable IDE1 */
232 }
233 break;
234 }
236 /* Map the I/O memory and port resources. */
237 for ( bar = 0; bar < 7; bar++ )
238 {
239 bar_reg = PCI_BASE_ADDRESS_0 + 4*bar;
240 if ( bar == 6 )
241 bar_reg = PCI_ROM_ADDRESS;
243 bar_data = pci_readl(devfn, bar_reg);
244 pci_writel(devfn, bar_reg, ~0);
245 bar_sz = pci_readl(devfn, bar_reg);
246 pci_writel(devfn, bar_reg, bar_data);
247 if ( bar_sz == 0 )
248 continue;
250 bar_sz &= (((bar_data & PCI_BASE_ADDRESS_SPACE) ==
251 PCI_BASE_ADDRESS_SPACE_MEMORY) ?
252 PCI_BASE_ADDRESS_MEM_MASK :
253 (PCI_BASE_ADDRESS_IO_MASK & 0xffff));
254 bar_sz &= ~(bar_sz - 1);
256 for ( i = 0; i < nr_bars; i++ )
257 if ( bars[i].bar_sz < bar_sz )
258 break;
260 if ( i != nr_bars )
261 memmove(&bars[i+1], &bars[i], (nr_bars-i) * sizeof(*bars));
263 bars[i].devfn = devfn;
264 bars[i].bar_reg = bar_reg;
265 bars[i].bar_sz = bar_sz;
267 if ( (bar_data & PCI_BASE_ADDRESS_SPACE) ==
268 PCI_BASE_ADDRESS_SPACE_MEMORY )
269 mmio_total += bar_sz;
271 nr_bars++;
273 /* Skip the upper-half of the address for a 64-bit BAR. */
274 if ( (bar_data & (PCI_BASE_ADDRESS_SPACE |
275 PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
276 (PCI_BASE_ADDRESS_SPACE_MEMORY |
277 PCI_BASE_ADDRESS_MEM_TYPE_64) )
278 bar++;
279 }
281 /* Map the interrupt. */
282 pin = pci_readb(devfn, PCI_INTERRUPT_PIN);
283 if ( pin != 0 )
284 {
285 /* This is the barber's pole mapping used by Xen. */
286 link = ((pin - 1) + (devfn >> 3)) & 3;
287 isa_irq = pci_readb(PCI_ISA_DEVFN, 0x60 + link);
288 pci_writeb(devfn, PCI_INTERRUPT_LINE, isa_irq);
289 printf("pci dev %02x:%x INT%c->IRQ%u\n",
290 devfn>>3, devfn&7, 'A'+pin-1, isa_irq);
291 }
293 /* Enable bus mastering. */
294 cmd = pci_readw(devfn, PCI_COMMAND);
295 cmd |= PCI_COMMAND_MASTER;
296 pci_writew(devfn, PCI_COMMAND, cmd);
297 }
299 while ( (mmio_total > (pci_mem_end - pci_mem_start)) &&
300 ((pci_mem_start << 1) != 0) )
301 pci_mem_start <<= 1;
303 while ( (pci_mem_start >> PAGE_SHIFT) < hvm_info->low_mem_pgend )
304 {
305 struct xen_add_to_physmap xatp;
306 if ( hvm_info->high_mem_pgend == 0 )
307 hvm_info->high_mem_pgend = 1ull << (32 - PAGE_SHIFT);
308 xatp.domid = DOMID_SELF;
309 xatp.space = XENMAPSPACE_gmfn;
310 xatp.idx = --hvm_info->low_mem_pgend;
311 xatp.gpfn = hvm_info->high_mem_pgend++;
312 if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )
313 BUG();
314 }
316 mem_resource.base = pci_mem_start;
317 mem_resource.max = pci_mem_end;
318 io_resource.base = 0xc000;
319 io_resource.max = 0x10000;
321 /* Assign iomem and ioport resources in descending order of size. */
322 for ( i = 0; i < nr_bars; i++ )
323 {
324 devfn = bars[i].devfn;
325 bar_reg = bars[i].bar_reg;
326 bar_sz = bars[i].bar_sz;
328 bar_data = pci_readl(devfn, bar_reg);
330 if ( (bar_data & PCI_BASE_ADDRESS_SPACE) ==
331 PCI_BASE_ADDRESS_SPACE_MEMORY )
332 {
333 resource = &mem_resource;
334 bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK;
335 }
336 else
337 {
338 resource = &io_resource;
339 bar_data &= ~PCI_BASE_ADDRESS_IO_MASK;
340 }
342 base = (resource->base + bar_sz - 1) & ~(bar_sz - 1);
343 bar_data |= base;
344 base += bar_sz;
346 if ( (base < resource->base) || (base > resource->max) )
347 {
348 printf("pci dev %02x:%x bar %02x size %08x: no space for "
349 "resource!\n", devfn>>3, devfn&7, bar_reg, bar_sz);
350 continue;
351 }
353 resource->base = base;
355 pci_writel(devfn, bar_reg, bar_data);
356 printf("pci dev %02x:%x bar %02x size %08x: %08x\n",
357 devfn>>3, devfn&7, bar_reg, bar_sz, bar_data);
359 /* Now enable the memory or I/O mapping. */
360 cmd = pci_readw(devfn, PCI_COMMAND);
361 if ( (bar_reg == PCI_ROM_ADDRESS) ||
362 ((bar_data & PCI_BASE_ADDRESS_SPACE) ==
363 PCI_BASE_ADDRESS_SPACE_MEMORY) )
364 cmd |= PCI_COMMAND_MEMORY;
365 else
366 cmd |= PCI_COMMAND_IO;
367 pci_writew(devfn, PCI_COMMAND, cmd);
368 }
369 }
371 /*
372 * Scan the list of Option ROMs at @roms for one which supports
373 * PCI (@vendor_id, @device_id) found at slot @devfn. If one is found,
374 * copy it to @dest and return its size rounded up to a multiple 2kB. This
375 * function will not copy ROMs beyond address OPTIONROM_PHYSICAL_END.
376 */
377 #define round_option_rom(x) (((x) + 2047) & ~2047)
378 static int scan_option_rom(
379 uint8_t devfn, uint16_t vendor_id, uint16_t device_id,
380 void *roms, uint32_t dest)
381 {
382 struct option_rom_header *rom;
383 struct option_rom_pnp_header *pnph;
384 struct option_rom_pci_header *pcih;
385 uint8_t csum;
386 int i;
388 static uint32_t orom_ids[64];
389 static int nr_roms;
391 /* Avoid duplicate ROMs. */
392 for ( i = 0; i < nr_roms; i++ )
393 if ( orom_ids[i] == (vendor_id | ((uint32_t)device_id << 16)) )
394 return 0;
396 rom = roms;
397 for ( ; ; )
398 {
399 /* Invalid signature means we're out of option ROMs. */
400 if ( strncmp((char *)rom->signature, "\x55\xaa", 2) ||
401 (rom->rom_size == 0) )
402 break;
404 /* Invalid checksum means we're out of option ROMs. */
405 csum = 0;
406 for ( i = 0; i < (rom->rom_size * 512); i++ )
407 csum += ((uint8_t *)rom)[i];
408 if ( csum != 0 )
409 break;
411 /* Check the PCI PnP header (if any) for a match. */
412 pcih = (struct option_rom_pci_header *)
413 ((char *)rom + rom->pci_header_offset);
414 if ( (rom->pci_header_offset != 0) &&
415 !strncmp((char *)pcih->signature, "PCIR", 4) &&
416 (pcih->vendor_id == vendor_id) &&
417 (pcih->device_id == device_id) )
418 goto found;
420 rom = (struct option_rom_header *)
421 ((char *)rom + rom->rom_size * 512);
422 }
424 return 0;
426 found:
427 /* Find the PnP expansion header (if any). */
428 pnph = ((rom->expansion_header_offset != 0)
429 ? ((struct option_rom_pnp_header *)
430 ((char *)rom + rom->expansion_header_offset))
431 : ((struct option_rom_pnp_header *)NULL));
432 while ( (pnph != NULL) && strncmp((char *)pnph->signature, "$PnP", 4) )
433 pnph = ((pnph->next_header_offset != 0)
434 ? ((struct option_rom_pnp_header *)
435 ((char *)rom + pnph->next_header_offset))
436 : ((struct option_rom_pnp_header *)NULL));
438 printf("Loading PCI Option ROM ...\n");
439 if ( (pnph != NULL) && (pnph->manufacturer_name_offset != 0) )
440 printf(" - Manufacturer: %s\n",
441 (char *)rom + pnph->manufacturer_name_offset);
442 if ( (pnph != NULL) && (pnph->product_name_offset != 0) )
443 printf(" - Product name: %s\n",
444 (char *)rom + pnph->product_name_offset);
446 if ( (dest + rom->rom_size * 512 + 1) > OPTIONROM_PHYSICAL_END )
447 {
448 printf("Option ROM size %x exceeds available space\n",
449 rom->rom_size * 512);
450 return 0;
451 }
453 orom_ids[nr_roms++] = vendor_id | ((uint32_t)device_id << 16);
454 memcpy((void *)dest, rom, rom->rom_size * 512);
455 *(uint8_t *)(dest + rom->rom_size * 512) = devfn;
456 return round_option_rom(rom->rom_size * 512 + 1);
457 }
459 /*
460 * Scan the PCI bus for the first NIC supported by etherboot, and copy
461 * the corresponding rom data to *copy_rom_dest. Returns the length of the
462 * selected rom, or 0 if no NIC found.
463 */
464 static int scan_etherboot_nic(uint32_t copy_rom_dest)
465 {
466 uint8_t devfn;
467 uint16_t class, vendor_id, device_id;
468 int rom_size = 0;
470 for ( devfn = 0; (devfn < 128) && !rom_size; devfn++ )
471 {
472 class = pci_readw(devfn, PCI_CLASS_DEVICE);
473 vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
474 device_id = pci_readw(devfn, PCI_DEVICE_ID);
476 /* We're only interested in NICs. */
477 if ( (vendor_id != 0xffff) &&
478 (device_id != 0xffff) &&
479 (class == 0x0200) )
480 rom_size = scan_option_rom(
481 devfn, vendor_id, device_id, etherboot, copy_rom_dest);
482 }
484 return rom_size;
485 }
487 /*
488 * Scan the PCI bus for the devices that have an option ROM, and copy
489 * the corresponding rom data to rom_phys_addr.
490 */
491 static int pci_load_option_roms(uint32_t rom_base_addr)
492 {
493 uint32_t option_rom_addr, rom_phys_addr = rom_base_addr;
494 uint16_t vendor_id, device_id;
495 uint8_t devfn, class;
497 for ( devfn = 0; devfn < 128; devfn++ )
498 {
499 class = pci_readb(devfn, PCI_CLASS_DEVICE + 1);
500 vendor_id = pci_readw(devfn, PCI_VENDOR_ID);
501 device_id = pci_readw(devfn, PCI_DEVICE_ID);
503 if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
504 continue;
506 /*
507 * Currently only scan options from mass storage devices and serial
508 * bus controller (Fibre Channel included).
509 */
510 if ( (class != 0x1) && (class != 0xc) )
511 continue;
513 option_rom_addr = pci_readl(devfn, PCI_ROM_ADDRESS);
514 if ( !option_rom_addr )
515 continue;
517 /* Ensure Expansion Bar is enabled before copying */
518 pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr | 0x1);
520 rom_phys_addr += scan_option_rom(
521 devfn, vendor_id, device_id,
522 (void *)(option_rom_addr & ~2047), rom_phys_addr);
524 /* Restore the default original value of Expansion Bar */
525 pci_writel(devfn, PCI_ROM_ADDRESS, option_rom_addr);
526 }
528 return rom_phys_addr - rom_base_addr;
529 }
531 /* Replace possibly erroneous memory-size CMOS fields with correct values. */
532 static void cmos_write_memory_size(void)
533 {
534 uint32_t base_mem = 640, ext_mem, alt_mem;
536 alt_mem = ext_mem = hvm_info->low_mem_pgend << PAGE_SHIFT;
537 ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
538 if ( ext_mem > 0xffff )
539 ext_mem = 0xffff;
540 alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
542 /* All BIOSes: conventional memory (CMOS *always* reports 640kB). */
543 cmos_outb(0x15, (uint8_t)(base_mem >> 0));
544 cmos_outb(0x16, (uint8_t)(base_mem >> 8));
546 /* All BIOSes: extended memory (1kB chunks above 1MB). */
547 cmos_outb(0x17, (uint8_t)( ext_mem >> 0));
548 cmos_outb(0x18, (uint8_t)( ext_mem >> 8));
549 cmos_outb(0x30, (uint8_t)( ext_mem >> 0));
550 cmos_outb(0x31, (uint8_t)( ext_mem >> 8));
552 /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */
553 cmos_outb(0x34, (uint8_t)( alt_mem >> 0));
554 cmos_outb(0x35, (uint8_t)( alt_mem >> 8));
555 }
557 /*
558 * Set up an empty TSS area for virtual 8086 mode to use.
559 * The only important thing is that it musn't have any bits set
560 * in the interrupt redirection bitmap, so all zeros will do.
561 */
562 static void init_vm86_tss(void)
563 {
564 void *tss;
565 struct xen_hvm_param p;
567 tss = mem_alloc(128, 128);
568 memset(tss, 0, 128);
569 p.domid = DOMID_SELF;
570 p.index = HVM_PARAM_VM86_TSS;
571 p.value = virt_to_phys(tss);
572 hypercall_hvm_op(HVMOP_set_param, &p);
573 printf("vm86 TSS at %08lx\n", virt_to_phys(tss));
574 }
576 /* Create an E820 table based on memory parameters provided in hvm_info. */
577 static void build_e820_table(void)
578 {
579 struct e820entry *e820 = E820;
580 unsigned int nr = 0;
582 /* 0x0-0x9FC00: Ordinary RAM. */
583 e820[nr].addr = 0x0;
584 e820[nr].size = 0x9FC00;
585 e820[nr].type = E820_RAM;
586 nr++;
588 /* 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). */
589 e820[nr].addr = 0x9FC00;
590 e820[nr].size = 0x400;
591 e820[nr].type = E820_RESERVED;
592 nr++;
594 /*
595 * Following regions are standard regions of the PC memory map.
596 * They are not covered by e820 regions. OSes will not use as RAM.
597 * 0xA0000-0xC0000: VGA memory-mapped I/O. Not covered by E820.
598 * 0xC0000-0xE0000: 16-bit devices, expansion ROMs (inc. vgabios).
599 * TODO: free pages which turn out to be unused.
600 */
602 /*
603 * 0xE0000-0x0F0000: PC-specific area. We place various tables here.
604 * 0xF0000-0x100000: System BIOS.
605 * TODO: free pages which turn out to be unused.
606 */
607 e820[nr].addr = 0xE0000;
608 e820[nr].size = 0x20000;
609 e820[nr].type = E820_RESERVED;
610 nr++;
612 /* Low RAM goes here. Reserve space for special pages. */
613 BUG_ON((hvm_info->low_mem_pgend << PAGE_SHIFT) < (2u << 20));
614 e820[nr].addr = 0x100000;
615 e820[nr].size = (hvm_info->low_mem_pgend << PAGE_SHIFT) - e820[nr].addr;
616 e820[nr].type = E820_RAM;
617 nr++;
619 /*
620 * Explicitly reserve space for special pages.
621 * This space starts at RESERVED_MEMBASE an extends to cover various
622 * fixed hardware mappings (e.g., LAPIC, IOAPIC, default SVGA framebuffer).
623 */
624 e820[nr].addr = RESERVED_MEMBASE;
625 e820[nr].size = (uint32_t)-e820[nr].addr;
626 e820[nr].type = E820_RESERVED;
627 nr++;
629 if ( hvm_info->high_mem_pgend )
630 {
631 e820[nr].addr = ((uint64_t)1 << 32);
632 e820[nr].size =
633 ((uint64_t)hvm_info->high_mem_pgend << PAGE_SHIFT) - e820[nr].addr;
634 e820[nr].type = E820_RAM;
635 nr++;
636 }
638 *E820_NR = nr;
639 }
641 int main(void)
642 {
643 int option_rom_sz = 0, vgabios_sz = 0, etherboot_sz = 0;
644 int rombios_sz, smbios_sz;
645 uint32_t etherboot_phys_addr, option_rom_phys_addr, bios32_addr;
646 struct bios_info *bios_info;
648 printf("HVM Loader\n");
650 init_hypercalls();
652 printf("CPU speed is %u MHz\n", get_cpu_mhz());
654 apic_setup();
655 pci_setup();
657 smp_initialise();
659 perform_tests();
661 printf("Writing SMBIOS tables ...\n");
662 smbios_sz = hvm_write_smbios_tables();
664 printf("Loading ROMBIOS ...\n");
665 rombios_sz = sizeof(rombios);
666 if ( rombios_sz > 0x10000 )
667 rombios_sz = 0x10000;
668 memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, rombios_sz);
669 bios32_addr = highbios_setup();
671 if ( (hvm_info->nr_vcpus > 1) || hvm_info->apic_mode )
672 create_mp_tables();
674 switch ( virtual_vga )
675 {
676 case VGA_cirrus:
677 printf("Loading Cirrus VGABIOS ...\n");
678 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
679 vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
680 vgabios_sz = round_option_rom(sizeof(vgabios_cirrusvga));
681 break;
682 case VGA_std:
683 printf("Loading Standard VGABIOS ...\n");
684 memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
685 vgabios_stdvga, sizeof(vgabios_stdvga));
686 vgabios_sz = round_option_rom(sizeof(vgabios_stdvga));
687 break;
688 default:
689 printf("No emulated VGA adaptor ...\n");
690 break;
691 }
693 etherboot_phys_addr = VGABIOS_PHYSICAL_ADDRESS + vgabios_sz;
694 if ( etherboot_phys_addr < OPTIONROM_PHYSICAL_ADDRESS )
695 etherboot_phys_addr = OPTIONROM_PHYSICAL_ADDRESS;
696 etherboot_sz = scan_etherboot_nic(etherboot_phys_addr);
698 option_rom_phys_addr = etherboot_phys_addr + etherboot_sz;
699 option_rom_sz = pci_load_option_roms(option_rom_phys_addr);
701 if ( hvm_info->acpi_enabled )
702 {
703 printf("Loading ACPI ...\n");
704 acpi_build_tables();
705 }
707 init_vm86_tss();
709 cmos_write_memory_size();
711 printf("BIOS map:\n");
712 if ( vgabios_sz )
713 printf(" %05x-%05x: VGA BIOS\n",
714 VGABIOS_PHYSICAL_ADDRESS,
715 VGABIOS_PHYSICAL_ADDRESS + vgabios_sz - 1);
716 if ( etherboot_sz )
717 printf(" %05x-%05x: Etherboot ROM\n",
718 etherboot_phys_addr,
719 etherboot_phys_addr + etherboot_sz - 1);
720 if ( option_rom_sz )
721 printf(" %05x-%05x: PCI Option ROMs\n",
722 option_rom_phys_addr,
723 option_rom_phys_addr + option_rom_sz - 1);
724 if ( smbios_sz )
725 printf(" %05x-%05x: SMBIOS tables\n",
726 SMBIOS_PHYSICAL_ADDRESS,
727 SMBIOS_PHYSICAL_ADDRESS + smbios_sz - 1);
728 if ( rombios_sz )
729 printf(" %05x-%05x: Main BIOS\n",
730 ROMBIOS_PHYSICAL_ADDRESS,
731 ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1);
733 build_e820_table();
735 bios_info = (struct bios_info *)BIOS_INFO_PHYSICAL_ADDRESS;
736 memset(bios_info, 0, sizeof(*bios_info));
737 bios_info->com1_present = uart_exists(0x3f8);
738 bios_info->com2_present = uart_exists(0x2f8);
739 bios_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS);
740 bios_info->pci_min = pci_mem_start;
741 bios_info->pci_len = pci_mem_end - pci_mem_start;
742 bios_info->bios32_entry = bios32_addr;
744 printf("Invoking ROMBIOS ...\n");
745 return 0;
746 }
748 /*
749 * Local variables:
750 * mode: C
751 * c-set-style: "BSD"
752 * c-basic-offset: 4
753 * tab-width: 4
754 * indent-tabs-mode: nil
755 * End:
756 */