Forward port bochs smp changes; rename smpdetect.c to smp.c.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 21 Jun 2009 13:10:28 +0000 (09:10 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 21 Jun 2009 13:10:28 +0000 (09:10 -0400)
Rename smpdetect.c to smp.c - the code does more than just cpu detection.
Don't probe cpu count on demand - schedule it during post.
Add logic to run wrmsr on all cpus.
Don't make mtrr setup specific to kvm - do it on all machines that
    have mtrr and msrs.
Detect cpu signature/features automatically in mptable.
Also, make sure acpi structures are packed.

Makefile
src/acpi.c
src/mptable.c
src/mptable.h
src/mtrr.c
src/post.c
src/smbios.c
src/smp.c [new file with mode: 0644]
src/smpdetect.c [deleted file]
src/util.h

index 356e72cfc127eccfbe870c59529536edeb050d83..71e3cb48b0df271c9dd7795a5201e47264d373e0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ OUT=out/
 
 # Source files
 SRCBOTH=output.c util.c floppy.c ata.c misc.c mouse.c kbd.c pci.c \
-        serial.c clock.c pic.c cdrom.c ps2port.c smpdetect.c resume.c \
+        serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \
         pnpbios.c pirtable.c
 SRC16=$(SRCBOTH) system.c disk.c apm.c pcibios.c vgahooks.c font.c
 SRC32=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
index 6a509718a4e87ef6c9ebf64300dedeee1b63f5e1..f140f1ac3522d08e39324da305eb61f5b9de9891 100644 (file)
@@ -35,7 +35,7 @@
 struct acpi_table_header         /* ACPI common table header */
 {
     ACPI_TABLE_HEADER_DEF
-};
+} PACKED;
 
 /*
  * ACPI 1.0 Root System Description Table (RSDT)
@@ -46,7 +46,7 @@ struct rsdt_descriptor_rev1
     ACPI_TABLE_HEADER_DEF       /* ACPI common table header */
     u32 table_offset_entry [3]; /* Array of pointers to other */
     /* ACPI tables */
-};
+} PACKED;
 
 /*
  * ACPI 1.0 Firmware ACPI Control Structure (FACS)
@@ -62,7 +62,7 @@ struct facs_descriptor_rev1
     u32 S4bios_f        : 1;    /* Indicates if S4BIOS support is present */
     u32 reserved1       : 31;   /* Must be 0 */
     u8  resverved3 [40];        /* Reserved - must be zero */
-};
+} PACKED;
 
 
 /*
@@ -124,7 +124,7 @@ struct fadt_descriptor_rev1
 #else
     u32 flags;
 #endif
-};
+} PACKED;
 
 /*
  * MADT values and structures
@@ -149,7 +149,7 @@ struct multiple_apic_table
 #else
     u32 flags;
 #endif
-};
+} PACKED;
 
 
 /* Values for Type in APIC_HEADER_DEF */
@@ -185,7 +185,7 @@ struct madt_processor_apic
 #else
     u32 flags;
 #endif
-};
+} PACKED;
 
 struct madt_io_apic
 {
@@ -195,7 +195,7 @@ struct madt_io_apic
     u32 address;                /* APIC physical address */
     u32 interrupt;              /* Global system interrupt where INTI
                                  * lines start */
-};
+} PACKED;
 
 #if CONFIG_KVM
 /* IRQs 5,9,10,11 */
@@ -245,7 +245,7 @@ acpi_build_processor_ssdt(u8 *ssdt)
 {
     u8 *ssdt_ptr = ssdt;
     int i, length;
-    int smp_cpus = smp_probe();
+    int smp_cpus = CountCPUs;
     int acpi_cpus = smp_cpus > 0xff ? 0xff : smp_cpus;
 
     ssdt_ptr[9] = 0; // checksum;
@@ -348,7 +348,7 @@ void acpi_bios_init(void)
     ssdt = (void *)(addr);
     addr += acpi_build_processor_ssdt(ssdt);
 
-    int smp_cpus = smp_probe();
+    int smp_cpus = CountCPUs;
     addr = ALIGN(addr, 8);
     madt_addr = addr;
     madt_size = sizeof(*madt) +
index 9e030fe8392435cbd55155048d31ff3ce68db245..47aee24bb227b0ca542465dcae5758416a7f4563 100644 (file)
@@ -18,7 +18,7 @@ mptable_init(void)
 
     dprintf(3, "init MPTable\n");
 
-    int smp_cpus = smp_probe();
+    int smp_cpus = CountCPUs;
     if (smp_cpus <= 1)
         // Building an mptable on uniprocessor machines confuses some OSes.
         return;
@@ -57,6 +57,8 @@ mptable_init(void)
     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 < smp_cpus; i++) {
@@ -67,8 +69,13 @@ mptable_init(void)
         cpu->apicver = 0x11;
         /* cpu flags: enabled, bootstrap cpu */
         cpu->cpuflag = (i == 0 ? 3 : 1);
-        cpu->cpufeature = 0x600;
-        cpu->featureflag = 0x201;
+        if (cpuid_signature) {
+            cpu->cpusignature = cpuid_signature;
+            cpu->featureflag = cpuid_features;
+        } else {
+            cpu->cpusignature = 0x600;
+            cpu->featureflag = 0x201;
+        }
     }
 
     /* isa bus */
index d8fecb31cda8165088c78f8004b2ee61099126da..4c4d52fb7bafe598c3067bffc76f85170a29758a 100644 (file)
@@ -44,7 +44,7 @@ struct mpt_cpu {
     u8 apicid;
     u8 apicver;
     u8 cpuflag;
-    u32 cpufeature;
+    u32 cpusignature;
     u32 featureflag;
     u32 reserved[2];
 } PACKED;
index 12837e00c6d3dc50bcc6ef31be52d8c3d50733a7..a9cd5f781cb7b16a1137b260d4dd702dcdbe6198 100644 (file)
 #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
 #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
 
-static u64 rdmsr(u32 index)
-{
-    u64 ret;
-    asm ("rdmsr" : "=A"(ret) : "c"(index));
-    return ret;
-}
-
-static void wrmsr(u32 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)
+    if (CONFIG_COREBOOT)
+        return;
+
+    u32 eax, ebx, ecx, cpuid_features;
+    cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
+    if (!(cpuid_features & CPUID_MTRR))
+        return;
+    if (!(cpuid_features & CPUID_MSR))
         return;
+
     dprintf(3, "init mtrr\n");
 
     int i, vcnt, fix, wc;
index 3c68990bedc1b3281cc298337b7ec5cb617f7997..638f95a8526cfccfccb55c2b23f2134970177e85 100644 (file)
@@ -163,10 +163,10 @@ post()
     mathcp_setup();
 
     smp_probe_setup();
-
     memmap_setup();
     ram_probe();
     mtrr_setup();
+    smp_probe();
 
     pnp_setup();
     vga_setup();
index e2f21901420581b528b4e473e15b5f64e1c05c71..40812e3b977cb1abe36c006841cebf5b919cf0fd 100644 (file)
@@ -559,7 +559,7 @@ smbios_init(void)
     add_struct(smbios_type_0_init(p));
     add_struct(smbios_type_1_init(p));
     add_struct(smbios_type_3_init(p));
-    int smp_cpus = smp_probe();
+    int smp_cpus = CountCPUs;
     for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
         add_struct(smbios_type_4_init(p, cpu_num));
     add_struct(smbios_type_16_init(p));
