[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



> 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?
> +
> +    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?

> +    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?

> +
> +    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?
>      {
> -        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.

> +    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?


>          } mov_to_msr;
>  
>          struct {
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.