]> xenbits.xensource.com Git - seabios.git/commitdiff
Initial KVM support.
authorKevin O'Connor <kevin@koconnor.net>
Mon, 5 Jan 2009 02:48:22 +0000 (21:48 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Mon, 5 Jan 2009 02:48:22 +0000 (21:48 -0500)
Add some of the enhancements KVM has to their bochs bios tree.  This
    is only partial support for KVM - some features still do not work
    correctly.

Makefile
src/acpi.c
src/config.h
src/mtrr.c [new file with mode: 0644]
src/pciinit.c
src/post.c
src/util.h

index 4c1b516e6c0bee3def0e587033ea79cad56af792..a6473d731154ce5d3612e838a0ceac3b1c9ac853 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ SRCBOTH=output.c util.c floppy.c ata.c system.c mouse.c kbd.c pci.c \
         pnpbios.c pirtable.c
 SRC16=$(SRCBOTH) disk.c apm.c pcibios.c vgahooks.c
 SRC32=$(SRCBOTH) post.c shadow.c post_menu.c memmap.c coreboot.c boot.c \
-      acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c
+      acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c
 TABLESRC=font.c cbt.c floppy_dbt.c
 
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
index 0daa3f6b7d413d2d6d9bdfd4433a1a0461f1af17..cf8e3fa01431a73c205ec95f0296a8ec5ae5d052 100644 (file)
@@ -197,6 +197,21 @@ struct madt_io_apic
                          * lines start */
 };
 
+#if CONFIG_KVM
+/* IRQs 5,9,10,11 */
+#define PCI_ISA_IRQ_MASK    0x0e20
+#else
+#define PCI_ISA_IRQ_MASK    0x0000
+#endif
+
+struct madt_intsrcovr {
+    APIC_HEADER_DEF
+    u8  bus;
+    u8  source;
+    u32 gsi;
+    u16 flags;
+} PACKED;
+
 #include "acpi-dsdt.hex"
 
 static inline u16 cpu_to_le16(u16 x)
@@ -398,32 +413,44 @@ void acpi_bios_init(void)
     memcpy(dsdt, AmlCode, sizeof(AmlCode));
 
     /* MADT */
