|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC v1 11/13] xen/libxl: allow creating HVM guests without a device model
Intorduce a new device model version (NONE) that can be used to specify that
no device model should be used. Propagate this to Xen by creating a new
XEN_DOMCTL_CDF_noemu flag that disables some of the emulation done inside of
Xen.
Signed-off-by: Roger Pau Monnà <roger.pau@xxxxxxxxxx>
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Cc: Ian Campbell <ian.campbell@xxxxxxxxxx>
Cc: Wei Liu <wei.liu2@xxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Cc: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Cc: Elena Ufimtseva <elena.ufimtseva@xxxxxxxxxx>
---
IMHO the XEN_DOMCTL_CDF_noemu flag should be expanded into multiple smaller
flags that can be used to disable specific emulated devices, like the
vlapic, vioapic, vhpet...
Also hvm_mmio_handlers should become domain specific in order to populate it
with the usable handlers only.
---
tools/libxl/libxl.c | 7 +++----
tools/libxl/libxl_create.c | 16 ++++++++++++++++
tools/libxl/libxl_dom.c | 6 ++++++
tools/libxl/libxl_types.idl | 1 +
tools/libxl/xl_cmdimpl.c | 2 ++
xen/arch/x86/domain.c | 2 +-
xen/arch/x86/hvm/hvm.c | 14 +++++++++-----
xen/arch/x86/hvm/intercept.c | 6 ++++++
xen/common/domctl.c | 5 ++++-
xen/include/asm-x86/hvm/domain.h | 1 +
xen/include/asm-x86/hvm/hvm.h | 2 +-
xen/include/public/domctl.h | 3 +++
xen/include/xen/sched.h | 4 ++++
13 files changed, 57 insertions(+), 12 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index d86ea62..7c83486 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1587,11 +1587,10 @@ void libxl__destroy_domid(libxl__egc *egc,
libxl__destroy_domid_state *dis)
switch (libxl__domain_type(gc, domid)) {
case LIBXL_DOMAIN_TYPE_HVM:
- if (!libxl_get_stubdom_id(CTX, domid))
- dm_present = 1;
- else
+ if (libxl_get_stubdom_id(CTX, domid)) {
dm_present = 0;
- break;
+ break;
+ }
case LIBXL_DOMAIN_TYPE_PV:
pid = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc,
"/local/domain/%d/image/device-model-pid", domid));
dm_present = (pid != NULL);
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 86384d2..06cf02c 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -164,6 +164,8 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
b_info->u.hvm.bios = LIBXL_BIOS_TYPE_ROMBIOS; break;
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
b_info->u.hvm.bios = LIBXL_BIOS_TYPE_SEABIOS; break;
+ case LIBXL_DEVICE_MODEL_VERSION_NONE:
+ break;
default:return ERROR_INVAL;
}
@@ -177,6 +179,8 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
if (b_info->u.hvm.bios == LIBXL_BIOS_TYPE_ROMBIOS)
return ERROR_INVAL;
break;
+ case LIBXL_DEVICE_MODEL_VERSION_NONE:
+ break;
default:abort();
}
@@ -278,6 +282,9 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
break;
}
break;
+ case LIBXL_DEVICE_MODEL_VERSION_NONE:
+ b_info->video_memkb = 0;
+ break;
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
default:
switch (b_info->u.hvm.vga.kind) {
@@ -535,6 +542,7 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config
*d_config,
/* convenience aliases */
libxl_domain_create_info *info = &d_config->c_info;
+ libxl_domain_build_info *b_info = &d_config->b_info;
assert(!libxl_domid_valid_guest(*domid));
@@ -549,6 +557,8 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config
*d_config,
flags |= XEN_DOMCTL_CDF_hvm_guest;
flags |= libxl_defbool_val(info->hap) ? XEN_DOMCTL_CDF_hap : 0;
flags |= libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off;
+ if (b_info->device_model_version == LIBXL_DEVICE_MODEL_VERSION_NONE)
+ flags |= XEN_DOMCTL_CDF_noemu;
} else if (libxl_defbool_val(info->pvh)) {
flags |= XEN_DOMCTL_CDF_pvh_guest;
if (!libxl_defbool_val(info->hap)) {
@@ -1293,6 +1303,12 @@ static void domcreate_launch_dm(libxl__egc *egc,
libxl__multidev *multidev,
libxl__device_console_add(gc, domid, &console, state, &device);
libxl__device_console_dispose(&console);
+ if (d_config->b_info.device_model_version ==
+ LIBXL_DEVICE_MODEL_VERSION_NONE) {
+ domcreate_devmodel_started(egc, &dcs->dmss.dm, 0);
+ return;
+ }
+
libxl_device_vkb_init(&vkb);
libxl__device_vkb_add(gc, domid, &vkb);
libxl_device_vkb_dispose(&vkb);
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 8ee14b9..d948546 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -866,6 +866,12 @@ static int libxl__domain_firmware(libxl__gc *gc,
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
firmware = "hvmloader";
break;
+ case LIBXL_DEVICE_MODEL_VERSION_NONE:
+ if (info->kernel == NULL) {
+ LOG(ERROR, "no device model requested without a kernel");
+ return ERROR_FAIL;
+ }
+ break;
default:
LOG(ERROR, "invalid device model version %d",
info->device_model_version);
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 23f27d4..0b75834 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -83,6 +83,7 @@ libxl_device_model_version =
Enumeration("device_model_version", [
(0, "UNKNOWN"),
(1, "QEMU_XEN_TRADITIONAL"), # Historical qemu-xen device model (qemu-dm)
(2, "QEMU_XEN"), # Upstream based qemu-xen device model
+ (3, "NONE"), # No device model
])
libxl_console_type = Enumeration("console_type", [
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index c858068..3d9b3d4 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -2067,6 +2067,8 @@ skip_vfb:
} else if (!strcmp(buf, "qemu-xen")) {
b_info->device_model_version
= LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
+ } else if (!strcmp(buf, "none")) {
+ b_info->device_model_version = LIBXL_DEVICE_MODEL_VERSION_NONE;
} else {
fprintf(stderr,
"Unknown device_model_version \"%s\" specified\n", buf);
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 0363650..bad0872 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -610,7 +610,7 @@ int arch_domain_create(struct domain *d, unsigned int
domcr_flags,
if ( has_hvm_container_domain(d) )
{
- if ( (rc = hvm_domain_initialise(d)) != 0 )
+ if ( (rc = hvm_domain_initialise(d, domcr_flags)) != 0 )
{
iommu_domain_destroy(d);
goto fail;
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index d5e5242..7694c9e 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -343,7 +343,7 @@ u64 hvm_get_guest_tsc_adjust(struct vcpu *v)
void hvm_migrate_timers(struct vcpu *v)
{
/* PVH doesn't use rtc and emulated timers, it uses pvclock mechanism. */
- if ( is_pvh_vcpu(v) )
+ if ( is_pvh_vcpu(v) || v->domain->arch.hvm_domain.no_emu )
return;
rtc_migrate_timers(v);
@@ -1423,7 +1423,7 @@ static int hvm_set_dm_domain(struct domain *d, domid_t
domid)
return rc;
}
-int hvm_domain_initialise(struct domain *d)
+int hvm_domain_initialise(struct domain *d, unsigned int domcr_flags)
{
int rc;
@@ -1485,9 +1485,10 @@ int hvm_domain_initialise(struct domain *d)
else
d->arch.hvm_domain.io_bitmap = hvm_io_bitmap;
- if ( is_pvh_domain(d) )
+ if ( is_pvh_domain(d) || domcr_flags & DOMCRF_noemu )
{
register_portio_handler(d, 0, 0x10003, handle_pvh_io);
+ d->arch.hvm_domain.no_emu = TRUE;
return 0;
}
@@ -1531,7 +1532,7 @@ int hvm_domain_initialise(struct domain *d)
void hvm_domain_relinquish_resources(struct domain *d)
{
- if ( is_pvh_domain(d) )
+ if ( is_pvh_domain(d) || d->arch.hvm_domain.no_emu )
return;
if ( hvm_funcs.nhvm_domain_relinquish_resources )
@@ -1557,7 +1558,7 @@ void hvm_domain_destroy(struct domain *d)
hvm_destroy_cacheattr_region_list(d);
- if ( is_pvh_domain(d) )
+ if ( is_pvh_domain(d) || d->arch.hvm_domain.no_emu )
return;
hvm_funcs.domain_destroy(d);
@@ -2327,6 +2328,9 @@ int hvm_vcpu_initialise(struct vcpu *v)
return 0;
}
+ if ( d->arch.hvm_domain.no_emu )
+ return 0;
+
rc = setup_compat_arg_xlat(v); /* teardown: free_compat_arg_xlat() */
if ( rc != 0 )
goto fail4;
diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c
index d52a48c..b7bc3c7 100644
--- a/xen/arch/x86/hvm/intercept.c
+++ b/xen/arch/x86/hvm/intercept.c
@@ -168,6 +168,9 @@ bool_t hvm_mmio_internal(paddr_t gpa)
struct vcpu *curr = current;
unsigned int i;
+ if ( curr->domain->arch.hvm_domain.no_emu )
+ return 0;
+
for ( i = 0; i < HVM_MMIO_HANDLER_NR; ++i )
if ( hvm_mmio_handlers[i]->check_handler(curr, gpa) )
return 1;
@@ -180,6 +183,9 @@ int hvm_mmio_intercept(ioreq_t *p)
struct vcpu *v = current;
int i;
+ if ( v->domain->arch.hvm_domain.no_emu )
+ return X86EMUL_UNHANDLEABLE;
+
for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ )
{
hvm_mmio_check_t check_handler =
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index ce517a7..1ce7ae0 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -550,7 +550,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t)
u_domctl)
| XEN_DOMCTL_CDF_pvh_guest
| XEN_DOMCTL_CDF_hap
| XEN_DOMCTL_CDF_s3_integrity
- | XEN_DOMCTL_CDF_oos_off)) )
+ | XEN_DOMCTL_CDF_oos_off
+ | XEN_DOMCTL_CDF_noemu)) )
break;
dom = op->domain;
@@ -592,6 +593,8 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t)
u_domctl)
domcr_flags |= DOMCRF_s3_integrity;
if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_oos_off )
domcr_flags |= DOMCRF_oos_off;
+ if ( op->u.createdomain.flags & XEN_DOMCTL_CDF_noemu )
+ domcr_flags |= DOMCRF_noemu;
d = domain_create(dom, domcr_flags, op->u.createdomain.ssidref,
&op->u.createdomain.config);
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index ad68fcf..948ced8 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -135,6 +135,7 @@ struct hvm_domain {
bool_t mem_sharing_enabled;
bool_t qemu_mapcache_invalidate;
bool_t is_s3_suspended;
+ bool_t no_emu;
/*
* TSC value that VCPUs use to calculate their tsc_offset value.
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 77eeac5..68c987a 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -217,7 +217,7 @@ extern s8 hvm_port80_allowed;
extern const struct hvm_function_table *start_svm(void);
extern const struct hvm_function_table *start_vmx(void);
-int hvm_domain_initialise(struct domain *d);
+int hvm_domain_initialise(struct domain *d, unsigned int domcr_flags);
void hvm_domain_relinquish_resources(struct domain *d);
void hvm_domain_destroy(struct domain *d);
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index bc45ea5..4e9d7e7 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -63,6 +63,9 @@ struct xen_domctl_createdomain {
/* Is this a PVH guest (as opposed to an HVM or PV guest)? */
#define _XEN_DOMCTL_CDF_pvh_guest 4
#define XEN_DOMCTL_CDF_pvh_guest (1U<<_XEN_DOMCTL_CDF_pvh_guest)
+ /* Disable emulated devices */
+#define _XEN_DOMCTL_CDF_noemu 5
+#define XEN_DOMCTL_CDF_noemu (1U<<_XEN_DOMCTL_CDF_noemu)
uint32_t flags;
struct xen_arch_domainconfig config;
};
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 604d047..0aaff1e 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -552,6 +552,10 @@ struct domain *domain_create(domid_t domid, unsigned int
domcr_flags,
/* DOMCRF_pvh: Create PV domain in HVM container. */
#define _DOMCRF_pvh 5
#define DOMCRF_pvh (1U<<_DOMCRF_pvh)
+/* DOMCRF_noemu: Create a HVM domain without emulated devices. */
+/* XXX: Should be split into smaller flags that disable specific devices? */
+#define _DOMCRF_noemu 6
+#define DOMCRF_noemu (1U<<_DOMCRF_noemu)
/*
* rcu_lock_domain_by_id() is more efficient than get_domain_by_id().
--
1.9.5 (Apple Git-50.3)
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |