Detect CPUID instruction before using it.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 29 Jan 2012 18:30:56 +0000 (13:30 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Thu, 2 Feb 2012 01:42:45 +0000 (20:42 -0500)
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@assembler.cz>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
src/bregs.h
src/mtrr.c
src/paravirt.h
src/util.c
src/util.h

index f026fa81e513faa70c342c2997149a390ec33c1e..577effc0e5b76b2164cada64091dcac02aa0d2fe 100644 (file)
@@ -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
index 0548043376986bf861b4158ca8808b8e1a0a251f..ec3be4f3aa66fcf76eed22183ab87ce30ed92dbe 100644 (file)
@@ -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++) {
index 4a370a0cb2b738076fda3ab5facdb49e20cd0369..96740893b8ba790d07e76fa05f94a2d97a867a4f 100644 (file)
@@ -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];
 
index ed73d632f11e619d1e83fbba7d7c581f82adc481..53ef84ded96dfb230c3162b4bafded88fa3394cf 100644 (file)
@@ -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
index eecba8b21ee1ab0766a9cf608f0e5d4fc041f18d..2c5f7ebc37931efe2b4fba97c602019aed1d4cf7 100644 (file)
@@ -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);