[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 2/2] 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. This is
presented as a proof of concept since it's not obvious yet which the
best approach will be from either Xen or SeaBIOS's point of view.

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 Makefile                     |    2 +-
 src/post.c                   |    5 ++
 src/xen.c                    |   93 ++++++++++++++++++++++++++++++++++++++++++
 src/xen.h                    |   26 ++++++++++++
 src/xen/hvm/hvm_info_table.h |   75 +++++++++++++++++++++++++++++++++
 5 files changed, 200 insertions(+), 1 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/post.c b/src/post.c
index 7d2b5f2..a2bd2d7 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
 
@@ -123,6 +124,9 @@ ram_probe(void)
 
         /* reserve 256KB BIOS area at the end of 4 GB */
         add_e820(0xfffc0000, 256*1024, E820_RESERVED);
+
+       if (xen_reserved_size)
+           add_e820(0x100000000ull-xen_reserved_size, xen_reserved_size, 
E820_RESERVED);
     }
 
     // Don't declare any memory between 0xa0000 and 0x100000
@@ -329,6 +333,7 @@ post(void)
 {
     // Detect ram and setup internal malloc.
     qemu_cfg_port_probe();
+    xen_probe_hvm_info();
     ram_probe();
     malloc_setup();
 
diff --git a/src/xen.c b/src/xen.c
new file mode 100644
index 0000000..29e7e68
--- /dev/null
+++ b/src/xen.c
@@ -0,0 +1,93 @@
+// 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"
+
+u32 xen_reserved_size = 0;
+u32 xen_nr_vcpus = 0;
+
+struct hvm_info_table *xen_hvm_info;
+
+static void validate_hvm_info(struct hvm_info_table *t)
+{
+    u8 *ptr = (u8 *)t;
+    u8 sum = 0;
+    int i;
+
+    if ( memcmp(t->signature, "HVM INFO", 8) )
+        panic("Bad hvm info signature\n");
+
+    if ( t->length < sizeof(struct hvm_info_table) )
+        panic("Bad hvm info length\n");
+
+    for ( i = 0; i < t->length; i++ )
+        sum += ptr[i];
+
+    if ( sum != 0 )
+        panic("Bad hvm info checksum\n");
+}
+
+/* Replace possibly erroneous memory-size CMOS fields with correct values. */
+static void cmos_write_memory_size(u32 low_mem_pgend, u32 high_mem_pgend)
+{
+    u32 base_mem = 640, ext_mem, alt_mem;
+    u64 high = high_mem_pgend ? ((u64)high_mem_pgend << 12) - 0x100000000ull : 
0ull;
+
+    alt_mem = ext_mem = low_mem_pgend << 12;
+    ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
+    if ( ext_mem > 0xffff )
+        ext_mem = 0xffff;
+    alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
+
+    /* All BIOSes: conventional memory (CMOS *always* reports 640kB). */
+    outb_cmos((u8)(base_mem >> 0), 0x15);
+    outb_cmos((u8)(base_mem >> 8), 0x16);
+
+    /* All BIOSes: extended memory (1kB chunks above 1MB). */
+    outb_cmos((u8)( ext_mem >> 0), CMOS_MEM_EXTMEM_LOW);
+    outb_cmos((u8)( ext_mem >> 8), CMOS_MEM_EXTMEM_HIGH);
+
+    /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */
+    outb_cmos((u8)( alt_mem >> 0), CMOS_MEM_EXTMEM2_LOW);
+    outb_cmos((u8)( alt_mem >> 8), CMOS_MEM_EXTMEM2_HIGH);
+
+    /* RAM above 4GB */
+    outb_cmos((u8) ((high >> 16) & 0xff), CMOS_MEM_HIGHMEM_LOW);
+    outb_cmos((u8) ((high >> 24) & 0xff), CMOS_MEM_HIGHMEM_MID);
+    outb_cmos((u8) ((high >> 32) & 0xff), CMOS_MEM_HIGHMEM_HIGH);
+}
+
+void xen_probe_hvm_info(void)
+{
+    struct hvm_info_table *t;
+
+    t = (struct hvm_info_table *)HVM_INFO_PADDR;
+
+    validate_hvm_info(t);
+
+    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);
+
+    cmos_write_memory_size(t->low_mem_pgend, t->high_mem_pgend);
+
+    xen_reserved_size = (u32)(0x100000000ull - 
((u64)t->reserved_mem_pgstart<<12));
+
+    xen_nr_vcpus = t->nr_vcpus;
+}
diff --git a/src/xen.h b/src/xen.h
new file mode 100644
index 0000000..eef9a0e
--- /dev/null
+++ b/src/xen.h
@@ -0,0 +1,26 @@
+#ifndef __XEN_H
+#define __XEN_H
+
+#ifdef CONFIG_XEN
+
+#include "util.h"
+
+#include "xen/hvm/hvm_info_table.h"
+
+void xen_probe_hvm_info(void);
+
+extern u32 xen_reserved_size;
+extern u32 xen_nr_vcpus;
+
+extern struct hvm_info_table *xen_hvm_info;
+
+#else
+
+static voic xen_probe_hvm_info(void) {}
+
+#define xen_reserved_size 0
+#define xen_nr_vcpus 0
+
+#endif
+
+#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


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.