-    {
-        struct madt_processor_apic *apic;
-        struct madt_io_apic *io_apic;
-
-        memset(madt, 0, madt_size);
-        madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
-        madt->flags = cpu_to_le32(1);
-        apic = (void *)(madt + 1);
-        for(i=0;i<smp_cpus;i++) {
-            apic->type = APIC_PROCESSOR;
-            apic->length = sizeof(*apic);
-            apic->processor_id = i;
-            apic->local_apic_id = i;
-            apic->flags = cpu_to_le32(1);
-            apic++;
+    memset(madt, 0, madt_size);
+    madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
+    madt->flags = cpu_to_le32(1);
+    struct madt_processor_apic *apic = (void *)(madt + 1);
+    for(i=0;i<smp_cpus;i++) {
+        apic->type = APIC_PROCESSOR;
+        apic->length = sizeof(*apic);
+        apic->processor_id = i;
+        apic->local_apic_id = i;
+        apic->flags = cpu_to_le32(1);
+        apic++;
+    }
+    struct madt_io_apic *io_apic = (void *)apic;
+    io_apic->type = APIC_IO;
+    io_apic->length = sizeof(*io_apic);
+    io_apic->io_apic_id = smp_cpus;
+    io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
+    io_apic->interrupt = cpu_to_le32(0);
+
+    struct madt_intsrcovr *intsrcovr = (struct madt_intsrcovr*)(io_apic + 1);
+    for (i = 0; i < 16; i++) {
+        if (PCI_ISA_IRQ_MASK & (1 << i)) {
+            memset(intsrcovr, 0, sizeof(*intsrcovr));
+            intsrcovr->type   = APIC_XRUPT_OVERRIDE;
+            intsrcovr->length = sizeof(*intsrcovr);
+            intsrcovr->source = i;
+            intsrcovr->gsi    = i;
+            intsrcovr->flags  = 0xd; /* active high, level triggered */
+        } else {
+            /* No need for a INT source override structure. */
+            continue;
         }
-        io_apic = (void *)apic;
-        io_apic->type = APIC_IO;
-        io_apic->length = sizeof(*io_apic);
-        io_apic->io_apic_id = smp_cpus;
-        io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
-        io_apic->interrupt = cpu_to_le32(0);
-
-        acpi_build_table_header((struct acpi_table_header *)madt,
-                                APIC_SIGNATURE, madt_size, 1);
+        intsrcovr++;
+        madt_size += sizeof(struct madt_intsrcovr);
     }
+
+    acpi_build_table_header((struct acpi_table_header *)madt,
+                            APIC_SIGNATURE, madt_size, 1);
 }
 
 u32
index 1ff4606a1d933c9d688d1df471c4b93a40294668..435019f0f416f6a52d5b7e48644edf74dd1a2b8f 100644 (file)
@@ -12,6 +12,8 @@
 #define CONFIG_APPNAME6 "BOCHS "
 #define CONFIG_APPNAME4 "BXPC"
 
+// Configure for use with KVM.
+#define CONFIG_KVM 0
 // Configure as a coreboot payload.
 #define CONFIG_COREBOOT 0
 
diff --git a/src/mtrr.c b/src/mtrr.c
new file mode 100644 (file)
index 0000000..161c1c0
--- /dev/null
@@ -0,0 +1,89 @@
+// Initialize MTRRs - mostly useful on KVM.
+//
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "util.h" // dprintf
+#include "biosvar.h" // GET_EBDA
+
+#define MSR_MTRRcap                    0x000000fe
+#define MSR_MTRRfix64K_00000           0x00000250
+#define MSR_MTRRfix16K_80000           0x00000258
+#define MSR_MTRRfix16K_A0000           0x00000259
+#define MSR_MTRRfix4K_C0000            0x00000268
+#define MSR_MTRRfix4K_C8000            0x00000269
+#define MSR_MTRRfix4K_D0000            0x0000026a
+#define MSR_MTRRfix4K_D8000            0x0000026b
+#define MSR_MTRRfix4K_E0000            0x0000026c
+#define MSR_MTRRfix4K_E8000            0x0000026d
+#define MSR_MTRRfix4K_F0000            0x0000026e
+#define MSR_MTRRfix4K_F8000            0x0000026f
+#define MSR_MTRRdefType                0x000002ff
+
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+static u64 rdmsr(unsigned index)
+{
+    unsigned long long ret;
+
+    asm ("rdmsr" : "=A"(ret) : "c"(index));
+    return ret;
+}
+
+static void wrmsr(unsigned index, u64 val)
+{
+    asm volatile ("wrmsr" : : "c"(index), "A"(val));
+}
+
+static void wrmsr_smp(u32 index, u64 val)
+{
+    // XXX - should run this on other CPUs also.
+    wrmsr(index, val);
+}
+
+void mtrr_setup(void)
+{
+    if (! CONFIG_KVM)
+        return;
+    dprintf(3, "init mtrr\n");
+
+    int i, vcnt, fix, wc;
+    u32 ram_size = GET_GLOBAL(RamSize);
+    u32 mtrr_cap;
+    union {
+        u8 valb[8];
+        u64 val;
+    } u;
+
+    mtrr_cap = rdmsr(MSR_MTRRcap);
+    vcnt = mtrr_cap & 0xff;
+    fix = mtrr_cap & 0x100;
+    wc = mtrr_cap & 0x400;
+    if (!vcnt || !fix)
+       return;
+    u.val = 0;
+    for (i = 0; i < 8; ++i)
+        if (ram_size >= 65536 * (i + 1))
+            u.valb[i] = 6;
+    wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
+    u.val = 0;
+    for (i = 0; i < 8; ++i)
+        if (ram_size >= 65536 * 8 + 16384 * (i + 1))
+            u.valb[i] = 6;
+    wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
+    wrmsr_smp(MSR_MTRRfix16K_A0000, 0);
+    wrmsr_smp(MSR_MTRRfix4K_C0000, 0);
+    wrmsr_smp(MSR_MTRRfix4K_C8000, 0);
+    wrmsr_smp(MSR_MTRRfix4K_D0000, 0);
+    wrmsr_smp(MSR_MTRRfix4K_D8000, 0);
+    wrmsr_smp(MSR_MTRRfix4K_E0000, 0);
+    wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
+    wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
+    wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
+    /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
+    wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000ull | 0);
+    wrmsr_smp(MTRRphysMask_MSR(0), ~(0x20000000ull - 1) | 0x800);
+    wrmsr_smp(MSR_MTRRdefType, 0xc06);
+}
index 6d35eeacb333facc31496ce1073c3216789eb353..95b8dd9be6cfb618f2ee3e9ee87263733b162340 100644 (file)
@@ -18,7 +18,13 @@ static u32 pci_bios_io_addr;
 static u32 pci_bios_mem_addr;
 static u32 pci_bios_bigmem_addr;
 /* host irqs corresponding to PCI irqs A-D */
-static u8 pci_irqs[4] = { 11, 9, 11, 9 };
+static u8 pci_irqs[4] = {
+#if CONFIG_KVM
+    10, 10, 11, 11
+#else
+    11, 9, 11, 9
+#endif
+};
 
 static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
 {
@@ -176,6 +182,11 @@ static void pci_bios_init_device(u16 bdf)
     if (vendor_id == PCI_VENDOR_ID_INTEL
         && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
         /* PIIX4 Power Management device (for ACPI) */
+
+        if (CONFIG_KVM)
+            // acpi sci is hardwired to 9
+            pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
+
         pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
         pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
         pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
index c7ddb2487877d8b6df825c726992744c599cd122..0fd41f981510e58702409516bcfe2e3ffdd9064e 100644 (file)
@@ -126,6 +126,11 @@ ram_probe(void)
              , E820_RESERVED);
     add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED);
 
+    if (CONFIG_KVM)
+        // 4 pages before the bios, 3 pages for vmx tss pages, the
+        // other page for EPT real mode pagetable
+        add_e820(0xfffbc000, 4*4096, E820_RESERVED);
+
     dprintf(1, "Ram Size=0x%08x\n", RamSize);
 }
 
@@ -197,6 +202,7 @@ post()
 
     memmap_setup();
     ram_probe();
+    mtrr_setup();
 
     pnp_setup();
     vga_setup();
index c448aef370bee03de7d264d2af8e4bce4ac68116..0c9be5e6dbc45c5bac5ad92d462a59e636cc05fd 100644 (file)
@@ -178,6 +178,9 @@ void init_dma();
 u16 get_pnp_offset();
 void pnp_setup();
 
+// mtrr.c
+void mtrr_setup(void);
+
 // romlayout.S
 void reset_vector() __attribute__ ((noreturn));