[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH V5] vm_event: Allow subscribing to write events for specific MSR-s
On 04/26/2016 11:49 AM, Razvan Cojocaru wrote: > Previously, subscribing to MSR write events was an all-or-none > approach, with special cases for introspection MSR-s. This patch > allows the vm_event consumer to specify exactly what MSR-s it is > interested in, and as a side-effect gets rid of the > vmx_introspection_force_enabled_msrs[] special case. > This replaces the previously posted "xen: Filter out MSR write > events" patch. > > Signed-off-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx> > > --- > Changes since V4: > - Added arch_monitor_init_domain() and arch_monitor_cleanup_domain() > as suggested by Tamas Lengyel and Andrew Cooper. > - Factored out common MSR range code in monitor_bitmap_for_msr(), > as suggested by Andrew Cooper. > - Renamed monitor_is_msr_enabled() to monitored_msr(), as > suggested by Andrew Cooper. > - Replaced clear_bit() with __clear_bit(). > - Now returning -EINVAL when monitor_bitmap_for_msr() returns NULL > (i.e. when the MSR is out of range). > - Since these are slightly more than minor changes, removed all > previous Acks. > --- > tools/libxc/include/xenctrl.h | 9 ++- > tools/libxc/xc_monitor.c | 6 +- > xen/arch/x86/hvm/event.c | 3 +- > xen/arch/x86/hvm/hvm.c | 3 +- > xen/arch/x86/hvm/vmx/vmcs.c | 26 +------- > xen/arch/x86/hvm/vmx/vmx.c | 10 +--- > xen/arch/x86/monitor.c | 120 > +++++++++++++++++++++++++++++++++---- > xen/arch/x86/vm_event.c | 9 +++ > xen/common/vm_event.c | 5 ++ > xen/include/asm-arm/monitor.h | 13 ++++ > xen/include/asm-x86/domain.h | 4 +- > xen/include/asm-x86/hvm/hvm.h | 8 +-- > xen/include/asm-x86/hvm/vmx/vmcs.h | 7 --- > xen/include/asm-x86/monitor.h | 12 ++++ > xen/include/public/domctl.h | 5 +- > 15 files changed, 173 insertions(+), 67 deletions(-) > > diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h > index f5a034a..3216e48 100644 > --- a/tools/libxc/include/xenctrl.h > +++ b/tools/libxc/include/xenctrl.h > @@ -2183,8 +2183,13 @@ int xc_monitor_get_capabilities(xc_interface *xch, > domid_t domain_id, > int xc_monitor_write_ctrlreg(xc_interface *xch, domid_t domain_id, > uint16_t index, bool enable, bool sync, > bool onchangeonly); > -int xc_monitor_mov_to_msr(xc_interface *xch, domid_t domain_id, bool enable, > - bool extended_capture); > +/* > + * A list of MSR indices can usually be found in > /usr/include/asm/msr-index.h. > + * Please consult the Intel/AMD manuals for more information on > + * non-architectural indices. > + */ > +int xc_monitor_mov_to_msr(xc_interface *xch, domid_t domain_id, uint32_t msr, > + bool enable); > int xc_monitor_singlestep(xc_interface *xch, domid_t domain_id, bool enable); > int xc_monitor_software_breakpoint(xc_interface *xch, domid_t domain_id, > bool enable); > diff --git a/tools/libxc/xc_monitor.c b/tools/libxc/xc_monitor.c > index b1705dd..78131b2 100644 > --- a/tools/libxc/xc_monitor.c > +++ b/tools/libxc/xc_monitor.c > @@ -86,8 +86,8 @@ int xc_monitor_write_ctrlreg(xc_interface *xch, domid_t > domain_id, > return do_domctl(xch, &domctl); > } > > -int xc_monitor_mov_to_msr(xc_interface *xch, domid_t domain_id, bool enable, > - bool extended_capture) > +int xc_monitor_mov_to_msr(xc_interface *xch, domid_t domain_id, uint32_t msr, > + bool enable) > { > DECLARE_DOMCTL; > > @@ -96,7 +96,7 @@ int xc_monitor_mov_to_msr(xc_interface *xch, domid_t > domain_id, bool enable, > domctl.u.monitor_op.op = enable ? XEN_DOMCTL_MONITOR_OP_ENABLE > : XEN_DOMCTL_MONITOR_OP_DISABLE; > domctl.u.monitor_op.event = XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR; > - domctl.u.monitor_op.u.mov_to_msr.extended_capture = extended_capture; > + domctl.u.monitor_op.u.mov_to_msr.msr = msr; > > return do_domctl(xch, &domctl); > } > diff --git a/xen/arch/x86/hvm/event.c b/xen/arch/x86/hvm/event.c > index 56c5514..8fdb6f5 100644 > --- a/xen/arch/x86/hvm/event.c > +++ b/xen/arch/x86/hvm/event.c > @@ -57,9 +57,8 @@ bool_t hvm_event_cr(unsigned int index, unsigned long > value, unsigned long old) > void hvm_event_msr(unsigned int msr, uint64_t value) > { > struct vcpu *curr = current; > - struct arch_domain *ad = &curr->domain->arch; > > - if ( ad->monitor.mov_to_msr_enabled ) > + if ( monitored_msr(curr->domain, msr) ) > { > vm_event_request_t req = { > .reason = VM_EVENT_REASON_MOV_TO_MSR, > diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c > index e9d4c6b..7495820 100644 > --- a/xen/arch/x86/hvm/hvm.c > +++ b/xen/arch/x86/hvm/hvm.c > @@ -3694,7 +3694,6 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t > msr_content, > bool_t mtrr; > unsigned int edx, index; > int ret = X86EMUL_OKAY; > - struct arch_domain *currad = ¤t->domain->arch; > > HVMTRACE_3D(MSR_WRITE, msr, > (uint32_t)msr_content, (uint32_t)(msr_content >> 32)); > @@ -3702,7 +3701,7 @@ int hvm_msr_write_intercept(unsigned int msr, uint64_t > msr_content, > hvm_cpuid(1, NULL, NULL, NULL, &edx); > mtrr = !!(edx & cpufeat_mask(X86_FEATURE_MTRR)); > > - if ( may_defer && unlikely(currad->monitor.mov_to_msr_enabled) ) > + if ( may_defer && unlikely(monitored_msr(v->domain, msr)) ) > { > ASSERT(v->arch.vm_event); > > diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c > index 8284281..f8421e8 100644 > --- a/xen/arch/x86/hvm/vmx/vmcs.c > +++ b/xen/arch/x86/hvm/vmx/vmcs.c > @@ -37,6 +37,7 @@ > #include <asm/hvm/vmx/vvmx.h> > #include <asm/hvm/vmx/vmcs.h> > #include <asm/flushtlb.h> > +#include <asm/monitor.h> > #include <asm/shadow.h> > #include <asm/tboot.h> > #include <asm/apic.h> > @@ -108,18 +109,6 @@ u64 vmx_ept_vpid_cap __read_mostly; > u64 vmx_vmfunc __read_mostly; > bool_t vmx_virt_exception __read_mostly; > > -const u32 vmx_introspection_force_enabled_msrs[] = { > - MSR_IA32_SYSENTER_EIP, > - MSR_IA32_SYSENTER_ESP, > - MSR_IA32_SYSENTER_CS, > - MSR_IA32_MC0_CTL, > - MSR_STAR, > - MSR_LSTAR > -}; > - > -const unsigned int vmx_introspection_force_enabled_msrs_size = > - ARRAY_SIZE(vmx_introspection_force_enabled_msrs); > - > static DEFINE_PER_CPU_READ_MOSTLY(paddr_t, vmxon_region); > static DEFINE_PER_CPU(paddr_t, current_vmcs); > static DEFINE_PER_CPU(struct list_head, active_vmcs_list); > @@ -810,17 +799,8 @@ void vmx_disable_intercept_for_msr(struct vcpu *v, u32 > msr, int type) > if ( msr_bitmap == NULL ) > return; > > - if ( unlikely(d->arch.monitor.mov_to_msr_enabled && > - d->arch.monitor.mov_to_msr_extended) && > - vm_event_check_ring(&d->vm_event->monitor) ) > - { > - unsigned int i; > - > - /* Filter out MSR-s needed for memory introspection */ > - for ( i = 0; i < vmx_introspection_force_enabled_msrs_size; i++ ) > - if ( msr == vmx_introspection_force_enabled_msrs[i] ) > - return; > - } > + if ( unlikely(monitored_msr(d, msr)) ) > + return; > > /* > * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals > diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c > index bc4410f..9135441 100644 > --- a/xen/arch/x86/hvm/vmx/vmx.c > +++ b/xen/arch/x86/hvm/vmx/vmx.c > @@ -1958,16 +1958,12 @@ 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) > +static void vmx_enable_msr_interception(struct domain *d, uint32_t msr) > { > struct vcpu *v; > - unsigned int i; > > - /* Enable interception for MSRs needed for memory introspection. */ > for_each_vcpu ( d, v ) > - for ( i = 0; i < vmx_introspection_force_enabled_msrs_size; i++ ) > - vmx_enable_intercept_for_msr(v, > vmx_introspection_force_enabled_msrs[i], > - MSR_TYPE_W); > + vmx_enable_intercept_for_msr(v, msr, MSR_TYPE_W); > } > > static bool_t vmx_is_singlestep_supported(void) > @@ -2166,7 +2162,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, > + .enable_msr_interception = vmx_enable_msr_interception, > .is_singlestep_supported = vmx_is_singlestep_supported, > .set_mode = vmx_set_mode, > .altp2m_vcpu_update_p2m = vmx_vcpu_update_eptp, > diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c > index 1fec412..df56981 100644 > --- a/xen/arch/x86/monitor.c > +++ b/xen/arch/x86/monitor.c > @@ -22,6 +22,99 @@ > #include <asm/monitor.h> > #include <public/vm_event.h> > > +int arch_monitor_init_domain(struct domain *d) > +{ > + d->arch.monitor_msr_bitmap = xzalloc(struct monitor_msr_bitmap); > + > + if ( !d->arch.monitor_msr_bitmap ) > + return -ENOMEM; > + > + return 0; > +} > + > +void arch_monitor_cleanup_domain(struct domain *d) > +{ > + xfree(d->arch.monitor_msr_bitmap); > + d->arch.monitor_msr_bitmap = NULL; > +} > + > +static void *monitor_bitmap_for_msr(struct domain *d, u32 *msr) > +{ > + ASSERT(d->arch.monitor_msr_bitmap && msr); > + > + switch ( *msr ) > + { > + case 0 ... 0x1fff: > + BUILD_BUG_ON(ARRAY_SIZE(d->arch.monitor_msr_bitmap->low) * 8 < > 0x1fff); > + return &d->arch.monitor_msr_bitmap->low; > + > + case 0x40000000 ... 0x40001fff: > + BUILD_BUG_ON( > + ARRAY_SIZE(d->arch.monitor_msr_bitmap->hypervisor) * 8 < 0x1fff); > + *msr &= 0x1fff; > + return &d->arch.monitor_msr_bitmap->hypervisor; > + > + case 0xc0000000 ... 0xc0001fff: > + BUILD_BUG_ON(ARRAY_SIZE(d->arch.monitor_msr_bitmap->high) * 8 < > 0x1fff); > + *msr &= 0x1fff; > + return &d->arch.monitor_msr_bitmap->high; > + > + default: > + return NULL; > + } > +} > + > +static int monitor_enable_msr(struct domain *d, u32 msr) > +{ > + u32 *bitmap; > + > + if ( !d->arch.monitor_msr_bitmap ) > + return -ENXIO; > + > + bitmap = monitor_bitmap_for_msr(d, &msr); > + > + if ( !bitmap ) > + return -EINVAL; > + > + __set_bit(msr, bitmap); > + > + hvm_enable_msr_interception(d, msr); > + > + return 0; > +} > + > +static int monitor_disable_msr(struct domain *d, u32 msr) > +{ > + u32 *bitmap; > + > + if ( !d->arch.monitor_msr_bitmap ) > + return -ENXIO; > + > + bitmap = monitor_bitmap_for_msr(d, &msr); > + > + if ( !bitmap ) > + return -EINVAL; > + > + __clear_bit(msr, bitmap); > + > + return 0; > +} > + > +bool_t monitored_msr(struct domain *d, u32 msr) > +{ > + u32 *bitmap; > + > + if ( !d->arch.monitor_msr_bitmap ) > + return 0; > + > + bitmap = monitor_bitmap_for_msr(d, &msr); > + > + if ( !bitmap ) > + return 0; > + > + return test_bit(msr, bitmap); > +} > + > int arch_monitor_domctl_event(struct domain *d, > struct xen_domctl_monitor_op *mop) > { > @@ -77,25 +170,28 @@ int arch_monitor_domctl_event(struct domain *d, > > case XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR: > { > - bool_t old_status = ad->monitor.mov_to_msr_enabled; > + bool_t old_status; > + int rc; > + u32 msr = mop->u.mov_to_msr.msr; > > - if ( unlikely(old_status == requested_status) ) > - return -EEXIST; > + domain_pause(d); > > - if ( requested_status && mop->u.mov_to_msr.extended_capture && > - !hvm_enable_msr_exit_interception(d) ) > - return -EOPNOTSUPP; > + old_status = monitored_msr(d, msr); > > - domain_pause(d); > + if ( unlikely(old_status == requested_status) ) > + { > + domain_unpause(d); > + return -EEXIST; > + } > > - if ( requested_status && mop->u.mov_to_msr.extended_capture ) > - ad->monitor.mov_to_msr_extended = 1; > + if ( requested_status ) > + rc = monitor_enable_msr(d, msr); > else > - ad->monitor.mov_to_msr_extended = 0; > + rc = monitor_disable_msr(d, msr); > > - ad->monitor.mov_to_msr_enabled = requested_status; > domain_unpause(d); > - break; > + > + return rc; > } > > case XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP: > diff --git a/xen/arch/x86/vm_event.c b/xen/arch/x86/vm_event.c > index 5635603..22819c5 100644 > --- a/xen/arch/x86/vm_event.c > +++ b/xen/arch/x86/vm_event.c > @@ -20,6 +20,7 @@ > > #include <xen/sched.h> > #include <asm/hvm/hvm.h> > +#include <asm/monitor.h> > #include <asm/vm_event.h> > > /* Implicitly serialized by the domctl lock. */ > @@ -27,6 +28,11 @@ int vm_event_init_domain(struct domain *d) > { > struct vcpu *v; > > + d->arch.monitor_msr_bitmap = xzalloc(struct monitor_msr_bitmap); > + > + if ( !d->arch.monitor_msr_bitmap ) > + return -ENOMEM; > + > for_each_vcpu ( d, v ) > { > if ( v->arch.vm_event ) > @@ -55,6 +61,9 @@ void vm_event_cleanup_domain(struct domain *d) > v->arch.vm_event = NULL; > } > > + xfree(d->arch.monitor_msr_bitmap); > + d->arch.monitor_msr_bitmap = NULL; > + > d->arch.mem_access_emulate_each_rep = 0; > memset(&d->arch.monitor, 0, sizeof(d->arch.monitor)); > memset(&d->monitor, 0, sizeof(d->monitor)); Aside from accidentally duplicating the alloc() / free() code here, I should have probably moved the following monitor-related memset()s in arch_monitor_init_domain() as well. I'll do that in V6. Thanks, Razvan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |