[SeaBIOS] [PATCH 1/2] Add CPUID emulation

Kevin O'Connor kevin at koconnor.net
Sun Jan 29 19:46:21 CET 2012


On Wed, Jan 25, 2012 at 06:45:28PM +0100, Rudolf Marek wrote:
> Hi all
> 
> As requested here is the first patch.

How about this patch instead?

-Kevin


commit c2228f401c13e0b300c6b1fcc43cc9097f47bb43
Author: Kevin O'Connor <kevin at koconnor.net>
Date:   Sun Jan 29 13:30:56 2012 -0500

    Detect CPUID instruction before using it.
    
    Enable SeaBIOS to work on 386/486 machines that don't have CPUID
    instruction.
    
    Based on patch by Rudolf Marek.
    
    Signed-off-by: Rudolf Marek <r.marek at assembler.cz>
    Signed-off-by: Kevin O'Connor <kevin at koconnor.net>

diff --git a/src/bregs.h b/src/bregs.h
index f026fa8..577effc 100644
--- a/src/bregs.h
+++ b/src/bregs.h
@@ -11,6 +11,7 @@
 #define F_CF (1<<0)
 #define F_ZF (1<<6)
 #define F_IF (1<<9)
+#define F_ID (1<<21)
 
 // CR0 flags
 #define CR0_PG (1<<31) // Paging
diff --git a/src/mptable.c b/src/mptable.c
index 103f462..3422212 100644
--- a/src/mptable.c
+++ b/src/mptable.c
@@ -35,7 +35,7 @@ mptable_init(void)
 
     // Detect cpu info
     u32 cpuid_signature, ebx, ecx, cpuid_features;
-    cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
+    get_cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
     if (! cpuid_signature) {
         // Use default values.
         cpuid_signature = 0x600;
diff --git a/src/mtrr.c b/src/mtrr.c
index 0548043..b6a8427 100644
--- a/src/mtrr.c
+++ b/src/mtrr.c
@@ -37,7 +37,7 @@ void mtrr_setup(void)
         return;
 
     u32 eax, ebx, ecx, edx, cpuid_features;
-    cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
+    get_cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
     if (!(cpuid_features & CPUID_MTRR))
         return;
     if (!(cpuid_features & CPUID_MSR))
@@ -82,11 +82,11 @@ void mtrr_setup(void)
 
     // Set variable MTRRs
     int phys_bits = 36;
-    cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
+    get_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;
+        /* Get physical bits from leaf 0x80000008 (if available) */
+        get_cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
+        phys_bits = eax & 0xff;
     }
     u64 phys_mask = ((1ull << phys_bits) - 1);
     for (i=0; i<vcnt; i++) {
diff --git a/src/paravirt.h b/src/paravirt.h
index 4a370a0..4014943 100644
--- a/src/paravirt.h
+++ b/src/paravirt.h
@@ -11,10 +11,12 @@
 
 static inline int kvm_para_available(void)
 {
+    if (CONFIG_COREBOOT)
+        return 0;
     unsigned int eax, ebx, ecx, edx;
     char signature[13];
 
-    cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
+    get_cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
     memcpy(signature + 0, &ebx, 4);
     memcpy(signature + 4, &ecx, 4);
     memcpy(signature + 8, &edx, 4);
diff --git a/src/smbios.c b/src/smbios.c
index fe1e183..9c8df98 100644
--- a/src/smbios.c
+++ b/src/smbios.c
@@ -255,7 +255,7 @@ smbios_init_type_4(void *start, unsigned int cpu_number)
     if (!qemu_cfg_smbios_load_field(4, offsetof(struct smbios_type_4,
                                     processor_id), p->processor_id)) {
         u32 cpuid_signature, ebx, ecx, cpuid_features;
-        cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
+        get_cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
         p->processor_id[0] = cpuid_signature;
         p->processor_id[1] = cpuid_features;
     }
diff --git a/src/smp.c b/src/smp.c
index 8c077a1..e36f960 100644
--- a/src/smp.c
+++ b/src/smp.c
@@ -73,7 +73,7 @@ smp_probe(void)
 {
     ASSERT32FLAT();
     u32 eax, ebx, ecx, cpuid_features;
-    cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
+    get_cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
     if (eax < 1 || !(cpuid_features & CPUID_APIC)) {
         // No apic - only the main cpu is present.
         dprintf(1, "No apic - only the main cpu is present.\n");
diff --git a/src/util.c b/src/util.c
index ed73d63..7141f5d 100644
--- a/src/util.c
+++ b/src/util.c
@@ -8,6 +8,22 @@
 #include "bregs.h" // struct bregs
 #include "config.h" // BUILD_STACK_ADDR
 
+void
+get_cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
+{
+    // Check for cpu id
+    u32 origflags = save_flags();
+    restore_flags(origflags ^ F_ID);
+    u32 newflags = save_flags();
+    restore_flags(origflags);
+
+    if (((origflags ^ newflags) & F_ID) != F_ID)
+        // no cpuid
+        *eax = *ebx = *ecx = *edx = 0;
+    else
+        cpuid(index, eax, ebx, ecx, edx);
+}
+
 
 /****************************************************************
  * 16bit calls
diff --git a/src/util.h b/src/util.h
index eecba8b..a69949d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -18,15 +18,14 @@ static inline void irq_enable(void)
     asm volatile("sti": : :"memory");
 }
 
-static inline unsigned long irq_save(void)
+static inline u32 save_flags(void)
 {
-    unsigned long flags;
-    asm volatile("pushfl ; popl %0" : "=g" (flags): :"memory");
-    irq_disable();
+    u32 flags;
+    asm("pushfl ; popl %0" : "=rm" (flags));
     return flags;
 }
 
-static inline void irq_restore(unsigned long flags)
+static inline void restore_flags(u32 flags)
 {
     asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc");
 }
@@ -196,6 +195,7 @@ struct descloc_s {
 } PACKED;
 
 // util.c
+void get_cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 struct bregs;
 inline void call16(struct bregs *callregs);
 inline void call16big(struct bregs *callregs);
diff --git a/src/xen.c b/src/xen.c
index 4072793..5f4abdb 100644
--- a/src/xen.c
+++ b/src/xen.c
@@ -55,7 +55,7 @@ void xen_probe(void)
         return;
 
     for (base = 0x40000000; base < 0x40010000; base += 0x100) {
-        cpuid(base, &eax, &ebx, &ecx, &edx);
+        get_cpuid(base, &eax, &ebx, &ecx, &edx);
         memcpy(signature + 0, &ebx, 4);
         memcpy(signature + 4, &ecx, 4);
         memcpy(signature + 8, &edx, 4);
@@ -88,7 +88,7 @@ void xen_init_hypercalls(void)
     if (!usingXen())
         return;
 
-    cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx);
+    get_cpuid(xen_cpuid_base + 2, &eax, &ebx, &ecx, &edx);
 
     xen_hypercall_page = (unsigned long)memalign_high(PAGE_SIZE, eax*PAGE_SIZE);
     if (!xen_hypercall_page)
@@ -99,7 +99,7 @@ void xen_init_hypercalls(void)
         wrmsr(ebx, xen_hypercall_page + (i << 12) + i);
 
     /* Print version information. */
-    cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx);
+    get_cpuid(xen_cpuid_base + 1, &eax, &ebx, &ecx, &edx);
     hypercall_xen_version(XENVER_extraversion, extraversion);
     dprintf(1, "Detected Xen v%u.%u%s\n", eax >> 16, eax & 0xffff, extraversion);
 }



More information about the SeaBIOS mailing list