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

Reply via email to