|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH V2] vm_event: Allow subscribing to write events for specific MSR-s
On 04/13/2016 12:47 PM, Konrad Rzeszutek Wilk wrote:
>> diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c
>> index 1fec412..4c96968 100644
>> --- a/xen/arch/x86/monitor.c
>> +++ b/xen/arch/x86/monitor.c
>> @@ -22,6 +22,58 @@
>> #include <asm/monitor.h>
>> #include <public/vm_event.h>
>>
>> +static int arch_monitor_enable_msr(struct domain *d, u32 msr)
>> +{
>> + if ( !d->arch.monitor_msr_bitmap )
>> + return -EINVAL;
>
> I this was not set wouldn't we fail in vm_event_enable with -ENOMEM?
>
> I presume the user can still make this hypercall.. Ah yes.
>
> Perhaps -ENXIO?
Sure, I can return -ENXIO. I just thought -EINVAL reflects the case
well: it's not right to call this hypercall if you haven't subscribed
for vm_events beforehand (in which case d->arch.monitor_msr_bitmap is
NULL, because it's only allocated then, and de-allocated again when the
subscriber unsubscribes).
>> +
>> + if ( msr <= 0x1fff )
>> + set_bit(msr, d->arch.monitor_msr_bitmap + 0x000/BYTES_PER_LONG);
>
> The 0x000/BYTER_PER_LONG looks odd. Is it even needed?
I've pretty much copied the code from the enabled msrs bitmap, so I
assume it was, but I'll change the code to follow Andrew Cooper's
suggestion which should make this go away.
>> + else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) )
>> + {
>> + msr &= 0x1fff;
>> + set_bit(msr, d->arch.monitor_msr_bitmap + 0x400/BYTES_PER_LONG);
>> + }
>> +
>> + hvm_enable_msr_interception(d, msr);
>
> And for MSRs above 0xc0001fff it is OK to enable the interception?
> Or between 0x1fff and 0xc0000000?
>
> No need to filter them out? Or error on them?
>> +
>> + return 0;
>> +}
>> +
>> +static int arch_monitor_disable_msr(struct domain *d, u32 msr)
>> +{
>> + if ( !d->arch.monitor_msr_bitmap )
>> + return -EINVAL;
>> +
>> + if ( msr <= 0x1fff )
>> + clear_bit(msr, d->arch.monitor_msr_bitmap + 0x000/BYTES_PER_LONG);
>> + else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) )
>> + {
>> + msr &= 0x1fff;
>> + clear_bit(msr, d->arch.monitor_msr_bitmap + 0x400/BYTES_PER_LONG);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +bool_t arch_monitor_is_msr_enabled(const struct domain *d, u32 msr)
>> +{
>> + bool_t rc = 0;
>> +
>> + if ( !d->arch.monitor_msr_bitmap )
>> + return 0;
>> +
>> + if ( msr <= 0x1fff )
>> + rc = test_bit(msr, d->arch.monitor_msr_bitmap +
>> 0x000/BYTES_PER_LONG);
>> + else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) )
>> + {
>> + msr &= 0x1fff;
>> + rc = test_bit(msr, d->arch.monitor_msr_bitmap +
>> 0x400/BYTES_PER_LONG);
>> + }
>
> And what if msr requested is above 0xc0001fff ? What then?
I think the questions above have been answered by Andrew Cooper.
>> +
>> + return rc;
>> +}
>> +
>> int arch_monitor_domctl_event(struct domain *d,
>> struct xen_domctl_monitor_op *mop)
>> {
>> @@ -77,25 +129,28 @@ int arch_monitor_domctl_event(struct domain *d,
>>
>> case XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR:
>
> Should this be renamed?
I'm happy to rename it, but I don't think it should - it has the exact
same semantics as before: monitor a MSR write.
>> {
>> - 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 = arch_monitor_is_msr_enabled(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 = arch_monitor_enable_msr(d, msr);
>> else
>> - ad->monitor.mov_to_msr_extended = 0;
>> + rc = arch_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..9b4267e 100644
>> --- a/xen/arch/x86/vm_event.c
>> +++ b/xen/arch/x86/vm_event.c
>> @@ -27,6 +27,13 @@ int vm_event_init_domain(struct domain *d)
>> {
>> struct vcpu *v;
>>
>> + d->arch.monitor_msr_bitmap = alloc_xenheap_page();
>
> How about using vzalloc?
>> +
>> + if ( !d->arch.monitor_msr_bitmap )
>> + return -ENOMEM;
>> +
>> + memset(d->arch.monitor_msr_bitmap, 0, PAGE_SIZE);
>
> Then you don't have to do that.
>
>> +
>> for_each_vcpu ( d, v )
>> {
>> if ( v->arch.vm_event )
>> @@ -55,6 +62,9 @@ void vm_event_cleanup_domain(struct domain *d)
>> v->arch.vm_event = NULL;
>> }
>>
>> + free_xenheap_page(d->arch.monitor_msr_bitmap);
>
> And this would be vfree.
I'll follow Andrew Cooper's requests here, which should address these
issues.
>> + 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));
>> diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
>> index d393ed2..d8d91c2 100644
>> --- a/xen/include/asm-x86/domain.h
>> +++ b/xen/include/asm-x86/domain.h
>> @@ -398,12 +398,12 @@ struct arch_domain
>> unsigned int write_ctrlreg_enabled : 4;
>> unsigned int write_ctrlreg_sync : 4;
>> unsigned int write_ctrlreg_onchangeonly : 4;
>> - unsigned int mov_to_msr_enabled : 1;
>> - unsigned int mov_to_msr_extended : 1;
>> unsigned int singlestep_enabled : 1;
>> unsigned int software_breakpoint_enabled : 1;
>> } monitor;
>>
>> + unsigned long *monitor_msr_bitmap;
>> +
>> /* Mem_access emulation control */
>> bool_t mem_access_emulate_each_rep;
>>
>> diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
>> index 7b7ff3f..9d1c0ef 100644
>> --- a/xen/include/asm-x86/hvm/hvm.h
>> +++ b/xen/include/asm-x86/hvm/hvm.h
>> @@ -211,7 +211,7 @@ struct hvm_function_table {
>> uint32_t *eax, uint32_t *ebx,
>> uint32_t *ecx, uint32_t *edx);
>>
>> - void (*enable_msr_exit_interception)(struct domain *d);
>> + void (*enable_msr_interception)(struct domain *d, uint32_t msr);
>> bool_t (*is_singlestep_supported)(void);
>> int (*set_mode)(struct vcpu *v, int mode);
>>
>> @@ -565,11 +565,11 @@ static inline enum hvm_intblk
>> nhvm_interrupt_blocked(struct vcpu *v)
>> return hvm_funcs.nhvm_intr_blocked(v);
>> }
>>
>> -static inline bool_t hvm_enable_msr_exit_interception(struct domain *d)
>> +static inline bool_t hvm_enable_msr_interception(struct domain *d, uint32_t
>> msr)
>> {
>> - if ( hvm_funcs.enable_msr_exit_interception )
>> + if ( hvm_funcs.enable_msr_interception )
>> {
>> - hvm_funcs.enable_msr_exit_interception(d);
>> + hvm_funcs.enable_msr_interception(d, msr);
>> return 1;
>> }
>>
>> diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h
>> b/xen/include/asm-x86/hvm/vmx/vmcs.h
>> index b54f52f..7bf5326 100644
>> --- a/xen/include/asm-x86/hvm/vmx/vmcs.h
>> +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
>> @@ -562,13 +562,6 @@ enum vmcs_field {
>> HOST_RIP = 0x00006c16,
>> };
>>
>> -/*
>> - * A set of MSR-s that need to be enabled for memory introspection
>> - * to work.
>> - */
>> -extern const u32 vmx_introspection_force_enabled_msrs[];
>> -extern const unsigned int vmx_introspection_force_enabled_msrs_size;
>> -
>> #define VMCS_VPID_WIDTH 16
>>
>> #define MSR_TYPE_R 1
>> diff --git a/xen/include/asm-x86/monitor.h b/xen/include/asm-x86/monitor.h
>> index 0954b59..74e5b1b 100644
>> --- a/xen/include/asm-x86/monitor.h
>> +++ b/xen/include/asm-x86/monitor.h
>> @@ -50,4 +50,6 @@ int arch_monitor_domctl_op(struct domain *d, struct
>> xen_domctl_monitor_op *mop)
>> int arch_monitor_domctl_event(struct domain *d,
>> struct xen_domctl_monitor_op *mop);
>>
>> +bool_t arch_monitor_is_msr_enabled(const struct domain *d, u32 msr);
>> +
>> #endif /* __ASM_X86_MONITOR_H__ */
>> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
>> index 2457698..875c09a 100644
>> --- a/xen/include/public/domctl.h
>> +++ b/xen/include/public/domctl.h
>> @@ -1107,8 +1107,7 @@ struct xen_domctl_monitor_op {
>> } mov_to_cr;
>>
>> struct {
>> - /* Enable the capture of an extended set of MSRs */
>> - uint8_t extended_capture;
>> + uint32_t msr;
>
> Whoa there. Isn't it expanding the structure? Will this be backwards
> compatible? What if somebody is using an older version of xen-access
> against this hypervisor? Will they work?
>
> Perhaps this should have a new struct / sub-ops? And the old
> 'mov_to_msr' will just re-use this new fangled code?
In addition to Andrew's comments, I think simply changing
VM_EVENT_INTERFACE_VERSION should be enough for xen-access-like clients
to figure out the incompatibility.
Thanks,
Razvan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |