Skip to contentSkip to conversation

Seabios qemu detect

PATCH In review Jes Sorensen 2 participants 7 messages Aug 4, 2009 – Aug 5, 2009 Kbuild

lore
Share & tools
lore
#1 lore raw

PATCH 1/5 Move QEMU_CFG related code out of smbios.c

In reply to Jes Sorensen

This patch moves QEMU_CFG infrastructure out of smbios.c and puts it into seperate files.

---
 Makefile       |    4 ++--
 src/qemu-cfg.c |   29 +++++++++++++++++++++++++++++
 src/qemu-cfg.h |   19 +++++++++++++++++++
 src/smbios.c   |   22 +---------------------
 4 files changed, 51 insertions(+), 23 deletions(-)
Makefile +2 -2
Index: seabios/Makefile
===================================================================
@@ -16,8 +16,8 @@ SRCBOTH=output.c util.c floppy.c ata.c m
         pnpbios.c pirtable.c vgahooks.c pmm.c
 SRC16=$(SRCBOTH) system.c disk.c apm.c pcibios.c font.c
 SRC32=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
-      acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
-      lzmadecode.c
+      acpi.c smm.c mptable.c qemu-cfg.c smbios.c pciinit.c optionroms.c \
+      mtrr.c lzmadecode.c
 
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
               /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;)
src/qemu-cfg.c new file +29 -0
Index: seabios/src/qemu-cfg.c
===================================================================
@@ -0,0 +1,29 @@
+// qemu-cfg.c: QEMU_CFG related code
+//
+// Copyright (C) 2009  Jes Sorensen, SGI <[email protected]>
+// Copyright (C) 2008  Kevin O'Connor <[email protected]>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "types.h"
+#include "ioport.h"
+#include "qemu-cfg.h"
+
+void
+qemu_cfg_read(u8 *buf, u16 f, int len)
+{
+    outw(f, PORT_QEMU_CFG_CTL);
+    while (len--)
+        *(buf++) = inb(PORT_QEMU_CFG_DATA);
+}
+
+int
+qemu_cfg_port_probe()
+{
+    u8 sig[4] = "QEMU";
+    u8 buf[4];
+    qemu_cfg_read(buf, QEMU_CFG_SIGNATURE, 4);
+    return *(u32*)buf == *(u32*)sig;
+}
+
src/qemu-cfg.h new file +19 -0
Index: seabios/src/qemu-cfg.h
===================================================================
@@ -0,0 +1,19 @@
+// qemu-cfg.h: QEMU_CFG related definitions
+//
+// Copyright (C) 2009  Jes Sorensen, SGI <[email protected]>
+// Copyright (C) 2008  Kevin O'Connor <[email protected]>
+// Copyright (C) 2006 Fabrice Bellard
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#ifndef __QEMU_CFG_H
+#define __QEMU_CFG_H
+
+#define QEMU_CFG_SIGNATURE  0x00
+#define QEMU_CFG_ID         0x01
+#define QEMU_CFG_UUID       0x02
+
+void qemu_cfg_read(u8 *buf, u16 f, int len);
+int qemu_cfg_port_probe();
+
+#endif
src/smbios.c +1 -21
Index: seabios/src/smbios.c
===================================================================
@@ -8,33 +8,13 @@
 #include "util.h" // dprintf
 #include "memmap.h" // malloc_fseg
 #include "biosvar.h" // GET_EBDA
+#include "qemu-cfg.h" // QEMU_CFG_UUID
 
 
 /****************************************************************
  * UUID probe
  ****************************************************************/
 
-#define QEMU_CFG_SIGNATURE  0x00
-#define QEMU_CFG_ID         0x01
-#define QEMU_CFG_UUID       0x02
-
-static void
-qemu_cfg_read(u8 *buf, u16 f, int len)
-{
-    outw(f, PORT_QEMU_CFG_CTL);
-    while (len--)
-        *(buf++) = inb(PORT_QEMU_CFG_DATA);
-}
-
-static int
-qemu_cfg_port_probe()
-{
-    u8 sig[4] = "QEMU";
-    u8 buf[4];
-    qemu_cfg_read(buf, QEMU_CFG_SIGNATURE, 4);
-    return *(u32*)buf == *(u32*)sig;
-}
-
 static void
 uuid_probe(u8 *bios_uuid)
 {
#4 lore raw

PATCH 4/5 Set irq0override based on emu_ver.

In reply to Jes Sorensen

Enable irq0override when we are running on QEMU. All recent versionsof QEMU rely on irq0override, not just for KVM.

---
 src/mptable.c |    4 ----
 src/post.c    |    2 ++
 2 files changed, 2 insertions(+), 4 deletions(-)
src/mptable.c +0 -4
Index: seabios/src/mptable.c
===================================================================
@@ -9,11 +9,7 @@
 #include "config.h" // CONFIG_*
 #include "mptable.h" // MPTABLE_SIGNATURE
 
-#if CONFIG_KVM
-int irq0override = 1;
-#else
 int irq0override = 0;
-#endif
 
 void
 mptable_init(void)
src/post.c +2 -0
Index: seabios/src/post.c
===================================================================
@@ -171,6 +171,8 @@ post()
     qemu_cfg_port_probe();
     if (qemu_cfg_port)
         emu_ver = qemu_cfg_get_emulator_rev();
+    if ((emu_ver & 0xff00) == EMU_QEMU)
+        irq0override = 1;
 
     pic_setup();
     timer_setup();
#2 lore raw

PATCH 2/5 Reorder call for qemu-cfg probing.

In reply to Jes Sorensen

This moves the call to probe for qemu-cfg to an earlier point in the BIOS init. Required in order to use the output for mptable setup etc.

---
 src/post.c     |   10 ++++++++++
 src/qemu-cfg.c |    6 +++++-
 src/smbios.c   |    2 +-
 src/util.h     |    3 +++
 4 files changed, 19 insertions(+), 2 deletions(-)
src/post.c +10 -0
Index: seabios/src/post.c
===================================================================
@@ -18,6 +18,7 @@
 #include "bregs.h" // struct bregs
 #include "mptable.h" // mptable_init
 #include "boot.h" // IPL
+#include "qemu-cfg.h"
 
 void
 __set_irq(int vector, void *loc)
@@ -158,6 +159,15 @@ post()
     init_ivt();
     init_bda();
 
+    /*
+     * Test for emulator earlier, to be able to runtime check whether
+     * we are on QEMU/KVM/Coreboot etc.
+     *
+     * Would be ideal to be able to runtime test for coreboot in here,
+     * if someone knows how to do so reliably.
+     */
+    qemu_cfg_port_probe();
+
     pic_setup();
     timer_setup();
     mathcp_setup();
src/qemu-cfg.c +5 -1
Index: seabios/src/qemu-cfg.c
===================================================================
@@ -10,6 +10,8 @@
 #include "ioport.h"
 #include "qemu-cfg.h"
 
+int qemu_cfg_port = 0;
+
 void
 qemu_cfg_read(u8 *buf, u16 f, int len)
 {
@@ -24,6 +26,8 @@ qemu_cfg_port_probe()
     u8 sig[4] = "QEMU";
     u8 buf[4];
     qemu_cfg_read(buf, QEMU_CFG_SIGNATURE, 4);
-    return *(u32*)buf == *(u32*)sig;
+    if (*(u32*)buf == *(u32*)sig)
+        qemu_cfg_port = 1;
+    return qemu_cfg_port;
 }
 
src/smbios.c +1 -1
Index: seabios/src/smbios.c
===================================================================
@@ -24,7 +24,7 @@ uuid_probe(u8 *bios_uuid)
         return;
     if (CONFIG_COREBOOT)
         return;
-    if (! qemu_cfg_port_probe())
+    if (!qemu_cfg_port)
         // Feature not available
         return;
 
src/util.h +3 -0
Index: seabios/src/util.h
===================================================================
@@ -264,4 +264,7 @@ extern int irq0override;
 // version (auto generated file out/version.c)
 extern const char VERSION[];
 
+// qemu-cfg.c
+extern int qemu_cfg_port;
+
 #endif // util.h
#5 lore raw

PATCH 5/5 Remove CONFIG_KVM and use emu_ver to runtime detect QEMU & KVM.

In reply to Jes Sorensen

This patch makes Seabios use emu_ver to determine QEMU and KVM specific configuration at runtime.

---
 src/acpi.c    |   14 +++++++-------
 src/config.h  |    2 --
 src/pciinit.c |   18 +++++++++++++-----
 src/post.c    |    2 +-
 4 files changed, 21 insertions(+), 15 deletions(-)
src/acpi.c +7 -7
Index: seabios/src/acpi.c
===================================================================
@@ -196,12 +196,8 @@ struct madt_io_apic
                                  * lines start */
 } PACKED;
 
