I'm attaching patches for seabios to make it work on the Virtutech
Simics x86-440bx model. Please let me know if there is some other list
that is preferred for seabios patches.
Patches 1-6 and 9 are not really related to the Virtutech model at all,
so those would be prime candidates to be included in the mainline version.
M.
>From e6e517bbf2960b7502b5f4307a0308985d5ae00c Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 12:49:27 +0100
Subject: [PATCH 01/10] Fit cpuflag in mptable (| has higher priority than ?:)
---
src/mptable.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/mptable.c b/src/mptable.c
index 3945d2e..805fe1b 100644
--- a/src/mptable.c
+++ b/src/mptable.c
@@ -60,7 +60,7 @@ mptable_init(void)
cpu->apicver = 0x11;
/* cpu flags: enabled, bootstrap cpu */
if (i < CountCPUs)
- cpu->cpuflag = 1 | (i == 0) ? 2 : 0;
+ cpu->cpuflag = 1 | ((i == 0) ? 2 : 0);
else
cpu->cpuflag = 0;
if (cpuid_signature) {
--
1.6.2.5
>From bfe9e84a00c4915fc3a5338cbf8b38d71ddf4d2b Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 12:50:09 +0100
Subject: [PATCH 02/10] Only add the first logical CPU in each physical CPU to the MPS tables.
---
src/mptable.c | 26 ++++++++++++++++++++++----
1 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/mptable.c b/src/mptable.c
index 805fe1b..525188d 100644
--- a/src/mptable.c
+++ b/src/mptable.c
@@ -44,16 +44,32 @@ mptable_init(void)
config->spec = 4;
memcpy(config->oemid, CONFIG_CPUNAME8, sizeof(config->oemid));
memcpy(config->productid, "0.1 ", sizeof(config->productid));
- config->entrycount = MaxCountCPUs + 2 + 16;
config->lapic = BUILD_APIC_ADDR;
// CPU definitions.
u32 cpuid_signature, ebx, ecx, cpuid_features;
cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
struct mpt_cpu *cpus = (void*)&config[1];
- int i;
- for (i = 0; i < MaxCountCPUs; i++) {
+ int i, actual_cpu_count;
+ for (i = 0, actual_cpu_count = 0; i < MaxCountCPUs; i++) {
struct mpt_cpu *cpu = &cpus[i];
+ int log_cpus = (ebx >> 16) & 0xff;
+
+ /* Only populate the MPS tables with the first logical CPU in each
+ package */
+ if ((cpuid_features & (1 << 28)) &&
+ log_cpus > 1 &&
+ ((log_cpus <= 2 && (i & 1) != 0) ||
+ (log_cpus <= 4 && (i & 3) != 0) ||
+ (log_cpus <= 8 && (i & 7) != 0) ||
+ (log_cpus <= 16 && (i & 15) != 0) ||
+ (log_cpus <= 32 && (i & 31) != 0) ||
+ (log_cpus <= 64 && (i & 63) != 0) ||
+ (log_cpus <= 128 && (i & 127) != 0)))
+ continue;
+
+ actual_cpu_count++;
+
memset(cpu, 0, sizeof(*cpu));
cpu->type = MPT_TYPE_CPU;
cpu->apicid = i;
@@ -72,8 +88,10 @@ mptable_init(void)
}
}
+ config->entrycount = actual_cpu_count + 2 + 16;
+
/* isa bus */
- struct mpt_bus *bus = (void*)&cpus[MaxCountCPUs];
+ struct mpt_bus *bus = (void*)&cpus[actual_cpu_count];
memset(bus, 0, sizeof(*bus));
bus->type = MPT_TYPE_BUS;
memcpy(bus->bustype, "ISA ", sizeof(bus->bustype));
--
1.6.2.5
>From c712c235ed74c49793479828af5b69c9870ec120 Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 12:50:45 +0100
Subject: [PATCH 03/10] Limit MPS tables to 15 CPUs to fit with 4-bit APIC addressing.
---
src/mptable.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/src/mptable.c b/src/mptable.c
index 525188d..7e8486d 100644
--- a/src/mptable.c
+++ b/src/mptable.c
@@ -86,6 +86,12 @@ mptable_init(void)
cpu->cpusignature = 0x600;
cpu->featureflag = 0x201;
}
+
+ /* Limit the CPU count to 15 in the MPS tables, which is the limit in
+ the 4-bit legacy APIC addressing scheme. Operating systems can find
+ all CPUs through the ACPI tables. */
+ if (actual_cpu_count >= 15)
+ break;
}
config->entrycount = actual_cpu_count + 2 + 16;
--
1.6.2.5
>From 2475852dd7e13db896ade26e489b572acbf0d52f Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 12:51:17 +0100
Subject: [PATCH 04/10] Remove device access from loop to make it faster when running in emulation.
---
src/smp.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/smp.c b/src/smp.c
index a912857..71b0da8 100644
--- a/src/smp.c
+++ b/src/smp.c
@@ -97,11 +97,13 @@ smp_probe(void)
writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
// Wait for other CPUs to process the SIPI.
- if (CONFIG_COREBOOT)
+ if (CONFIG_COREBOOT) {
msleep(10);
- else
- while (inb_cmos(CMOS_BIOS_SMP_COUNT) + 1 != readl(&CountCPUs))
- ;
+ } else {
+ u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT);
+ while (cmos_smp_count + 1 != readl(&CountCPUs))
+ ;
+ }
// Restore memory.
*(u64*)BUILD_AP_BOOT_ADDR = old;
--
1.6.2.5
>From 49d35df6674ef32cffaecc50d8c1eeeebf05d41c Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 12:51:45 +0100
Subject: [PATCH 05/10] Initialize the LINT LVTs on the local APIC of the BSP. Since the APIC is enabled, we need to initialize LINT0 to ExtINT and LINT1 to NMI.
---
src/smp.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/src/smp.c b/src/smp.c
index 71b0da8..b0852f8 100644
--- a/src/smp.c
+++ b/src/smp.c
@@ -13,6 +13,8 @@
#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300)
#define APIC_SVR ((u8*)BUILD_APIC_ADDR + 0x0F0)
+#define APIC_LINT0 ((u8*)BUILD_APIC_ADDR + 0x350)
+#define APIC_LINT1 ((u8*)BUILD_APIC_ADDR + 0x360)
#define APIC_ENABLED 0x0100
@@ -91,6 +93,12 @@ smp_probe(void)
u32 val = readl(APIC_SVR);
writel(APIC_SVR, val | APIC_ENABLED);
+ /* Set LINT0 as Ext_INT, level triggered */
+ writel(APIC_LINT0, 0x8700);
+
+ /* Set LINT1 as NMI, level triggered */
+ writel(APIC_LINT1, 0x8400);
+
// broadcast SIPI
writel(APIC_ICR_LOW, 0x000C4500);
u32 sipi_vector = BUILD_AP_BOOT_ADDR >> 12;
--
1.6.2.5
>From 26910b04759c2380523dbeab016adfe675a265b4 Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 12:52:07 +0100
Subject: [PATCH 06/10] Add MPS entries for LINT interrupts.
---
src/mptable.c | 23 +++++++++++++++++++++--
src/mptable.h | 1 +
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/src/mptable.c b/src/mptable.c
index 7e8486d..b91591d 100644
--- a/src/mptable.c
+++ b/src/mptable.c
@@ -22,7 +22,7 @@ mptable_init(void)
+ sizeof(struct mpt_cpu) * MaxCountCPUs
+ sizeof(struct mpt_bus)
+ sizeof(struct mpt_ioapic)
- + sizeof(struct mpt_intsrc) * 16);
+ + sizeof(struct mpt_intsrc) * 18);
struct mptable_config_s *config = malloc_fseg(length);
struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating));
if (!config || !floating) {
@@ -94,7 +94,7 @@ mptable_init(void)
break;
}
- config->entrycount = actual_cpu_count + 2 + 16;
+ config->entrycount = actual_cpu_count + 2 + 16 + 2;
/* isa bus */
struct mpt_bus *bus = (void*)&cpus[actual_cpu_count];
@@ -131,6 +131,25 @@ mptable_init(void)
intsrc++;
}
+ /* Local interrupt assignment */
+ intsrc->type = MPT_TYPE_LOCAL_INT;
+ intsrc->irqtype = 3; /* ExtINT */
+ intsrc->irqflag = 0; /* PO, EL default */
+ intsrc->srcbus = 0;
+ intsrc->srcbusirq = 0;
+ intsrc->dstapic = 0; /* BSP == APIC #0 */
+ intsrc->dstirq = 0; /* LINTIN0 */
+ intsrc++;
+
+ intsrc->type = MPT_TYPE_LOCAL_INT;
+ intsrc->irqtype = 1; /* NMI */
+ intsrc->irqflag = 0; /* PO, EL default */
+ intsrc->srcbus = 0;
+ intsrc->srcbusirq = 0;
+ intsrc->dstapic = 0; /* BSP == APIC #0 */
+ intsrc->dstirq = 1; /* LINTIN1 */
+ intsrc++;
+
// Set checksum.
config->length = (void*)intsrc - (void*)config;
config->checksum -= checksum(config, config->length);
diff --git a/src/mptable.h b/src/mptable.h
index 4c4d52f..c4e3c51 100644
--- a/src/mptable.h
+++ b/src/mptable.h
@@ -38,6 +38,7 @@ struct mptable_config_s {
#define MPT_TYPE_BUS 1
#define MPT_TYPE_IOAPIC 2
#define MPT_TYPE_INTSRC 3
+#define MPT_TYPE_LOCAL_INT 4
struct mpt_cpu {
u8 type;
--
1.6.2.5
>From 9f07511ca1dd4bfd345cfb8bf43b4835a8bcd6c6 Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 13:41:24 +0100
Subject: [PATCH 07/10] Always enable the IRQ0 override if the VIRTUTECH_IRQ0_OVERRIDE option is set.
---
src/config.h | 3 +++
src/paravirt.c | 4 ++++
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/src/config.h b/src/config.h
index 3033133..71903bb 100644
--- a/src/config.h
+++ b/src/config.h
@@ -189,4 +189,7 @@
#define DEBUG_HDL_pmm 1
#define DEBUG_thread 1
+/* Options for running on the Virtutech Simics x86-440bx machine model */
+#define VIRTUTECH_IRQ0_OVERRIDE 1
+
#endif // config.h
diff --git a/src/paravirt.c b/src/paravirt.c
index 6f48d2e..577c7e8 100644
--- a/src/paravirt.c
+++ b/src/paravirt.c
@@ -82,6 +82,9 @@ int qemu_cfg_show_boot_menu(void)
int qemu_cfg_irq0_override(void)
{
+#if VIRTUTECH_IRQ0_OVERRIDE
+ return 1;
+#else
u8 v;
if (!qemu_cfg_present)
@@ -90,6 +93,7 @@ int qemu_cfg_irq0_override(void)
qemu_cfg_read_entry(&v, QEMU_CFG_IRQ0_OVERRIDE, sizeof(v));
return v;
+#endif
}
u16 qemu_cfg_acpi_additional_tables(void)
--
1.6.2.5
>From 3733d50bf7432e3183f410db08f3d127dde5720c Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 13:43:13 +0100
Subject: [PATCH 08/10] Handle Virtutech Simics x86-440bx shadowing with the VIRTUTECH_PC_SHADOW option.
---
src/config.h | 1 +
src/shadow.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 0 deletions(-)
diff --git a/src/config.h b/src/config.h
index 71903bb..754559b 100644
--- a/src/config.h
+++ b/src/config.h
@@ -191,5 +191,6 @@
/* Options for running on the Virtutech Simics x86-440bx machine model */
#define VIRTUTECH_IRQ0_OVERRIDE 1
+#define VIRTUTECH_PC_SHADOW 1
#endif // config.h
diff --git a/src/shadow.c b/src/shadow.c
index f0f97c5..4b7f15c 100644
--- a/src/shadow.c
+++ b/src/shadow.c
@@ -9,6 +9,7 @@
#include "pci.h" // pci_config_writeb
#include "config.h" // CONFIG_*
#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
+#include "ioport.h" // outb
// Test if 'addr' is in the range from 'start'..'start+size'
#define IN_RANGE(addr, start, size) ({ \
@@ -21,6 +22,40 @@
// On the emulators, the bios at 0xf0000 is also at 0xffff0000
#define BIOS_SRC_ADDR 0xffff0000
+#if VIRTUTECH_PC_SHADOW
+
+#define Read_Only 1
+#define Write_Only 2
+#define Read_Write 3
+
+static void modify_shadow(unsigned long start, unsigned long len, int mode)
+{
+ int start_loc = ((int)(start >> 10) - 640) >> 1;
+ int len_remaining = len >> 11;
+ int i;
+ for (i = 0; i < len_remaining; i++) {
+ outb(start_loc + i, 0xfff4);
+ if (mode == Read_Only) {
+ outb(1, 0xfff5);
+ } else if (mode == Read_Write) {
+ outb(3, 0xfff5);
+ } else if (mode == Write_Only) {
+ outb(2, 0xfff5);
+ } else {
+ outb(0, 0xfff5);
+ }
+ }
+}
+
+static void
+__copy_bios(void)
+{
+ // Copy bios.
+ memcpy((void*)BUILD_BIOS_ADDR, (void*)BIOS_SRC_ADDR, BUILD_BIOS_SIZE);
+}
+
+#else
+
// Enable shadowing and copy bios.
static void
__make_bios_writable(u16 bdf)
@@ -59,6 +94,8 @@ __make_bios_writable(u16 bdf)
memcpy((void*)BUILD_BIOS_ADDR, (void*)BIOS_SRC_ADDR, BUILD_BIOS_SIZE);
}
+#endif // VIRTUTECH_PC_SHADOW
+
// Make the 0xc0000-0x100000 area read/writable.
void
make_bios_writable()
@@ -68,6 +105,19 @@ make_bios_writable()
dprintf(3, "enabling shadow ram\n");
+#if VIRTUTECH_PC_SHADOW
+ /* Read (and execute) from PCI, write to RAM */
+ modify_shadow(0xf0000, 0x10000, Write_Only);
+
+ /* Run the copy from the high address to avoid simulator flushes after each
+ write (the flushes ruin performance) */
+ u32 pos = (u32)__copy_bios - BUILD_BIOS_ADDR + BIOS_SRC_ADDR;
+ void (*func)(void) = (void*)pos;
+ func();
+
+ /* Keep BIOS read/write */
+ modify_shadow(0xf0000, 0x10000, Read_Write);
+#else
// Locate chip controlling ram shadowing.
int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
if (bdf < 0) {
@@ -88,6 +138,7 @@ make_bios_writable()
}
// Ram already present - just enable writes
__make_bios_writable(bdf);
+#endif
}
// Make the BIOS code segment area (0xf0000) read-only.
@@ -99,6 +150,9 @@ make_bios_readonly()
dprintf(3, "locking shadow ram\n");
+#if VIRTUTECH_PC_SHADOW
+ modify_shadow(0xf0000, 0x10000, Read_Only);
+#else
int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
if (bdf < 0) {
dprintf(1, "Unable to lock ram - bridge not found\n");
@@ -122,4 +176,5 @@ make_bios_readonly()
// Write protect 0xf0000-0x100000
pci_config_writeb(bdf, 0x59, 0x10);
+#endif
}
--
1.6.2.5
>From 3d3e75bb83cb871603c5bab01026343e03af7b6f Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 13:47:52 +0100
Subject: [PATCH 09/10] Properly mask value for MTRR mask.
---
src/mtrr.c | 14 ++++++++++++--
1 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/mtrr.c b/src/mtrr.c
index a9cd5f7..6bd0dba 100644
--- a/src/mtrr.c
+++ b/src/mtrr.c
@@ -29,7 +29,7 @@ void mtrr_setup(void)
if (CONFIG_COREBOOT)
return;
- u32 eax, ebx, ecx, cpuid_features;
+ u32 eax, ebx, ecx, edx, cpuid_features;
cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
if (!(cpuid_features & CPUID_MTRR))
return;
@@ -73,6 +73,16 @@ void mtrr_setup(void)
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);
+
+ int phys_bits = 36;
+ cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
+ if (eax >= 0x80000008) {
+ /* Get physical bits from leaf 0x80000008 (if available) */
+ cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
+ phys_bits = eax & 0xff;
+ }
+ u64 phys_mask = ((1ull << phys_bits) - 1);
+ wrmsr_smp(MTRRphysMask_MSR(0), (~(0x20000000ull - 1) & phys_mask) | 0x800);
+
wrmsr_smp(MSR_MTRRdefType, 0xc06);
}
--
1.6.2.5
>From eedd6f2f7378a03f95a7a31968c42940e363049f Mon Sep 17 00:00:00 2001
From: Magnus Christensson <[email protected]>
Date: Tue, 3 Nov 2009 14:46:52 +0100
Subject: [PATCH 10/10] Add USE_CMOS_BIOS_SMP_COUNT option. If disabled, we wait 10ms instead of relying on the cpu count stored in memory.
---
src/config.h | 1 +
src/smp.c | 2 +-
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/config.h b/src/config.h
index 754559b..a9e79cb 100644
--- a/src/config.h
+++ b/src/config.h
@@ -192,5 +192,6 @@
/* Options for running on the Virtutech Simics x86-440bx machine model */
#define VIRTUTECH_IRQ0_OVERRIDE 1
#define VIRTUTECH_PC_SHADOW 1
+#define USE_CMOS_BIOS_SMP_COUNT 0
#endif // config.h
diff --git a/src/smp.c b/src/smp.c
index b0852f8..caec5f1 100644
--- a/src/smp.c
+++ b/src/smp.c
@@ -105,7 +105,7 @@ smp_probe(void)
writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
// Wait for other CPUs to process the SIPI.
- if (CONFIG_COREBOOT) {
+ if (CONFIG_COREBOOT || !USE_CMOS_BIOS_SMP_COUNT) {
msleep(10);
} else {
u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT);
--
1.6.2.5
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot