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@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@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__ */