-#if CONFIG_KVM
-/* IRQs 5,9,10,11 */
-#define PCI_ISA_IRQ_MASK    0x0e20
-#else
-#define PCI_ISA_IRQ_MASK    0x0000
-#endif
+/* IRQs 5,9,10,11 for QEMU/KQEMU/KVM */
+#define QEMU_PCI_ISA_IRQ_MASK    0x0e20
 
 struct madt_intsrcovr {
     APIC_HEADER_DEF
@@ -339,8 +335,12 @@ build_madt(struct rsdt_descriptor_rev1 *
         intsrcovr->flags  = 0; /* conforms to bus specifications */
         intsrcovr++;
     }
+    int pci_isa_irq_mask = 0;
+    if ((emu_ver & 0xff00) == EMU_QEMU)
+        pci_isa_irq_mask = QEMU_PCI_ISA_IRQ_MASK;
+
     for (i = 1; i < 16; i++) {
-        if (!(PCI_ISA_IRQ_MASK & (1 << i)))
+        if (!(pci_isa_irq_mask & (1 << i)))
             /* No need for a INT source override structure. */
             continue;
         memset(intsrcovr, 0, sizeof(*intsrcovr));
src/config.h +0 -2
Index: seabios/src/config.h
===================================================================
@@ -12,8 +12,6 @@
 #define CONFIG_APPNAME6 "BOCHS "
 #define CONFIG_APPNAME4 "BXPC"
 
-// Configure for use with KVM.
-#define CONFIG_KVM 1
 // Configure as a coreboot payload.
 #define CONFIG_COREBOOT 0
 
src/pciinit.c +13 -5
Index: seabios/src/pciinit.c
===================================================================
@@ -18,12 +18,15 @@ static u32 pci_bios_io_addr;
 static u32 pci_bios_mem_addr;
 static u32 pci_bios_bigmem_addr;
 /* host irqs corresponding to PCI irqs A-D */
-static u8 pci_irqs[4] = {
-#if CONFIG_KVM
-    10, 10, 11, 11
-#else
+
+static u8 *pci_irqs;
+
+static u8 default_pci_irqs[4] = {
     11, 9, 11, 9
-#endif
+};
+
+static u8 qemu_pci_irqs[4] = {
+    10, 10, 11, 11
 };
 
 static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
@@ -194,6 +197,11 @@ pci_bios_setup(void)
         // Already done by coreboot.
         return;
 
+    if ((emu_ver & 0xff00) == EMU_QEMU)
+        pci_irqs = qemu_pci_irqs;
+    else
+        pci_irqs = default_pci_irqs;
+
     pci_bios_io_addr = 0xc000;
     pci_bios_mem_addr = 0xc0000000;
     pci_bios_bigmem_addr = RamSize;
src/post.c +1 -1
Index: seabios/src/post.c
===================================================================
@@ -129,7 +129,7 @@ ram_probe(void)
              , E820_RESERVED);
     add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED);
 
-    if (CONFIG_KVM)
+    if (emu_ver == EMU_QEMU_KVM)
         // 4 pages before the bios, 3 pages for vmx tss pages, the
         // other page for EPT real mode pagetable
         add_e820(0xfffbc000, 4*4096, E820_RESERVED);
#3 lore raw

PATCH 3/5 Set emu_ver based on information provided by qemu_cfg.

In reply to Jes Sorensen

This patch retrieves the value of QEMU_CFG_EMULATOR and sets emu_ver, allowing the BIOS to runtime verify which emulator it is running on.

---
 src/post.c     |    4 ++++
 src/qemu-cfg.c |    8 ++++++++
 src/qemu-cfg.h |    2 ++
 src/util.h     |    7 +++++++
 4 files changed, 21 insertions(+)
src/post.c +4 -0
Index: seabios/src/post.c
===================================================================
@@ -20,6 +20,8 @@
 #include "boot.h" // IPL
 #include "qemu-cfg.h"
 
+u16 emu_ver;
+
 void
 __set_irq(int vector, void *loc)
 {
@@ -167,6 +169,8 @@ post()
      * if someone knows how to do so reliably.
      */
     qemu_cfg_port_probe();
+    if (qemu_cfg_port)
+        emu_ver = qemu_cfg_get_emulator_rev();
 
     pic_setup();
     timer_setup();
src/qemu-cfg.c +8 -0
Index: seabios/src/qemu-cfg.c
===================================================================
@@ -31,3 +31,11 @@ qemu_cfg_port_probe()
     return qemu_cfg_port;
 }
 
+u16 qemu_cfg_get_emulator_rev(void)
+{
+    u16 rev;
+
+    qemu_cfg_read((u8*)&rev, QEMU_CFG_EMULATOR, sizeof(rev));
+
+    return rev;
+}
src/qemu-cfg.h +2 -0
Index: seabios/src/qemu-cfg.h
===================================================================
@@ -12,8 +12,10 @@
 #define QEMU_CFG_SIGNATURE  0x00
 #define QEMU_CFG_ID         0x01
 #define QEMU_CFG_UUID       0x02
+#define QEMU_CFG_EMULATOR   0x10
 
 void qemu_cfg_read(u8 *buf, u16 f, int len);
 int qemu_cfg_port_probe();
+u16 qemu_cfg_get_emulator_rev(void);
 
 #endif
src/util.h +7 -0
Index: seabios/src/util.h
===================================================================
@@ -267,4 +267,11 @@ extern const char VERSION[];
 // qemu-cfg.c
 extern int qemu_cfg_port;
 
+// port.c
+extern u16 emu_ver;
+#define EMU_NONE            0x0000
+#define EMU_QEMU            0x0100
+#define EMU_QEMU_KVM        0x0101
+#define EMU_QEMU_KQEMU      0x0102
+
 #endif // util.h
#0 lore raw

cover Seabios qemu detect

Hi,

Argh! Forgot to post this yesterday!

Here is a series of patches for Seabios which introduces support for QEMU_CFG_EMULATOR and uses it to select the irq0verride flag and for runtime detection of whether or not Seabios is running on QEMU and KVM.

This allows us to eliminate CONFIG_KVM completely as well.

I would love to see something similar used to detect Coreboot, making it possible to have one shared BIOS binary.

Cheers,
Jes

#6 lore raw
Quoted 8 lines · Jes Sorensen

Hi,

Argh! Forgot to post this yesterday!

Here is a series of patches for Seabios which introduces support for QEMU_CFG_EMULATOR and uses it to select the irq0verride flag and for runtime detection of whether or not Seabios is running on QEMU and KVM.

Thanks Jes.

Once the backend work is committed to qemu or kvm, I think we should check this into SeaBIOS.

A couple of minor notes on style: can you make the global variables use more prominent names (eg, "EmulatorVersion" instead of "emu_ver"), can you abstract the test "(emu_ver & 0xff00) == EMU_QEMU" into a function - as it isn't obvious what it does, and finally, can you move the code you added to post() into qemu_cfg_port_probe() instead?

You asked about detecting coreboot automatically. There are several ways to do this, but probably the easiest is to take advantage of the fact that coreboot uses a dedicated 32bit entry point. See the (poorly named) post32 function in romlayout.S.

Note though, the coreboot case may still need some compile-time checks, because of the code size increase resulting from doing the tests at runtime.

Thanks again,
-Kevin