[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC V8 3/5] xen, libxc: Force-enable relevant MSR events
> From: Razvan Cojocaru [mailto:rcojocaru@xxxxxxxxxxxxxxx] > Sent: Wednesday, August 27, 2014 7:02 AM > > Vmx_disable_intercept_for_msr() will now refuse to disable interception of > MSRs needed for memory introspection. It is not possible to gate this on > mem_access being active for the domain, since by the time mem_access does > become active the interception for the interesting MSRs has already been > disabled (vmx_disable_intercept_for_msr() runs very early on). > > Changes since V1: > - Replaced printk() with gdprintk(XENLOG_DEBUG, ...). > > Changes since V2: > - Split a log line differently to keep it grepable. > - Interception for relevant MSRs will be disabled only if > mem_access is not enabled. > - Since they end up being disabled early on (when mem_access > is not enabled yet), re-enable interception when mem_access > becomes active. > > Changes since V3: > - Removed log line stating that MSR interception cannot be disabled. > - Removed superfluous #include <asm/hvm/vmx/vmcs.h>. > - Moved VMX-specific code to vmx.c (as a new hvm_funcs member). > > Changes since V5: > - Added xc_mem_access_enable_introspection() to libxc, which has > the same parameters and semantics as xc_mem_access_enable(), > but it additionally sets d->arch.hvm_domain.introspection_enabled > and enables relevant MSR interception. > - Renamed vmx_enable_intro_msr_interception() to > vmx_enable_msr_exit_interception(). > - Simplified vmx_enable_msr_exit_interception() (const array of MSRs). > > Changes since V6: > - Moved the array of interesting MSRs to common header. > - Minor code cleanup. > > Changes since V7: > - Reversed if conditions (cheapest one first). > - Combined two if statements. > - Moved "bool_t introspection_enabled;" to the bool_t group above. > - Renamed msrs_exit_array to vmx_msrs_exit_array and made it > "extern" in the header. > > Signed-off-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx> > --- > tools/libxc/xc_mem_access.c | 10 +++++++++- > tools/libxc/xc_mem_event.c | 7 +++++-- > tools/libxc/xc_private.h | 2 +- > tools/libxc/xenctrl.h | 2 ++ > xen/arch/x86/hvm/vmx/vmcs.c | 25 > +++++++++++++++++++++++++ > xen/arch/x86/hvm/vmx/vmx.c | 12 ++++++++++++ > xen/arch/x86/mm/mem_event.c | 11 +++++++++++ > xen/include/asm-x86/hvm/domain.h | 1 + > xen/include/asm-x86/hvm/hvm.h | 2 ++ > xen/include/asm-x86/hvm/vmx/vmcs.h | 3 +++ > xen/include/public/domctl.h | 7 ++++--- > 11 files changed, 75 insertions(+), 7 deletions(-) > > diff --git a/tools/libxc/xc_mem_access.c b/tools/libxc/xc_mem_access.c > index 461f0e9..55d0e9f 100644 > --- a/tools/libxc/xc_mem_access.c > +++ b/tools/libxc/xc_mem_access.c > @@ -26,7 +26,15 @@ > > void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, > uint32_t *port) > { > - return xc_mem_event_enable(xch, domain_id, > HVM_PARAM_ACCESS_RING_PFN, port); > + return xc_mem_event_enable(xch, domain_id, > HVM_PARAM_ACCESS_RING_PFN, > + port, 0); > +} > + > +void *xc_mem_access_enable_introspection(xc_interface *xch, domid_t > domain_id, > + uint32_t *port) > +{ > + return xc_mem_event_enable(xch, domain_id, > HVM_PARAM_ACCESS_RING_PFN, > + port, 1); > } > > int xc_mem_access_disable(xc_interface *xch, domid_t domain_id) > diff --git a/tools/libxc/xc_mem_event.c b/tools/libxc/xc_mem_event.c > index faf1cc6..8c0be4e 100644 > --- a/tools/libxc/xc_mem_event.c > +++ b/tools/libxc/xc_mem_event.c > @@ -57,7 +57,7 @@ int xc_mem_event_memop(xc_interface *xch, domid_t > domain_id, > } > > void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int > param, > - uint32_t *port) > + uint32_t *port, int enable_introspection) > { > void *ring_page = NULL; > uint64_t pfn; > @@ -120,7 +120,10 @@ void *xc_mem_event_enable(xc_interface *xch, > domid_t domain_id, int param, > break; > > case HVM_PARAM_ACCESS_RING_PFN: > - op = XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE; > + if ( enable_introspection ) > + op = > XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION; > + else > + op = XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE; > mode = XEN_DOMCTL_MEM_EVENT_OP_ACCESS; > break; > > diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h > index c50a7c9..94df688 100644 > --- a/tools/libxc/xc_private.h > +++ b/tools/libxc/xc_private.h > @@ -381,6 +381,6 @@ int xc_mem_event_memop(xc_interface *xch, > domid_t domain_id, > * param can be HVM_PARAM_PAGING/ACCESS/SHARING_RING_PFN > */ > void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int > param, > - uint32_t *port); > + uint32_t *port, int enable_introspection); > > #endif /* __XC_PRIVATE_H__ */ > diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h > index 1c5d0db..28b5562 100644 > --- a/tools/libxc/xenctrl.h > +++ b/tools/libxc/xenctrl.h > @@ -2263,6 +2263,8 @@ int xc_mem_paging_load(xc_interface *xch, > domid_t domain_id, > * Caller has to unmap this page when done. > */ > void *xc_mem_access_enable(xc_interface *xch, domid_t domain_id, > uint32_t *port); > +void *xc_mem_access_enable_introspection(xc_interface *xch, domid_t > domain_id, > + uint32_t *port); > int xc_mem_access_disable(xc_interface *xch, domid_t domain_id); > int xc_mem_access_resume(xc_interface *xch, domid_t domain_id); > > diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c > index 4a4f4e1..44aca73 100644 > --- a/xen/arch/x86/hvm/vmx/vmcs.c > +++ b/xen/arch/x86/hvm/vmx/vmcs.c > @@ -39,6 +39,7 @@ > #include <xen/keyhandler.h> > #include <asm/shadow.h> > #include <asm/tboot.h> > +#include <asm/mem_event.h> > > static bool_t __read_mostly opt_vpid_enabled = 1; > boolean_param("vpid", opt_vpid_enabled); > @@ -71,6 +72,18 @@ u32 vmx_vmexit_control __read_mostly; > u32 vmx_vmentry_control __read_mostly; > u64 vmx_ept_vpid_cap __read_mostly; > > +const u32 vmx_msrs_exit_array[] = { > + MSR_IA32_SYSENTER_EIP, > + MSR_IA32_SYSENTER_ESP, > + MSR_IA32_SYSENTER_CS, > + MSR_IA32_MC0_CTL, > + MSR_STAR, > + MSR_LSTAR > +}; > + > +const unsigned int vmx_msrs_exit_array_size = > + ARRAY_SIZE(vmx_msrs_exit_array); > + prefer a name including 'force' purpose or at least have a comment to describe the intention, so its meaning is explained as early as possible. > static DEFINE_PER_CPU_READ_MOSTLY(struct vmcs_struct *, > vmxon_region); > static DEFINE_PER_CPU(struct vmcs_struct *, current_vmcs); > static DEFINE_PER_CPU(struct list_head, active_vmcs_list); > @@ -695,11 +708,23 @@ static void vmx_set_host_env(struct vcpu *v) > void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type) > { > unsigned long *msr_bitmap = v->arch.hvm_vmx.msr_bitmap; > + struct domain *d = v->domain; > > /* VMX MSR bitmap supported? */ > if ( msr_bitmap == NULL ) > return; > > + if ( unlikely(d->arch.hvm_domain.introspection_enabled) && > + mem_event_check_ring(&d->mem_event->access) ) > + { > + unsigned int i; > + > + /* Filter out MSR-s needed for memory introspection */ > + for ( i = 0; i < vmx_msrs_exit_array_size; i++ ) > + if ( msr == vmx_msrs_exit_array[i] ) > + return; > + } > + the comment is very introspection specific, while the array name is generic. better to change array name since it isn't generic under the current condition. > /* > * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals > * have the write-low and read-high bitmap offsets the wrong way > round. > diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c > index dc18a72..40e6c2c 100644 > --- a/xen/arch/x86/hvm/vmx/vmx.c > +++ b/xen/arch/x86/hvm/vmx/vmx.c > @@ -1682,6 +1682,17 @@ void vmx_hypervisor_cpuid_leaf(uint32_t sub_idx, > *eax |= XEN_HVM_CPUID_X2APIC_VIRT; > } > > +static void vmx_enable_msr_exit_interception(struct domain *d) > +{ > + struct vcpu *v; > + unsigned int i; > + > + /* Enable interception for MSRs needed for memory introspection. */ > + for_each_vcpu ( d, v ) > + for ( i = 0; i < vmx_msrs_exit_array_size; i++ ) > + vmx_enable_intercept_for_msr(v, vmx_msrs_exit_array[i], > MSR_TYPE_W); > +} > + so you need same conditional check as you added for vmx_disable_intercept_for_msr > static struct hvm_function_table __initdata vmx_function_table = { > .name = "VMX", > .cpu_up_prepare = vmx_cpu_up_prepare, > @@ -1740,6 +1751,7 @@ static struct hvm_function_table __initdata > vmx_function_table = { > .handle_eoi = vmx_handle_eoi, > .nhvm_hap_walk_L1_p2m = nvmx_hap_walk_L1_p2m, > .hypervisor_cpuid_leaf = vmx_hypervisor_cpuid_leaf, > + .enable_msr_exit_interception = vmx_enable_msr_exit_interception, > }; > > const struct hvm_function_table * __init start_vmx(void) > diff --git a/xen/arch/x86/mm/mem_event.c > b/xen/arch/x86/mm/mem_event.c > index ba7e71e..fdd5ff6 100644 > --- a/xen/arch/x86/mm/mem_event.c > +++ b/xen/arch/x86/mm/mem_event.c > @@ -587,6 +587,7 @@ int mem_event_domctl(struct domain *d, > xen_domctl_mem_event_op_t *mec, > switch( mec->op ) > { > case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE: > + case > XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION: > { > rc = -ENODEV; > /* Only HAP is supported */ > @@ -600,13 +601,23 @@ int mem_event_domctl(struct domain *d, > xen_domctl_mem_event_op_t *mec, > rc = mem_event_enable(d, mec, med, _VPF_mem_access, > > HVM_PARAM_ACCESS_RING_PFN, > mem_access_notification); > + > + if ( mec->op != > XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE && > + rc == 0 && hvm_funcs.enable_msr_exit_interception ) > + { > + d->arch.hvm_domain.introspection_enabled = 1; > + hvm_funcs.enable_msr_exit_interception(d); > + } > } > break; > > case XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE: > { > if ( med->ring_page ) > + { > rc = mem_event_disable(d, med); > + d->arch.hvm_domain.introspection_enabled = 0; > + } > } > break; > > diff --git a/xen/include/asm-x86/hvm/domain.h > b/xen/include/asm-x86/hvm/domain.h > index 291a2e0..30d4aa3 100644 > --- a/xen/include/asm-x86/hvm/domain.h > +++ b/xen/include/asm-x86/hvm/domain.h > @@ -134,6 +134,7 @@ struct hvm_domain { > bool_t mem_sharing_enabled; > bool_t qemu_mapcache_invalidate; > bool_t is_s3_suspended; > + bool_t introspection_enabled; > > /* > * 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 0ebd478..069ba39 100644 > --- a/xen/include/asm-x86/hvm/hvm.h > +++ b/xen/include/asm-x86/hvm/hvm.h > @@ -205,6 +205,8 @@ struct hvm_function_table { > void (*hypervisor_cpuid_leaf)(uint32_t sub_idx, > uint32_t *eax, uint32_t *ebx, > uint32_t *ecx, uint32_t *edx); > + > + void (*enable_msr_exit_interception)(struct domain *d); > }; > > extern struct hvm_function_table hvm_funcs; > diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h > b/xen/include/asm-x86/hvm/vmx/vmcs.h > index 215d93c..f2e4d82 100644 > --- a/xen/include/asm-x86/hvm/vmx/vmcs.h > +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h > @@ -471,6 +471,9 @@ enum vmcs_field { > HOST_RIP = 0x00006c16, > }; > > +extern const u32 vmx_msrs_exit_array[]; > +extern const unsigned int vmx_msrs_exit_array_size; > + > #define VMCS_VPID_WIDTH 16 > > #define MSR_TYPE_R 1 > diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h > index 5b11bbf..a3431ec 100644 > --- a/xen/include/public/domctl.h > +++ b/xen/include/public/domctl.h > @@ -772,10 +772,11 @@ struct xen_domctl_gdbsx_domstatus { > * ENODEV - host lacks HAP support (EPT/NPT) or HAP is disabled in guest > * EBUSY - guest has or had access enabled, ring buffer still active > */ > -#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS 2 > +#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS > 2 > > -#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE 0 > -#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE 1 > +#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE > 0 > +#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_DISABLE > 1 > +#define XEN_DOMCTL_MEM_EVENT_OP_ACCESS_ENABLE_INTROSPECTION > 2 > > /* > * Sharing ENOMEM helper. > -- > 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |