libxl: HVM firmware passthrough support

This patch introduces support for two new parameters in libxl:

smbios_firmware=<path_to_smbios_structures_file>
acpi_firmware=<path_to_acpi_tables_file>

The changes are primarily in the domain building code where the firmware files
are read and passed to libxc for loading into the new guest. After the domain
building call to libxc, the addresses for the loaded blobs are returned and
written to xenstore.

LIBXL_HAVE_FIRMWARE_PASSTHROUGH is defined in libxl.h to allow users to
determine if the feature is present.

This patch also updates the xl.cfg man page with descriptions of the two new
parameters for firmware passthrough.

Signed-off-by: Ross Philipson <ross.philipson@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Committed-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
Ross Philipson committed 2013-02-15 13:32:16 +00:00
1 parent a234675150
commit dcd468855a
5 files changed
+148 -17

No files matched your search

+19
View File
@@ -829,6 +829,25 @@ libxl: 'host,tm=0,sse3=0'
More info about the CPUID instruction can be found in the processor manuals, and
in Wikipedia: L<http://en.wikipedia.org/wiki/CPUID>
=item B<acpi_firmware="STRING">
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="STRING">
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
=head3 Guest Virtual Time Controls
+7
View File
@@ -67,6 +67,13 @@
* the same $(XEN_VERSION) (e.g. throughout a major release).
*/
/*
* LIBXL_HAVE_FIRMWARE_PASSTHROUGH indicates the feature for
* passing in SMBIOS and ACPI firmware to HVM guests is present
* in the library.
*/
#define LIBXL_HAVE_FIRMWARE_PASSTHROUGH 1
/*
* libxl ABI compatibility
*
+115 -17
View File
@@ -21,6 +21,7 @@
#include <xc_dom.h>
#include <xen/hvm/hvm_info_table.h>
#include <xen/hvm/hvm_xs_strings.h>
libxl_domain_type libxl__domain_type(libxl__gc *gc, uint32_t domid)
{
@@ -510,11 +511,61 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
return 0;
}
static const char *libxl__domain_firmware(libxl__gc *gc,
libxl_domain_build_info *info)
static int hvm_build_set_xs_values(libxl__gc *gc,
uint32_t domid,
struct xc_hvm_build_args *args)
{
char *path = NULL;
int ret = 0;
if (args->smbios_module.guest_addr_out) {
path = GCSPRINTF("/local/domain/%d/"HVM_XS_SMBIOS_PT_ADDRESS, domid);
ret = libxl__xs_write(gc, XBT_NULL, path, "0x%"PRIx64,
args->smbios_module.guest_addr_out);
if (ret)
goto err;
path = GCSPRINTF("/local/domain/%d/"HVM_XS_SMBIOS_PT_LENGTH, domid);
ret = libxl__xs_write(gc, XBT_NULL, path, "0x%x",
args->smbios_module.length);
if (ret)
goto err;
}
if (args->acpi_module.guest_addr_out) {
path = GCSPRINTF("/local/domain/%d/"HVM_XS_ACPI_PT_ADDRESS, domid);
ret = libxl__xs_write(gc, XBT_NULL, path, "0x%"PRIx64,
args->acpi_module.guest_addr_out);
if (ret)
goto err;
path = GCSPRINTF("/local/domain/%d/"HVM_XS_ACPI_PT_LENGTH, domid);
ret = libxl__xs_write(gc, XBT_NULL, path, "0x%x",
args->acpi_module.length);
if (ret)
goto err;
}
return 0;
err:
LOG(ERROR, "failed to write firmware xenstore value, err: %d", ret);
return ret;
}
static int libxl__domain_firmware(libxl__gc *gc,
libxl_domain_build_info *info,
struct xc_hvm_build_args *args)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
const char *firmware;
int e, rc = ERROR_FAIL;
int datalen = 0;
void *data;
if (info->u.hvm.firmware)
firmware = info->u.hvm.firmware;
@@ -528,13 +579,52 @@ static const char *libxl__domain_firmware(libxl__gc *gc,
firmware = "hvmloader";
break;
default:
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "invalid device model version %d",
info->device_model_version);
return NULL;
LOG(ERROR, "invalid device model version %d",
info->device_model_version);
return ERROR_FAIL;
break;
}
}
return libxl__abs_path(gc, firmware, libxl__xenfirmwaredir_path());
args->image_file_name = libxl__abs_path(gc, firmware,
libxl__xenfirmwaredir_path());
if (info->u.hvm.smbios_firmware) {
data = NULL;
e = libxl_read_file_contents(ctx, info->u.hvm.smbios_firmware,
&data, &datalen);
if (e) {
LOGEV(ERROR, e, "failed to read SMBIOS firmware file %s",
info->u.hvm.smbios_firmware);
goto out;
}
libxl__ptr_add(gc, data);
if (datalen) {
/* Only accept non-empty files */
args->smbios_module.data = data;
args->smbios_module.length = (uint32_t)datalen;
}
}
if (info->u.hvm.acpi_firmware) {
data = NULL;
e = libxl_read_file_contents(ctx, info->u.hvm.acpi_firmware,
&data, &datalen);
if (e) {
LOGEV(ERROR, e, "failed to read ACPI firmware file %s",
info->u.hvm.acpi_firmware);
goto out;
}
libxl__ptr_add(gc, data);
if (datalen) {
/* Only accept non-empty files */
args->acpi_module.data = data;
args->acpi_module.length = (uint32_t)datalen;
}
}
return 0;
out:
return rc;
}
int libxl__build_hvm(libxl__gc *gc, uint32_t domid,
@@ -544,10 +634,6 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid,
libxl_ctx *ctx = libxl__gc_owner(gc);
struct xc_hvm_build_args args = {};
int ret, rc = ERROR_FAIL;
const char *firmware = libxl__domain_firmware(gc, info);
if (!firmware)
goto out;
memset(&args, 0, sizeof(struct xc_hvm_build_args));
/* The params from the configuration file are in Mb, which are then
@@ -557,22 +643,34 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid,
*/
args.mem_size = (uint64_t)(info->max_memkb - info->video_memkb) << 10;
args.mem_target = (uint64_t)(info->target_memkb - info->video_memkb) << 10;
args.image_file_name = firmware;
if (libxl__domain_firmware(gc, info, &args)) {
LOG(ERROR, "initializing domain firmware failed");
goto out;
}
ret = xc_hvm_build(ctx->xch, domid, &args);
if (ret) {
LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "hvm building failed");
LOGEV(ERROR, ret, "hvm building failed");
goto out;
}
ret = hvm_build_set_params(ctx->xch, domid, info, state->store_port,
&state->store_mfn, state->console_port,
&state->console_mfn, state->store_domid,
state->console_domid);
if (ret) {
LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "hvm build set params failed");
LOGEV(ERROR, ret, "hvm build set params failed");
goto out;
}
rc = 0;
ret = hvm_build_set_xs_values(gc, domid, &args);
if (ret) {
LOG(ERROR, "hvm build set xenstore values failed (ret=%d)", ret);
goto out;
}
return 0;
out:
return rc;
}
@@ -634,7 +732,7 @@ int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
memcpy(&count, ptr, sizeof(count));
ptr += sizeof(count);
if (size < sizeof(version) + sizeof(count) +
count * (sizeof(struct libxl__physmap_info))) {
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "wrong size");
@@ -848,7 +946,7 @@ static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch *watch,
rc = libxl__xs_rm_checked(gc, t, lds->ret_path);
if (rc) goto out;
rc = libxl__xs_transaction_commit(gc, &t);
rc = libxl__xs_transaction_commit(gc, &t);
if (!rc) break;
if (rc<0) goto out;
}
@@ -1320,7 +1418,7 @@ void libxl__xc_domain_save_done(libxl__egc *egc, void *dss_void,
if (type == LIBXL_DOMAIN_TYPE_HVM) {
rc = libxl__domain_suspend_device_model(gc, dss);
if (rc) goto out;
libxl__domain_save_device_model(egc, dss, domain_suspend_done);
return;
}
+2
View File
@@ -308,6 +308,8 @@ libxl_domain_build_info = Struct("domain_build_info",[
("vpt_align", libxl_defbool),
("timer_mode", libxl_timer_mode),
("nested_hvm", libxl_defbool),
("smbios_firmware", string),
("acpi_firmware", string),
("nographic", libxl_defbool),
("vga", libxl_vga_interface_info),
("vnc", libxl_vnc_info),
+5
View File
@@ -882,6 +882,11 @@ static void parse_config_data(const char *config_source,
}
xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
xlu_cfg_replace_string(config, "smbios_firmware",
&b_info->u.hvm.smbios_firmware, 0);
xlu_cfg_replace_string(config, "acpi_firmware",
&b_info->u.hvm.acpi_firmware, 0);
break;
case LIBXL_DOMAIN_TYPE_PV:
{
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.