598a3740c6
virtualization on 32-bit exposes host crash CVE-2013-0151-xsa34.patch - bnc#797287 - VUL-0: Xen: XSA-35 (CVE-2013-0152) - Nested HVM exposes host to being driven out of memory by guest CVE-2013-0152-xsa35.patch - bnc#793717 - NetWare will not boot on Xen 4.2 xnloader.py domUloader.py pygrub-netware-xnloader.patch Removed reverse-24757-use-grant-references.patch - bnc#797523 - VUL-1: CVE-2012-6075: qemu / kvm-qemu: e1000 overflows under some conditions CVE-2012-6075-xsa41.patch - Mask the floating point exceptions for guests like NetWare on machines that support XSAVE. x86-fpu-context-conditional.patch - fate##313584: pass bios information to XEN HVM guest 26341-hvm-firmware-passthrough.patch 26342-hvm-firmware-passthrough.patch 26343-hvm-firmware-passthrough.patch 26344-hvm-firmware-passthrough.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=223
283 lines
9.7 KiB
Diff
283 lines
9.7 KiB
Diff
fate#313584: pass bios information to XEN HVM guest
|
|
|
|
# HG changeset patch
|
|
# User Ross Philipson <ross.philipson@citrix.com>
|
|
# Date 1357838241 0
|
|
# Node ID cabf395a6c849cc65e56f1640b18db0c3e0faf5d
|
|
# Parent 07bf59a7ce837bd795e2df2f28166cfe41990d3d
|
|
HVM firmware passthrough control tools support
|
|
|
|
Xen control tools support for loading the firmware passthrough blocks
|
|
during domain construction. SMBIOS and ACPI blocks are passed in using
|
|
the new xc_hvm_build_args structure. Each block is read and loaded
|
|
into the new domain address space behind the HVMLOADER image. The base
|
|
address for the two blocks is returned as an out parameter to the
|
|
caller via the args structure.
|
|
|
|
Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
|
|
Committed-by: Keir Fraser <keir@xen.org>
|
|
|
|
diff -r 07bf59a7ce83 -r cabf395a6c84 tools/libxc/xc_hvm_build_arm.c
|
|
--- a/tools/libxc/xc_hvm_build_arm.c Thu Jan 10 17:16:28 2013 +0000
|
|
+++ b/tools/libxc/xc_hvm_build_arm.c Thu Jan 10 17:17:21 2013 +0000
|
|
@@ -22,7 +22,7 @@
|
|
#include <xenguest.h>
|
|
|
|
int xc_hvm_build(xc_interface *xch, uint32_t domid,
|
|
- const struct xc_hvm_build_args *hvm_args)
|
|
+ struct xc_hvm_build_args *hvm_args)
|
|
{
|
|
errno = ENOSYS;
|
|
return -1;
|
|
diff -r 07bf59a7ce83 -r cabf395a6c84 tools/libxc/xc_hvm_build_x86.c
|
|
--- a/tools/libxc/xc_hvm_build_x86.c Thu Jan 10 17:16:28 2013 +0000
|
|
+++ b/tools/libxc/xc_hvm_build_x86.c Thu Jan 10 17:17:21 2013 +0000
|
|
@@ -49,6 +49,40 @@
|
|
#define NR_SPECIAL_PAGES 8
|
|
#define special_pfn(x) (0xff000u - NR_SPECIAL_PAGES + (x))
|
|
|
|
+static int modules_init(struct xc_hvm_build_args *args,
|
|
+ uint64_t vend, struct elf_binary *elf,
|
|
+ uint64_t *mstart_out, uint64_t *mend_out)
|
|
+{
|
|
+#define MODULE_ALIGN 1UL << 7
|
|
+#define MB_ALIGN 1UL << 20
|
|
+#define MKALIGN(x, a) (((uint64_t)(x) + (a) - 1) & ~(uint64_t)((a) - 1))
|
|
+ uint64_t total_len = 0, offset1 = 0;
|
|
+
|
|
+ if ( (args->acpi_module.length == 0)&&(args->smbios_module.length == 0) )
|
|
+ return 0;
|
|
+
|
|
+ /* Find the total length for the firmware modules with a reasonable large
|
|
+ * alignment size to align each the modules.
|
|
+ */
|
|
+ total_len = MKALIGN(args->acpi_module.length, MODULE_ALIGN);
|
|
+ offset1 = total_len;
|
|
+ total_len += MKALIGN(args->smbios_module.length, MODULE_ALIGN);
|
|
+
|
|
+ /* Want to place the modules 1Mb+change behind the loader image. */
|
|
+ *mstart_out = MKALIGN(elf->pend, MB_ALIGN) + (MB_ALIGN);
|
|
+ *mend_out = *mstart_out + total_len;
|
|
+
|
|
+ if ( *mend_out > vend )
|
|
+ return -1;
|
|
+
|
|
+ if ( args->acpi_module.length != 0 )
|
|
+ args->acpi_module.guest_addr_out = *mstart_out;
|
|
+ if ( args->smbios_module.length != 0 )
|
|
+ args->smbios_module.guest_addr_out = *mstart_out + offset1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void build_hvm_info(void *hvm_info_page, uint64_t mem_size,
|
|
uint64_t mmio_start, uint64_t mmio_size)
|
|
{
|
|
@@ -86,9 +120,8 @@ static void build_hvm_info(void *hvm_inf
|
|
hvm_info->checksum = -sum;
|
|
}
|
|
|
|
-static int loadelfimage(
|
|
- xc_interface *xch,
|
|
- struct elf_binary *elf, uint32_t dom, unsigned long *parray)
|
|
+static int loadelfimage(xc_interface *xch, struct elf_binary *elf,
|
|
+ uint32_t dom, unsigned long *parray)
|
|
{
|
|
privcmd_mmap_entry_t *entries = NULL;
|
|
unsigned long pfn_start = elf->pstart >> PAGE_SHIFT;
|
|
@@ -126,6 +159,66 @@ static int loadelfimage(
|
|
return rc;
|
|
}
|
|
|
|
+static int loadmodules(xc_interface *xch,
|
|
+ struct xc_hvm_build_args *args,
|
|
+ uint64_t mstart, uint64_t mend,
|
|
+ uint32_t dom, unsigned long *parray)
|
|
+{
|
|
+ privcmd_mmap_entry_t *entries = NULL;
|
|
+ unsigned long pfn_start;
|
|
+ unsigned long pfn_end;
|
|
+ size_t pages;
|
|
+ uint32_t i;
|
|
+ uint8_t *dest;
|
|
+ int rc = -1;
|
|
+
|
|
+ if ( (mstart == 0)||(mend == 0) )
|
|
+ return 0;
|
|
+
|
|
+ pfn_start = (unsigned long)(mstart >> PAGE_SHIFT);
|
|
+ pfn_end = (unsigned long)((mend + PAGE_SIZE - 1) >> PAGE_SHIFT);
|
|
+ pages = pfn_end - pfn_start;
|
|
+
|
|
+ /* Map address space for module list. */
|
|
+ entries = calloc(pages, sizeof(privcmd_mmap_entry_t));
|
|
+ if ( entries == NULL )
|
|
+ goto error_out;
|
|
+
|
|
+ for ( i = 0; i < pages; i++ )
|
|
+ entries[i].mfn = parray[(mstart >> PAGE_SHIFT) + i];
|
|
+
|
|
+ dest = xc_map_foreign_ranges(
|
|
+ xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT,
|
|
+ entries, pages);
|
|
+ if ( dest == NULL )
|
|
+ goto error_out;
|
|
+
|
|
+ /* Zero the range so padding is clear between modules */
|
|
+ memset(dest, 0, pages << PAGE_SHIFT);
|
|
+
|
|
+ /* Load modules into range */
|
|
+ if ( args->acpi_module.length != 0 )
|
|
+ {
|
|
+ memcpy(dest,
|
|
+ args->acpi_module.data,
|
|
+ args->acpi_module.length);
|
|
+ }
|
|
+ if ( args->smbios_module.length != 0 )
|
|
+ {
|
|
+ memcpy(dest + (args->smbios_module.guest_addr_out - mstart),
|
|
+ args->smbios_module.data,
|
|
+ args->smbios_module.length);
|
|
+ }
|
|
+
|
|
+ munmap(dest, pages << PAGE_SHIFT);
|
|
+ rc = 0;
|
|
+
|
|
+ error_out:
|
|
+ free(entries);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
/*
|
|
* Check whether there exists mmio hole in the specified memory range.
|
|
* Returns 1 if exists, else returns 0.
|
|
@@ -140,7 +233,7 @@ static int check_mmio_hole(uint64_t star
|
|
}
|
|
|
|
static int setup_guest(xc_interface *xch,
|
|
- uint32_t dom, const struct xc_hvm_build_args *args,
|
|
+ uint32_t dom, struct xc_hvm_build_args *args,
|
|
char *image, unsigned long image_size)
|
|
{
|
|
xen_pfn_t *page_array = NULL;
|
|
@@ -153,6 +246,7 @@ static int setup_guest(xc_interface *xch
|
|
uint32_t *ident_pt;
|
|
struct elf_binary elf;
|
|
uint64_t v_start, v_end;
|
|
+ uint64_t m_start = 0, m_end = 0;
|
|
int rc;
|
|
xen_capabilities_info_t caps;
|
|
unsigned long stat_normal_pages = 0, stat_2mb_pages = 0,
|
|
@@ -178,11 +272,19 @@ static int setup_guest(xc_interface *xch
|
|
goto error_out;
|
|
}
|
|
|
|
+ if ( modules_init(args, v_end, &elf, &m_start, &m_end) != 0 )
|
|
+ {
|
|
+ ERROR("Insufficient space to load modules.");
|
|
+ goto error_out;
|
|
+ }
|
|
+
|
|
IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
|
|
" Loader: %016"PRIx64"->%016"PRIx64"\n"
|
|
+ " Modules: %016"PRIx64"->%016"PRIx64"\n"
|
|
" TOTAL: %016"PRIx64"->%016"PRIx64"\n"
|
|
" ENTRY ADDRESS: %016"PRIx64"\n",
|
|
elf.pstart, elf.pend,
|
|
+ m_start, m_end,
|
|
v_start, v_end,
|
|
elf_uval(&elf, elf.ehdr, e_entry));
|
|
|
|
@@ -337,6 +439,9 @@ static int setup_guest(xc_interface *xch
|
|
if ( loadelfimage(xch, &elf, dom, page_array) != 0 )
|
|
goto error_out;
|
|
|
|
+ if ( loadmodules(xch, args, m_start, m_end, dom, page_array) != 0 )
|
|
+ goto error_out;
|
|
+
|
|
if ( (hvm_info_page = xc_map_foreign_range(
|
|
xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE,
|
|
HVM_INFO_PFN)) == NULL )
|
|
@@ -413,7 +518,7 @@ static int setup_guest(xc_interface *xch
|
|
* Create a domain for a virtualized Linux, using files/filenames.
|
|
*/
|
|
int xc_hvm_build(xc_interface *xch, uint32_t domid,
|
|
- const struct xc_hvm_build_args *hvm_args)
|
|
+ struct xc_hvm_build_args *hvm_args)
|
|
{
|
|
struct xc_hvm_build_args args = *hvm_args;
|
|
void *image;
|
|
@@ -441,6 +546,15 @@ int xc_hvm_build(xc_interface *xch, uint
|
|
|
|
sts = setup_guest(xch, domid, &args, image, image_size);
|
|
|
|
+ if (!sts)
|
|
+ {
|
|
+ /* Return module load addresses to caller */
|
|
+ hvm_args->acpi_module.guest_addr_out =
|
|
+ args.acpi_module.guest_addr_out;
|
|
+ hvm_args->smbios_module.guest_addr_out =
|
|
+ args.smbios_module.guest_addr_out;
|
|
+ }
|
|
+
|
|
free(image);
|
|
|
|
return sts;
|
|
@@ -461,6 +575,7 @@ int xc_hvm_build_target_mem(xc_interface
|
|
{
|
|
struct xc_hvm_build_args args = {};
|
|
|
|
+ memset(&args, 0, sizeof(struct xc_hvm_build_args));
|
|
args.mem_size = (uint64_t)memsize << 20;
|
|
args.mem_target = (uint64_t)target << 20;
|
|
args.image_file_name = image_name;
|
|
diff -r 07bf59a7ce83 -r cabf395a6c84 tools/libxc/xenguest.h
|
|
--- a/tools/libxc/xenguest.h Thu Jan 10 17:16:28 2013 +0000
|
|
+++ b/tools/libxc/xenguest.h Thu Jan 10 17:17:21 2013 +0000
|
|
@@ -211,11 +211,23 @@ int xc_linux_build_mem(xc_interface *xch
|
|
unsigned int console_evtchn,
|
|
unsigned long *console_mfn);
|
|
|
|
+struct xc_hvm_firmware_module {
|
|
+ uint8_t *data;
|
|
+ uint32_t length;
|
|
+ uint64_t guest_addr_out;
|
|
+};
|
|
+
|
|
struct xc_hvm_build_args {
|
|
uint64_t mem_size; /* Memory size in bytes. */
|
|
uint64_t mem_target; /* Memory target in bytes. */
|
|
uint64_t mmio_size; /* Size of the MMIO hole in bytes. */
|
|
const char *image_file_name; /* File name of the image to load. */
|
|
+
|
|
+ /* Extra ACPI tables passed to HVMLOADER */
|
|
+ struct xc_hvm_firmware_module acpi_module;
|
|
+
|
|
+ /* Extra SMBIOS structures passed to HVMLOADER */
|
|
+ struct xc_hvm_firmware_module smbios_module;
|
|
};
|
|
|
|
/**
|
|
@@ -228,7 +240,7 @@ struct xc_hvm_build_args {
|
|
* are optional.
|
|
*/
|
|
int xc_hvm_build(xc_interface *xch, uint32_t domid,
|
|
- const struct xc_hvm_build_args *hvm_args);
|
|
+ struct xc_hvm_build_args *hvm_args);
|
|
|
|
int xc_hvm_build_target_mem(xc_interface *xch,
|
|
uint32_t domid,
|
|
diff -r 07bf59a7ce83 -r cabf395a6c84 tools/libxc/xg_private.c
|
|
--- a/tools/libxc/xg_private.c Thu Jan 10 17:16:28 2013 +0000
|
|
+++ b/tools/libxc/xg_private.c Thu Jan 10 17:17:21 2013 +0000
|
|
@@ -192,7 +192,7 @@ unsigned long csum_page(void *page)
|
|
__attribute__((weak))
|
|
int xc_hvm_build(xc_interface *xch,
|
|
uint32_t domid,
|
|
- const struct xc_hvm_build_args *hvm_args)
|
|
+ struct xc_hvm_build_args *hvm_args)
|
|
{
|
|
errno = ENOSYS;
|
|
return -1;
|