diff options
-rw-r--r-- | docs/man/xl.cfg.pod.5 | 19 | ||||
-rw-r--r-- | tools/libxl/libxl.h | 7 | ||||
-rw-r--r-- | tools/libxl/libxl_dom.c | 132 | ||||
-rw-r--r-- | tools/libxl/libxl_types.idl | 2 | ||||
-rw-r--r-- | tools/libxl/xl_cmdimpl.c | 5 |
5 files changed, 148 insertions, 17 deletions
diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 index caba1628f5..48e05c4a7c 100644 --- a/docs/man/xl.cfg.pod.5 +++ b/docs/man/xl.cfg.pod.5 @@ -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 diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 72e5efb6d1..030aa86d52 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -68,6 +68,13 @@ */ /* + * 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 * * The only guarantee which libxl makes regarding ABI compatibility diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 33ae5583d8..8fe4fc4d06 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -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; } diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index acc4bc9d9c..89a80300fe 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -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), diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index bdd1865bf6..9c554ba040 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -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: { |