diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2009-01-04 21:48:22 -0500 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2009-01-04 21:48:22 -0500 |
commit | 7061eb6aa6adc19f965d01509483c67a201c8b35 (patch) | |
tree | 9064b1470fdddcc823ae90fb254bc7650f8ee661 /src | |
parent | 0234cd90be8805b1951b4411de81314d27518eea (diff) | |
download | seabios-7061eb6aa6adc19f965d01509483c67a201c8b35.tar.gz |
Initial KVM support.
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/acpi.c | 75 | ||||
-rw-r--r-- | src/config.h | 2 | ||||
-rw-r--r-- | src/mtrr.c | 89 | ||||
-rw-r--r-- | src/pciinit.c | 13 | ||||
-rw-r--r-- | src/post.c | 6 | ||||
-rw-r--r-- | src/util.h | 3 |
6 files changed, 163 insertions, 25 deletions
@@ -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 diff --git a/src/config.h b/src/config.h index 1ff4606a..435019f0 100644 --- a/src/config.h +++ b/src/config.h @@ -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 index 00000000..161c1c0c --- /dev/null +++ b/src/mtrr.c @@ -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); +} diff --git a/src/pciinit.c b/src/pciinit.c index 6d35eeac..95b8dd9b 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -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); @@ -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(); @@ -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)); |