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@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);