[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