[SeaBIOS] [BROKEN RFC 2/5] move hypervisor detection to "util.c" (SRCBOTH)

Laszlo Ersek lersek at redhat.com
Wed Feb 13 04:52:11 CET 2013


Enabling CONFIG_DEBUG_IO for putc_debug() [src/output.c] exposes the
following during the vgabios build:

- the "PlatformRunningOn" variable has no external definition in that
  build, and

- even though putc_debug() is SRCBOTH (consequently, SRC16 too), the
  hypervisor-dependent initialization functions of "PlatformRunningOn"
  (kvm_preinit() / xen_preinit()) are defined in SRC32FLAT files only
  ([src/paravirt.c] / [src/xen.c], respectively).

This makes it impossible to use "PlatformRunningOn" in SRC16 code (even if
it was defined, it wouldn't be initialized), which means that we can't
print to the qemu debug port in SRC16 code.

The init functions depend on SRCBOTH functionality only:
- [src/util.c]: cpuid(), memcpy(), strcmp(), dprintf(),
- [src/output.c]: panic(), DebugOutputPort,

hence extract / move both definition and initialization of
"PlatformRunningOn" to SRCBOTH [src/util.c]. Assignment to global
variables is made with SET_FARVAR(), mimicking SET_VGA().

This should allow us to use CONFIG_DEBUG_IO even in vgabios and Legacy16
CSM callbacks.

Signed-off-by: Laszlo Ersek <lersek at redhat.com>
---
 src/paravirt.h |   22 ------------------
 src/util.h     |   30 +++++++++++++++++++++++++
 src/misc.c     |    2 -
 src/paravirt.c |   27 +----------------------
 src/xen.c      |   30 +-----------------------
 src/util.c     |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/apm.c      |    1 -
 src/esp-scsi.c |    1 -
 src/lsi-scsi.c |    1 -
 src/output.c   |    1 -
 10 files changed, 99 insertions(+), 82 deletions(-)

diff --git a/src/paravirt.h b/src/paravirt.h
index a3da04d..d6fbf99 100644
--- a/src/paravirt.h
+++ b/src/paravirt.h
@@ -1,28 +1,6 @@
 #ifndef __PV_H
 #define __PV_H
 
-#include "config.h" // CONFIG_*
-#include "biosvar.h" // GET_GLOBAL
-
-// Types of paravirtualized platforms.
-#define PF_QEMU     (1<<0)
-#define PF_XEN      (1<<1)
-#define PF_KVM      (1<<2)
-
-// misc.c
-extern int PlatformRunningOn;
-
-static inline int runningOnQEMU(void) {
-    return CONFIG_QEMU || (
-        CONFIG_QEMU_HARDWARE && GET_GLOBAL(PlatformRunningOn) & PF_QEMU);
-}
-static inline int runningOnXen(void) {
-    return CONFIG_XEN && GET_GLOBAL(PlatformRunningOn) & PF_XEN;
-}
-static inline int runningOnKVM(void) {
-    return CONFIG_QEMU && GET_GLOBAL(PlatformRunningOn) & PF_KVM;
-}
-
 void qemu_ramsize_preinit(void);
 void qemu_biostable_setup(void);
 void qemu_cfg_preinit(void);
diff --git a/src/util.h b/src/util.h
index 04c5a9d..15e7ce9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -7,6 +7,8 @@
 #define __UTIL_H
 
 #include "types.h" // u32
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
 
 static inline void irq_disable(void)
 {
@@ -149,6 +151,34 @@ struct descloc_s {
 } PACKED;
 
 // util.c
+
+// Types of paravirtualized platforms.
+#define PF_QEMU     (1<<0)
+#define PF_XEN      (1<<1)
+#define PF_KVM      (1<<2)
+
+extern int PlatformRunningOn;
+
+static inline int runningOnQEMU(void) {
+    return CONFIG_QEMU || (
+        CONFIG_QEMU_HARDWARE && GET_GLOBAL(PlatformRunningOn) & PF_QEMU);
+}
+static inline int runningOnXen(void) {
+    return CONFIG_XEN && GET_GLOBAL(PlatformRunningOn) & PF_XEN;
+}
+static inline int runningOnKVM(void) {
+    return CONFIG_QEMU && GET_GLOBAL(PlatformRunningOn) & PF_KVM;
+}
+
+void qemu_kvm_preinit(void);
+
+#define XEN_CPUID_BASE_MIN 0x40000000
+#define XEN_CPUID_BASE_MAX 0x40010000
+
+// return Xen CPUID base in [XEN_CPUID_BASE_MIN, XEN_CPUID_BASE_MAX)
+// returns >= XEN_CPUID_BASE_MAX if Xen was not found
+u32 __xen_preinit(void);
+
 void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 u8 checksum_far(u16 buf_seg, void *buf_far, u32 len);
 u8 checksum(void *buf, u32 len);
diff --git a/src/misc.c b/src/misc.c
index 3b2ffc1..bcc450a 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -16,8 +16,6 @@ u32 RamSize VAR16VISIBLE;
 u64 RamSizeOver4G;
 // Space for bios tables built an run-time.
 char BiosTableSpace[CONFIG_MAX_BIOSTABLE] __aligned(MALLOC_MIN_ALIGN) VAR16VISIBLE;
-// Type of emulator platform.
-int PlatformRunningOn VAR16VISIBLE;
 
 
 /****************************************************************
diff --git a/src/paravirt.c b/src/paravirt.c
index cc64094..0e6bc92 100644
--- a/src/paravirt.c
+++ b/src/paravirt.c
@@ -25,38 +25,13 @@ struct e820_reservation {
     u32 type;
 };
 
-/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx.  It
- * should be used to determine that a VM is running under KVM.
- */
-#define KVM_CPUID_SIGNATURE     0x40000000
-
-static void kvm_preinit(void)
-{
-    if (!CONFIG_QEMU)
-        return;
-    unsigned int eax, ebx, ecx, edx;
-    char signature[13];
-
-    cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
-    memcpy(signature + 0, &ebx, 4);
-    memcpy(signature + 4, &ecx, 4);
-    memcpy(signature + 8, &edx, 4);
-    signature[12] = 0;
-
-    if (strcmp(signature, "KVMKVMKVM") == 0) {
-        dprintf(1, "Running on KVM\n");
-        PlatformRunningOn |= PF_KVM;
-    }
-}
-
 void
 qemu_ramsize_preinit(void)
 {
     if (!CONFIG_QEMU)
         return;
 
-    PlatformRunningOn = PF_QEMU;
-    kvm_preinit();
+    qemu_kvm_preinit();
 
     // On emulators, get memory size from nvram.
     u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16)
diff --git a/src/xen.c b/src/xen.c
index e34f25c..8eb7ab4 100644
--- a/src/xen.c
+++ b/src/xen.c
@@ -6,7 +6,6 @@
 
 #include "config.h"
 #include "xen.h"
-#include "paravirt.h" // PlatformRunningOn
 #include "memmap.h" // add_e820
 #include "types.h" // ASM32FLAT
 #include "util.h" // copy_acpi_rsdp
@@ -50,37 +49,12 @@ static void validate_info(struct xen_seabios_info *t)
 
 void xen_preinit(void)
 {
-    u32 base, eax, ebx, ecx, edx;
-    char signature[13];
-
     if (!CONFIG_XEN)
         return;
 
-    for (base = 0x40000000; base < 0x40010000; base += 0x100) {
-        cpuid(base, &eax, &ebx, &ecx, &edx);
-        memcpy(signature + 0, &ebx, 4);
-        memcpy(signature + 4, &ecx, 4);
-        memcpy(signature + 8, &edx, 4);
-        signature[12] = 0;
-
-        dprintf(9, "Found hypervisor signature \"%s\" at %x\n",
-                signature, base);
-        if (strcmp(signature, "XenVMMXenVMM") == 0) {
-            /* Set debug_io_port first, so the following messages work. */
-            DebugOutputPort = 0xe9;
-            dprintf(1, "SeaBIOS (version %s)\n\n", VERSION);
-            dprintf(1, "Found Xen hypervisor signature at %x\n", base);
-            if ((eax - base) < 2)
-                panic("Insufficient Xen cpuid leaves. eax=%x at base %x\n",
-                      eax, base);
-            xen_cpuid_base = base;
-            break;
-        }
-    }
-    if (!xen_cpuid_base)
+    xen_cpuid_base = __xen_preinit();
+    if (xen_cpuid_base >= XEN_CPUID_BASE_MAX)
         panic("No Xen hypervisor found.\n");
-
-    PlatformRunningOn = PF_QEMU|PF_XEN;
 }
 
 static int hypercall_xen_version( int cmd, void *arg)
diff --git a/src/util.c b/src/util.c
index dcc0b71..8ba4eb0 100644
--- a/src/util.c
+++ b/src/util.c
@@ -8,6 +8,72 @@
 #include "bregs.h" // struct bregs
 #include "config.h" // BUILD_STACK_ADDR
 
+// Type of emulator platform.
+int PlatformRunningOn VAR16VISIBLE;
+
+/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx.  It
+ * should be used to determine that a VM is running under KVM.
+ */
+#define KVM_CPUID_SIGNATURE     0x40000000
+
+void qemu_kvm_preinit(void)
+{
+    unsigned int eax, ebx, ecx, edx;
+    char signature[13];
+
+    if (!CONFIG_QEMU)
+        return;
+
+    SET_FARVAR(get_global_seg(), PlatformRunningOn, PF_QEMU);
+
+    cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
+    memcpy(signature + 0, &ebx, 4);
+    memcpy(signature + 4, &ecx, 4);
+    memcpy(signature + 8, &edx, 4);
+    signature[12] = 0;
+
+    if (strcmp(signature, "KVMKVMKVM") == 0) {
+        dprintf(1, "Running on KVM\n");
+        SET_FARVAR(get_global_seg(), PlatformRunningOn, PF_QEMU|PF_KVM);
+    }
+}
+
+u32 __xen_preinit(void)
+{
+    u32 base, eax, ebx, ecx, edx;
+    char signature[13];
+
+    if (!CONFIG_XEN)
+        return XEN_CPUID_BASE_MAX;
+
+    for (base = XEN_CPUID_BASE_MIN; base < XEN_CPUID_BASE_MAX; base += 0x100) {
+        cpuid(base, &eax, &ebx, &ecx, &edx);
+        memcpy(signature + 0, &ebx, 4);
+        memcpy(signature + 4, &ecx, 4);
+        memcpy(signature + 8, &edx, 4);
+        signature[12] = 0;
+
+        dprintf(9, "Found hypervisor signature \"%s\" at %x\n",
+                signature, base);
+        if (strcmp(signature, "XenVMMXenVMM") == 0) {
+            /* Set debug_io_port first, so the following messages work. */
+            SET_FARVAR(get_global_seg(), DebugOutputPort, 0xe9);
+            dprintf(1, "SeaBIOS (version %s)\n\n", VERSION);
+            dprintf(1, "Found Xen hypervisor signature at %x\n", base);
+            if ((eax - base) < 2)
+                panic("Insufficient Xen cpuid leaves. eax=%x at base %x\n",
+                      eax, base);
+            break;
+        }
+    }
+
+    if (base < XEN_CPUID_BASE_MAX) {
+        SET_FARVAR(get_global_seg(), PlatformRunningOn, PF_QEMU|PF_XEN);
+    }
+
+    return base;
+}
+
 void
 cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
 {
diff --git a/src/apm.c b/src/apm.c
index b2eac6d..6f9434b 100644
--- a/src/apm.c
+++ b/src/apm.c
@@ -11,7 +11,6 @@
 #include "util.h" // dprintf
 #include "config.h" // CONFIG_*
 #include "biosvar.h" // GET_GLOBAL
-#include "paravirt.h" // runningOnQEMU
 
 static void
 out_str(const char *str_cs)
diff --git a/src/esp-scsi.c b/src/esp-scsi.c
index fe70366..e875676 100644
--- a/src/esp-scsi.c
+++ b/src/esp-scsi.c
@@ -18,7 +18,6 @@
 #include "pci_regs.h" // PCI_VENDOR_ID
 #include "boot.h" // bootprio_find_scsi_device
 #include "blockcmd.h" // scsi_drive_setup
-#include "paravirt.h" // runningOnQEMU
 #include "disk.h"
 
 #define ESP_TCLO      0x00
diff --git a/src/lsi-scsi.c b/src/lsi-scsi.c
index 305610a..78d2f3d 100644
--- a/src/lsi-scsi.c
+++ b/src/lsi-scsi.c
@@ -18,7 +18,6 @@
 #include "pci_regs.h" // PCI_VENDOR_ID
 #include "boot.h" // bootprio_find_scsi_device
 #include "blockcmd.h" // scsi_drive_setup
-#include "paravirt.h" // runningOnQEMU
 #include "disk.h"
 
 #define LSI_REG_DSTAT     0x0c
diff --git a/src/output.c b/src/output.c
index 27621f5..9d8f8d9 100644
--- a/src/output.c
+++ b/src/output.c
@@ -11,7 +11,6 @@
 #include "bregs.h" // struct bregs
 #include "config.h" // CONFIG_*
 #include "biosvar.h" // GET_GLOBAL
-#include "paravirt.h" // runningOnQEMU
 
 struct putcinfo {
     void (*func)(struct putcinfo *info, char c);
-- 
1.7.1





More information about the SeaBIOS mailing list