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

Kevin O'Connor kevin at koconnor.net
Sun Jan 29 20:30:06 CET 2012


On Sun, Jan 29, 2012 at 02:02:38PM -0500, Kevin O'Connor wrote:
> On Sun, Jan 29, 2012 at 07:56:05PM +0100, Rudolf Marek wrote:
> > Hi,
> > 
> > Sure why not. The idea behind the variable use was not to perform
> > the test everytime as you suggested on the IRC channel. But I like
> > this variant too, lets give it a go.
> 
> Yeah - sorry about that - the fact that cpuid is needed so early makes
> it painful to cache the results.  Also, cpuid isn't really called
> frequently, so I don't think there's much harm in doing explicit
> detection.  Now that I think about it, though, it's probably better to
> keep the name cpuid() and rename the low-level cpuid to __cpuid().

New patch below.

-Kevin


commit dabc0039ece59cabc37bf1164e76be7c7af0eea5
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/mtrr.c b/src/mtrr.c
index 0548043..ec3be4f 100644
--- a/src/mtrr.c
+++ b/src/mtrr.c
@@ -84,9 +84,9 @@ void mtrr_setup(void)
     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;
+        /* 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);
     for (i=0; i<vcnt; i++) {
diff --git a/src/paravirt.h b/src/paravirt.h
index 4a370a0..9674089 100644
--- a/src/paravirt.h
+++ b/src/paravirt.h
@@ -11,6 +11,8 @@
 
 static inline int kvm_para_available(void)
 {
+    if (CONFIG_COREBOOT)
+        return 0;
     unsigned int eax, ebx, ecx, edx;
     char signature[13];
 
diff --git a/src/util.c b/src/util.c
index ed73d63..53ef84d 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
+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..2c5f7eb 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 volatile("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");
 }
@@ -54,7 +53,7 @@ static inline void wbinvd(void)
 #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)
+static inline void __cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
 {
     asm("cpuid"
         : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
@@ -196,6 +195,7 @@ struct descloc_s {
 } PACKED;
 
 // util.c
+void 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);



More information about the SeaBIOS mailing list