[SeaBIOS] [RFC] [PATCH 0/2] Basic SeaBIOS support for Xen HVM

Ian Campbell Ian.Campbell at eu.citrix.com
Tue May 17 17:59:08 CEST 2011


On Mon, 2011-05-16 at 19:39 -0400, Kevin O'Connor wrote:
> On Mon, May 16, 2011 at 09:44:28AM +0100, Ian Campbell wrote:
> > Sure. I'll change things to do it that way then.
> > 
> > As well as CONFIG_XEN should I be adding a xen_present variable which is
> > set dynamically and used as appropriate? If so then is a #ifdef to
> > define it to 0 in the !CONFIG_XEN case (to allow the dead code to be
> > eliminated) necessary?
> 
> Thanks.
> 
> I'd suggest something like a "int usingXen(void)" inline which reads
> "xen_present".  The first couple of lines of usingXen() could do a "if
> (!CONFIG_XEN) return 0".

I've done this, although rather than check a xen_present variable I just
check whether or not the xen_hvm_info ptr is NULL. I also needed to move
the call to xen_probe_hvm_info sooner.

> Though - if the code is as simple as the
> patches you've already sent - then you can leave it on permanently for
> emulators (ie, do "if (CONFIG_COREBOOT)") - I'm not worried about a
> few extra bytes for Xen in the emulator case.

I think once we get a xenbus client and some PV drivers etc it will be
an amount worth saving in the !Xen case.

The following implements all your feedback (I hope). I have squashed it
down into a single commit which supports direct boot.

Ian.

>From 25fdf95c608c73a00a72f0aa1bc72cbd9c03d4ce Mon Sep 17 00:00:00 2001
From: Ian Campbell <ian.campbell at citrix.com>
Date: Tue, 17 May 2011 16:43:34 +0100
Subject: [PATCH] Kconfig: Add basic support for booting directly as Xen HVM firmware

This allows a guest to be booted using SeaBIOS directly as its
firmware rather than being loaded indirectly via hvmloader.

Signed-off-by: Ian Campbell <ian.campbell at citrix.com>
---
 Makefile                     |    2 +-
 src/Kconfig                  |    6 +++
 src/post.c                   |   19 ++++++++++
 src/shadow.c                 |    5 ++-
 src/xen.c                    |   57 ++++++++++++++++++++++++++++++++
 src/xen.h                    |   18 ++++++++++
 src/xen/hvm/hvm_info_table.h |   75 ++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 179 insertions(+), 3 deletions(-)
 create mode 100644 src/xen.c
 create mode 100644 src/xen.h
 create mode 100644 src/xen/hvm/hvm_info_table.h

diff --git a/Makefile b/Makefile
index 9affb39..6f12d5a 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ SRC16=$(SRCBOTH) system.c disk.c font.c
 SRC32FLAT=$(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 bootsplash.c jpeg.c usb-hub.c paravirt.c dev-i440fx.c \
-      pci_region.c
+      pci_region.c xen.c
 SRC32SEG=util.c output.c pci.c pcibios.c apm.c stacks.c
 
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
diff --git a/src/Kconfig b/src/Kconfig
index 3133d88..69b63b3 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -10,6 +10,12 @@ menu "General Features"
         help
             Configure as a coreboot payload.
 
+    config XEN
+        bool "Build for Xen HVM"
+        default n
+        help
+            Configure to be used by xen hvmloader, for a HVM guest.
+
     config THREADS
         bool "Parallelize hardware init"
         default y
diff --git a/src/post.c b/src/post.c
index 7d2b5f2..6703f5e 100644
--- a/src/post.c
+++ b/src/post.c
@@ -23,6 +23,7 @@
 #include "usb.h" // usb_setup
 #include "smbios.h" // smbios_init
 #include "paravirt.h" // qemu_cfg_port_probe
+#include "xen.h" // xen_probe_hvm_info
 #include "ps2port.h" // ps2port_setup
 #include "virtio-blk.h" // virtio_blk_setup
 
@@ -101,6 +102,22 @@ ram_probe(void)
     dprintf(3, "Find memory size\n");
     if (CONFIG_COREBOOT) {
         coreboot_setup();
+    } else if (usingXen()) {
+        RamSize = xen_hvm_info->low_mem_pgend << 12;
+
+        add_e820(0, RamSize, E820_RAM);
+        if (xen_hvm_info->high_mem_pgend) {
+            RamSizeOver4G = ((u64)xen_hvm_info->high_mem_pgend - 0x100000ull) << 12ull;
+            add_e820(0x100000000ull, RamSizeOver4G, E820_RAM);
+        } else {
+            RamSizeOver4G = 0;
+        }
+
+        if (xen_hvm_info->reserved_mem_pgstart) {
+            u32 reserved_base = xen_hvm_info->reserved_mem_pgstart<<12;
+            u64 reserved_size = 0x100000000ull - reserved_base;
+            add_e820(reserved_base, reserved_size, E820_RESERVED);
+        }
     } else {
         // On emulators, get memory size from nvram.
         u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16)
@@ -380,6 +397,8 @@ _start(void)
         // This is a soft reboot - invoke a hard reboot.
         tryReboot();
 
+    xen_probe_hvm_info();
+
     // Allow writes to modify bios area (0xf0000)
     make_bios_writable();
     HaveRunPost = 1;
diff --git a/src/shadow.c b/src/shadow.c
index ed530e0..cb39ddf 100644
--- a/src/shadow.c
+++ b/src/shadow.c
@@ -10,6 +10,7 @@
 #include "config.h" // CONFIG_*
 #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
 #include "dev-i440fx.h"
+#include "xen.h" // usingXen
 
 // On the emulators, the bios at 0xf0000 is also at 0xffff0000
 #define BIOS_SRC_OFFSET 0xfff00000
@@ -102,7 +103,7 @@ static const struct pci_device_id dram_controller_make_writable_tbl[] = {
 void
 make_bios_writable(void)
 {
-    if (CONFIG_COREBOOT)
+    if (CONFIG_COREBOOT || usingXen())
         return;
 
     dprintf(3, "enabling shadow ram\n");
@@ -127,7 +128,7 @@ static const struct pci_device_id dram_controller_make_readonly_tbl[] = {
 void
 make_bios_readonly(void)
 {
-    if (CONFIG_COREBOOT)
+    if (CONFIG_COREBOOT || usingXen())
         return;
 
     dprintf(3, "locking shadow ram\n");
diff --git a/src/xen.c b/src/xen.c
new file mode 100644
index 0000000..3b3b79a
--- /dev/null
+++ b/src/xen.c
@@ -0,0 +1,57 @@
+// Xen HVM support
+//
+// Copyright (C) 2011 Citrix Systems.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "config.h"
+#include "xen.h"
+#include "cmos.h"
+
+struct hvm_info_table *xen_hvm_info = NULL;
+
+static int validate_hvm_info(struct hvm_info_table *t)
+{
+    if ( memcmp(t->signature, "HVM INFO", 8) )
+        return 1;
+
+    if ( t->length < sizeof(struct hvm_info_table) )
+        return 1;
+
+    if (checksum(t, t->length) != 0)
+        return 1;
+
+    return 0;
+}
+
+void xen_probe_hvm_info(void)
+{
+    struct hvm_info_table *t;
+
+    if (!CONFIG_XEN)
+        return;
+
+    dprintf(1, "Probing for Xen HVM info\n");
+
+    t = (struct hvm_info_table *)HVM_INFO_PADDR;
+
+    if (validate_hvm_info(t)) {
+        dprintf(1, "Xen HVM info not found\n");
+        return;
+    }
+
+    xen_hvm_info = t;
+
+    dprintf(1, "Found HVM info table at %p\n", t);
+    dprintf(1, "Signature %c%c%c%c%c%c%c%c\n",
+            t->signature[0], t->signature[1],
+            t->signature[2], t->signature[3],
+            t->signature[4], t->signature[5],
+            t->signature[6], t->signature[7]);
+    dprintf(1, "Length %d, checksum %x\n", t->length, t->checksum);
+    dprintf(1, "ACPI:%d APIC:%d VCPUS:%d\n",
+            t->acpi_enabled, t->apic_mode, t->nr_vcpus);
+    dprintf(1, "low_mem_pgend:        %x\n", t->low_mem_pgend);
+    dprintf(1, "high_mem_pgend:       %x\n", t->high_mem_pgend);
+    dprintf(1, "reserved_mem_pgstart: %x\n", t->reserved_mem_pgstart);
+}
diff --git a/src/xen.h b/src/xen.h
new file mode 100644
index 0000000..723e0c5
--- /dev/null
+++ b/src/xen.h
@@ -0,0 +1,18 @@
+#ifndef __XEN_H
+#define __XEN_H
+
+#include "util.h"
+
+#include "xen/hvm/hvm_info_table.h"
+
+void xen_probe_hvm_info(void);
+
+extern struct hvm_info_table *xen_hvm_info;
+
+static inline int usingXen(void) {
+    if (!CONFIG_XEN)
+	return 0;
+    return (xen_hvm_info != NULL);
+}
+
+#endif
diff --git a/src/xen/hvm/hvm_info_table.h b/src/xen/hvm/hvm_info_table.h
new file mode 100644
index 0000000..e665883
--- /dev/null
+++ b/src/xen/hvm/hvm_info_table.h
@@ -0,0 +1,75 @@
+/******************************************************************************
+ * hvm/hvm_info_table.h
+ *
+ * HVM parameter and information table, written into guest memory map.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__
+#define __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__
+
+#define HVM_INFO_PFN         0x09F
+#define HVM_INFO_OFFSET      0x800
+#define HVM_INFO_PADDR       ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET)
+
+/* Maximum we can support with current vLAPIC ID mapping. */
+#define HVM_MAX_VCPUS        128
+
+struct hvm_info_table {
+    char        signature[8]; /* "HVM INFO" */
+    u32         length;
+    u8          checksum;
+
+    /* Should firmware build ACPI tables? */
+    u8          acpi_enabled;
+
+    /* Should firmware build APIC descriptors (APIC MADT / MP BIOS)? */
+    u8          apic_mode;
+
+    /* How many CPUs does this domain have? */
+    u32         nr_vcpus;
+
+    /*
+     * MEMORY MAP provided by HVM domain builder.
+     * Notes:
+     *  1. page_to_phys(x) = x << 12
+     *  2. If a field is zero, the corresponding range does not exist.
+     */
+    /*
+     *  0x0 to page_to_phys(low_mem_pgend)-1:
+     *    RAM below 4GB (except for VGA hole 0xA0000-0xBFFFF)
+     */
+    u32         low_mem_pgend;
+    /*
+     *  page_to_phys(reserved_mem_pgstart) to 0xFFFFFFFF:
+     *    Reserved for special memory mappings
+     */
+    u32         reserved_mem_pgstart;
+    /*
+     *  0x100000000 to page_to_phys(high_mem_pgend)-1:
+     *    RAM above 4GB
+     */
+    u32         high_mem_pgend;
+
+    /* Bitmap of which CPUs are online at boot time. */
+    u8          vcpu_online[(HVM_MAX_VCPUS + 7)/8];
+};
+
+#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
-- 
1.7.2.5






More information about the SeaBIOS mailing list