xen/xend-hvm-firmware-passthrough.patch

278 lines
11 KiB
Diff
Raw Normal View History

fate#313584: pass bios information to XEN HVM guest
Index: xen-4.4.0-testing/tools/python/xen/xm/create.py
===================================================================
--- xen-4.4.0-testing.orig/tools/python/xen/xm/create.py
+++ xen-4.4.0-testing/tools/python/xen/xm/create.py
@@ -473,6 +473,14 @@ gopts.var('nfs_root', val="PATH",
fn=set_value, default=None,
use="Set the path of the root NFS directory.")
+gopts.var('smbios_firmware', val='FILE',
+ fn=set_value, default=None,
+ use="Path to a file that contains extra SMBIOS firmware structures.")
+
+gopts.var('acpi_firmware', val='FILE',
+ fn=set_value, default=None,
+ use="Path to a file that contains extra ACPI firmware tables.")
+
gopts.var('device_model', val='FILE',
fn=set_value, default=None,
use="Path to device model program.")
@@ -1048,6 +1056,7 @@ def configure_hvm(config_image, vals):
'boot',
'cpuid', 'cpuid_check',
'device_model', 'display',
+ 'smbios_firmware', 'acpi_firmware',
'fda', 'fdb',
'gfx_passthru', 'guest_os_type',
'hap', 'hpet',
Index: xen-4.4.0-testing/tools/python/xen/xm/xenapi_create.py
===================================================================
--- xen-4.4.0-testing.orig/tools/python/xen/xm/xenapi_create.py
+++ xen-4.4.0-testing/tools/python/xen/xm/xenapi_create.py
@@ -1047,6 +1047,8 @@ class sxp2xml:
'apic',
'boot',
'device_model',
+ 'smbios_firmware',
+ 'acpi_firmware',
'loader',
'fda',
'fdb',
Index: xen-4.4.0-testing/tools/python/xen/xend/image.py
===================================================================
--- xen-4.4.0-testing.orig/tools/python/xen/xend/image.py
+++ xen-4.4.0-testing/tools/python/xen/xend/image.py
@@ -17,7 +17,7 @@
#============================================================================
-import os, os.path, string
+import os, os.path, string, struct, stat
import re
import math
import time
@@ -123,6 +123,8 @@ class ImageHandler:
self.device_model = vmConfig['platform'].get('device_model')
+ self.smbios_firmware =(str(vmConfig['platform'].get('smbios_firmware')))
+ self.acpi_firmware =(str(vmConfig['platform'].get('acpi_firmware')))
self.display = vmConfig['platform'].get('display')
self.xauthority = vmConfig['platform'].get('xauthority')
self.vncconsole = int(vmConfig['platform'].get('vncconsole', 0))
@@ -945,6 +947,38 @@ class HVMImageHandler(ImageHandler):
self.vm.getDomid() ])
return args
+ def _readFirmwareFile(self, filename):
+ # Sanity check
+ if filename is None or filename.strip() == "":
+ size = struct.pack('i', int(0))
+ return size + ""
+
+ log.debug("Reading firmware file %s", filename)
+ # Open
+ try:
+ fd = os.open(filename, os.O_RDONLY)
+ except Exception, e:
+ raise VmError('Unable to open firmware file %s' % filename)
+
+ # Validate file size
+ statinfo = os.fstat(fd)
+ if statinfo.st_size == 0 or statinfo.st_size > sys.maxint:
+ os.close(fd)
+ raise VmError('Firmware file %s is an invalid size' % filename)
+ if not stat.S_ISREG(statinfo.st_mode):
+ os.close(fd)
+ raise VmError('Firmware file %s is an invalid file type' % filename)
+ size = struct.pack('i', statinfo.st_size)
+
+ # Read entire file
+ try:
+ buf = os.read(fd, statinfo.st_size)
+ except Exception, e:
+ os.close(fd)
+ raise VmError('Failed reading firmware file %s' % filename)
+ os.close(fd)
+ return size+buf
+
def buildDomain(self):
store_evtchn = self.vm.getStorePort()
@@ -960,6 +994,8 @@ class HVMImageHandler(ImageHandler):
log.debug("vcpu_avail = %li", self.vm.getVCpuAvail())
log.debug("acpi = %d", self.acpi)
log.debug("apic = %d", self.apic)
+ log.debug("smbios_firmware= %s", self.smbios_firmware)
+ log.debug("acpi_firmware = %s", self.acpi_firmware)
rc = xc.hvm_build(domid = self.vm.getDomid(),
image = self.loader,
@@ -968,7 +1004,9 @@ class HVMImageHandler(ImageHandler):
vcpus = self.vm.getVCpuCount(),
vcpu_avail = self.vm.getVCpuAvail(),
acpi = self.acpi,
- apic = self.apic)
+ apic = self.apic,
+ smbios_firmware= self._readFirmwareFile(self.smbios_firmware),
+ acpi_firmware = self._readFirmwareFile(self.acpi_firmware))
rc['notes'] = { 'SUSPEND_CANCEL': 1 }
rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
Index: xen-4.4.0-testing/tools/python/xen/xend/XendConfig.py
===================================================================
--- xen-4.4.0-testing.orig/tools/python/xen/xend/XendConfig.py
+++ xen-4.4.0-testing/tools/python/xen/xend/XendConfig.py
@@ -147,6 +147,8 @@ XENAPI_PLATFORM_CFG_TYPES = {
'apic': int,
'boot': str,
'device_model': str,
+ 'smbios_firmware': str,
+ 'acpi_firmware': str,
'loader': str,
'display' : str,
'fda': str,
@@ -514,6 +516,10 @@ class XendConfig(dict):
self['platform']['nomigrate'] = 0
if self.is_hvm():
+ if 'smbios_firmware' not in self['platform']:
+ self['platform']['smbios_firmware'] = ""
+ if 'acpi_firmware' not in self['platform']:
+ self['platform']['acpi_firmware'] = ""
if 'timer_mode' not in self['platform']:
self['platform']['timer_mode'] = 1
if 'viridian' not in self['platform']:
Index: xen-4.4.0-testing/tools/python/xen/lowlevel/xc/xc.c
===================================================================
--- xen-4.4.0-testing.orig/tools/python/xen/lowlevel/xc/xc.c
+++ xen-4.4.0-testing/tools/python/xen/lowlevel/xc/xc.c
@@ -915,18 +915,23 @@ static PyObject *pyxc_hvm_build(XcObject
uint32_t dom;
struct hvm_info_table *va_hvm;
uint8_t *va_map, sum;
- int i;
- char *image;
+ int i, datalen;
+ char *image, *smbios_str, *acpi_str;
int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1;
+ PyObject *acpi_firmware = NULL;
+ PyObject *smbios_firmware = NULL;
PyObject *vcpu_avail_handle = NULL;
uint8_t vcpu_avail[(HVM_MAX_VCPUS + 7)/8];
+ struct xc_hvm_build_args hvm_args = {};
static char *kwd_list[] = { "domid",
"memsize", "image", "target", "vcpus",
- "vcpu_avail", "acpi", "apic", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiOii", kwd_list,
+ "vcpu_avail", "acpi", "apic",
+ "smbios_firmware", "acpi_firmware", NULL };
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiOiiOO", kwd_list,
&dom, &memsize, &image, &target, &vcpus,
- &vcpu_avail_handle, &acpi, &apic) )
+ &vcpu_avail_handle, &acpi,
+ &apic, &smbios_firmware, &acpi_firmware) )
return NULL;
memset(vcpu_avail, 0, sizeof(vcpu_avail));
@@ -957,8 +962,38 @@ static PyObject *pyxc_hvm_build(XcObject
if ( target == -1 )
target = memsize;
- if ( xc_hvm_build_target_mem(self->xc_handle, dom, memsize,
- target, image) != 0 )
+ memset(&hvm_args, 0, sizeof(struct xc_hvm_build_args));
+ hvm_args.mem_size = (uint64_t)memsize << 20;
+ hvm_args.mem_target = (uint64_t)target << 20;
+ hvm_args.image_file_name = image;
+
+ if ( PyString_Check(smbios_firmware ) )
+ {
+ smbios_str = PyString_AsString(smbios_firmware);
+ if ( smbios_str )
+ {
+ datalen = *(int *)smbios_str;
+ if ( datalen ) {
+ hvm_args.smbios_module.data = &((uint8_t *)smbios_str)[4];
+ hvm_args.smbios_module.length = (uint32_t)datalen;
+ }
+ }
+ }
+
+ if ( PyString_Check(acpi_firmware ) )
+ {
+ acpi_str = PyString_AsString(acpi_firmware);
+ if (acpi_str)
+ {
+ datalen = *(int *)acpi_str;
+ if ( datalen ) {
+ hvm_args.acpi_module.data = &((uint8_t *)acpi_str)[4];
+ hvm_args.acpi_module.length = (uint32_t)datalen;
+ }
+ }
+ }
+
+ if ( xc_hvm_build(self->xc_handle, dom, &hvm_args) != 0 )
return pyxc_error_to_exception(self->xc_handle);
/* Fix up the HVM info table. */
Index: xen-4.4.0-testing/docs/man/xmdomain.cfg.pod.5
===================================================================
--- xen-4.4.0-testing.orig/docs/man/xmdomain.cfg.pod.5
+++ xen-4.4.0-testing/docs/man/xmdomain.cfg.pod.5
@@ -243,6 +243,25 @@ this the xen kernel must be compiled wit
This defaults to 1, meaning running the domain as a UP.
+=item B<acpi_firmware>
+
+Specify a path to a file that contains extra ACPI firmware tables to pass in to
+a guest. The file can contain several tables in their binary AML form
+concatenated together. Each table self describes its length so no additional
+information is needed. These tables will be added to the ACPI table set in the
+guest. Note that existing tables cannot be overridden by this feature. For
+example this cannot be used to override tables like DSDT, FADT, etc.
+
+=item B<smbios_firmware>
+
+Specify a path to a file that contains extra SMBIOS firmware structures to pass
+in to a guest. The file can contain a set DMTF predefined structures which will
+override the internal defaults. Not all predefined structures can be overridden,
+only the following types: 0, 1, 2, 3, 11, 22, 39. The file can also contain any
+number of vendor defined SMBIOS structures (type 128 - 255). Since SMBIOS
+structures do not present their overall size, each entry in the file must be
+preceded by a 32b integer indicating the size of the next structure.
+
=back
=head1 DOMAIN SHUTDOWN OPTIONS
Index: xen-4.4.0-testing/tools/python/README.sxpcfg
===================================================================
--- xen-4.4.0-testing.orig/tools/python/README.sxpcfg
+++ xen-4.4.0-testing/tools/python/README.sxpcfg
@@ -51,6 +51,8 @@ image
- vncunused
(HVM)
- device_model
+ - smbios_firmware
+ - acpi_firmware
- display
- xauthority
- vncconsole
Index: xen-4.4.0-testing/tools/python/README.XendConfig
===================================================================
--- xen-4.4.0-testing.orig/tools/python/README.XendConfig
+++ xen-4.4.0-testing/tools/python/README.XendConfig
@@ -118,6 +118,8 @@ otherConfig
image.vncdisplay
image.vncunused
image.hvm.device_model
+ image.hvm.smbios_firmware
+ image.hvm.apci_firmware
image.hvm.display
image.hvm.xauthority
image.hvm.vncconsole