diff --git a/src/smp.c b/src/smp.c
new file mode 100644 (file)
index 0000000..49e5631
--- /dev/null
+++ b/src/smp.c
@@ -0,0 +1,146 @@
+// CPU count detection
+//
+// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "config.h" // CONFIG_*
+#include "cmos.h" // CMOS_BIOS_SMP_COUNT
+#include "farptr.h" // ASSERT32
+
+#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300)
+#define APIC_SVR     ((u8*)BUILD_APIC_ADDR + 0x0F0)
+
+#define APIC_ENABLED 0x0100
+
+static inline void writel(void *addr, u32 val)
+{
+    *(volatile u32 *)addr = val;
+}
+
+static inline void writew(void *addr, u16 val)
+{
+    *(volatile u16 *)addr = val;
+}
+
+static inline void writeb(void *addr, u8 val)
+{
+    *(volatile u8 *)addr = val;
+}
+
+static inline u32 readl(const void *addr)
+{
+    return *(volatile const u32 *)addr;
+}
+
+static inline u16 readw(const void *addr)
+{
+    return *(volatile const u16 *)addr;
+}
+
+static inline u8 readb(const void *addr)
+{
+    return *(volatile const u8 *)addr;
+}
+
+struct { u32 ecx, eax, edx; } smp_mtrr[16] VAR16_32;
+u32 smp_mtrr_count VAR16_32;
+
+void
+wrmsr_smp(u32 index, u64 val)
+{
+    wrmsr(index, val);
+    if (smp_mtrr_count >= ARRAY_SIZE(smp_mtrr))
+        return;
+    smp_mtrr[smp_mtrr_count].ecx = index;
+    smp_mtrr[smp_mtrr_count].eax = val;
+    smp_mtrr[smp_mtrr_count].edx = val >> 32;
+    smp_mtrr_count++;
+}
+
+u32 CountCPUs VAR16_32;
+extern void smp_ap_boot_code();
+ASM16(
+    "  .global smp_ap_boot_code\n"
+    "smp_ap_boot_code:\n"
+
+    // Setup data segment
+    "  movw $" __stringify(SEG_BIOS) ", %ax\n"
+    "  movw %ax, %ds\n"
+
+    // MTRR setup
+    "  movl $smp_mtrr, %esi\n"
+    "  movl smp_mtrr_count, %ebx\n"
+    "1:testl %ebx, %ebx\n"
+    "  jz 2f\n"
+    "  movl 0(%esi), %ecx\n"
+    "  movl 4(%esi), %eax\n"
+    "  movl 8(%esi), %edx\n"
+    "  wrmsr\n"
+    "  addl $12, %esi\n"
+    "  decl %ebx\n"
+    "  jmp 1b\n"
+    "2:\n"
+
+    // Increment the cpu counter
+    "  lock incl CountCPUs\n"
+
+    // Halt the processor.
+    "1:hlt\n"
+    "  jmp 1b\n"
+    );
+
+// find and initialize the CPUs by launching a SIPI to them
+void
+smp_probe(void)
+{
+    ASSERT32();
+    u32 eax, ebx, ecx, cpuid_features;
+    cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
+    if (! (cpuid_features & CPUID_APIC)) {
+        // No apic - only the main cpu is present.
+        CountCPUs= 1;
+        return;
+    }
+
+    // Init the counter.
+    writel(&CountCPUs, 1);
+
+    // Setup jump trampoline to counter code.
+    u64 old = *(u64*)BUILD_AP_BOOT_ADDR;
+    // ljmpw $SEG_BIOS, $(smp_ap_boot_code - BUILD_BIOS_ADDR)
+    u64 new = (0xea | ((u64)SEG_BIOS<<24)
+               | (((u32)smp_ap_boot_code - BUILD_BIOS_ADDR) << 8));
+    *(u64*)BUILD_AP_BOOT_ADDR = new;
+
+    // enable local APIC
+    u32 val = readl(APIC_SVR);
+    writel(APIC_SVR, val | APIC_ENABLED);
+
+    // broadcast SIPI
+    writel(APIC_ICR_LOW, 0x000C4500);
+    u32 sipi_vector = BUILD_AP_BOOT_ADDR >> 12;
+    writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
+
+    // Wait for other CPUs to process the SIPI.
+    if (CONFIG_COREBOOT)
+        mdelay(10);
+    else
+        while (inb_cmos(CMOS_BIOS_SMP_COUNT) + 1 != readl(&CountCPUs))
+            ;
+
+    // Restore memory.
+    *(u64*)BUILD_AP_BOOT_ADDR = old;
+
+    dprintf(1, "Found %d cpu(s)\n", readl(&CountCPUs));
+}
+
+// Reset variables to zero
+void
+smp_probe_setup(void)
+{
+    CountCPUs = 0;
+    smp_mtrr_count = 0;
+}
diff --git a/src/smpdetect.c b/src/smpdetect.c
deleted file mode 100644 (file)
index a25e042..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-// CPU count detection
-//
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
-// Copyright (C) 2006 Fabrice Bellard
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "util.h" // dprintf
-#include "config.h" // CONFIG_*
-#include "cmos.h" // CMOS_BIOS_SMP_COUNT
-#include "farptr.h" // ASSERT32
-
-#define CPUID_APIC (1 << 9)
-
-#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300)
-#define APIC_SVR     ((u8*)BUILD_APIC_ADDR + 0x0F0)
-
-#define APIC_ENABLED 0x0100
-
-static inline void writel(void *addr, u32 val)
-{
-    *(volatile u32 *)addr = val;
-}
-
-static inline void writew(void *addr, u16 val)
-{
-    *(volatile u16 *)addr = val;
-}
-
-static inline void writeb(void *addr, u8 val)
-{
-    *(volatile u8 *)addr = val;
-}
-
-static inline u32 readl(const void *addr)
-{
-    return *(volatile const u32 *)addr;
-}
-
-static inline u16 readw(const void *addr)
-{
-    return *(volatile const u16 *)addr;
-}
-
-static inline u8 readb(const void *addr)
-{
-    return *(volatile const u8 *)addr;
-}
-
-u32 smp_cpus VAR16_32;
-extern void smp_ap_boot_code();
-ASM16(
-    "  .global smp_ap_boot_code\n"
-    "smp_ap_boot_code:\n"
-    // Increment the cpu counter
-    "  movw $" __stringify(SEG_BIOS) ", %ax\n"
-    "  movw %ax, %ds\n"
-    "  lock incl smp_cpus\n"
-    // Halt the processor.
-    "1:hlt\n"
-    "  jmp 1b\n"
-    );
-
-/* find the number of CPUs by launching a SIPI to them */
-int
-smp_probe(void)
-{
-    ASSERT32();
-    if (smp_cpus)
-        return smp_cpus;
-
-    u32 eax, ebx, ecx, cpuid_features;
-    cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
-    if (! (cpuid_features & CPUID_APIC)) {
-        // No apic - only the main cpu is present.
-        smp_cpus = 1;
-        return 1;
-    }
-
-    // Init the counter.
-    writel(&smp_cpus, 1);
-
-    // Setup jump trampoline to counter code.
-    u64 old = *(u64*)BUILD_AP_BOOT_ADDR;
-    // ljmpw $SEG_BIOS, $(smp_ap_boot_code - BUILD_BIOS_ADDR)
-    u64 new = (0xea | ((u64)SEG_BIOS<<24)
-               | (((u32)smp_ap_boot_code - BUILD_BIOS_ADDR) << 8));
-    *(u64*)BUILD_AP_BOOT_ADDR = new;
-
-    // enable local APIC
-    u32 val = readl(APIC_SVR);
-    writel(APIC_SVR, val | APIC_ENABLED);
-
-    // broadcast SIPI
-    writel(APIC_ICR_LOW, 0x000C4500);
-    u32 sipi_vector = BUILD_AP_BOOT_ADDR >> 12;
-    writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
-
-    // Wait for other CPUs to process the SIPI.
-    if (CONFIG_COREBOOT)
-        mdelay(10);
-    else
-        while (inb_cmos(CMOS_BIOS_SMP_COUNT) + 1 != readl(&smp_cpus))
-            ;
-
-    // Restore memory.
-    *(u64*)BUILD_AP_BOOT_ADDR = old;
-
-    u32 count = readl(&smp_cpus);
-    dprintf(1, "Found %d cpu(s)\n", count);
-    return count;
-}
-
-// Reset smp_cpus to zero (forces a recheck on reboots).
-void
-smp_probe_setup(void)
-{
-    smp_cpus = 0;
-}
index 2ba80ddf6bf4b15f043ffce61bca75e0ccaca5a7..6ae7f1929e59232e3e80d493866601fa67999ad4 100644 (file)
@@ -51,6 +51,9 @@ static inline void wbinvd(void)
     asm volatile("wbinvd");
 }
 
+#define CPUID_MSR (1 << 5)
+#define CPUID_APIC (1 << 9)
+#define CPUID_MTRR (1 << 12)
 static inline void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
 {
     asm("cpuid"
@@ -58,6 +61,18 @@ static inline void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
         : "0" (index));
 }
 
+static inline u64 rdmsr(u32 index)
+{
+    u64 ret;
+    asm ("rdmsr" : "=A"(ret) : "c"(index));
+    return ret;
+}
+
+static inline void wrmsr(u32 index, u64 val)
+{
+    asm volatile ("wrmsr" : : "c"(index), "A"(val));
+}
+
 static inline u64 rdtscll(void)
 {
     u64 val;
@@ -177,8 +192,10 @@ void pci_bios_setup(void);
 // smm.c
 void smm_init();
 
-// smpdetect.c
-int smp_probe(void);
+// smp.c
+extern u32 CountCPUs VAR16_32;
+void wrmsr_smp(u32 index, u64 val);
+void smp_probe(void);
 void smp_probe_setup(void);
 
 // smbios.c