[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v11 1/9] x86: add generic MSR access hypercall



> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@xxxxxxxx]
> Sent: Friday, June 20, 2014 11:01 PM
> To: Xu, Dongxiao
> Cc: andrew.cooper3@xxxxxxxxxx; Ian.Campbell@xxxxxxxxxx;
> George.Dunlap@xxxxxxxxxxxxx; Ian.Jackson@xxxxxxxxxxxxx;
> stefano.stabellini@xxxxxxxxxxxxx; xen-devel@xxxxxxxxxxxxx;
> konrad.wilk@xxxxxxxxxx; dgdegra@xxxxxxxxxxxxx; keir@xxxxxxx
> Subject: Re: [PATCH v11 1/9] x86: add generic MSR access hypercall
> 
> >>> On 20.06.14 at 16:31, <dongxiao.xu@xxxxxxxxx> wrote:
> > Add a generic MSR access hypercall for tool stack or other components to
> > read or write certain system MSRs.
> 
> If you want this to be usable by components other than the tool stack
> then this can't be a sysctl (would e.g. need to be a platform-op then).

Per my understanding, the platform-op related hypercalls are used by Dom0 
kernel.
While in this CQM scenario, we want libvirt/libxl/libxc to call such hypercall 
to access the MSR, however I didn't see any usage of platform_op in libxl/libxc 
side.

Could you explain a bit more for it?

> 
> > --- a/xen/arch/x86/sysctl.c
> > +++ b/xen/arch/x86/sysctl.c
> > @@ -66,10 +66,27 @@ void arch_do_physinfo(xen_sysctl_physinfo_t *pi)
> >          pi->capabilities |= XEN_SYSCTL_PHYSCAP_hvm_directio;
> >  }
> >
> > +static void msr_access_helper(void *data)
> > +{
> > +    struct msr_access_info *info = data;
> > +    xen_sysctl_msr_data_t *msr_data;
> > +    unsigned int i;
> > +
> > +    for ( i = 0; i < info->nr_ops; i++ )
> > +    {
> > +        msr_data = &info->msr_data[i];
> > +        if ( msr_data->cmd == XEN_SYSCTL_MSR_read )
> > +            rdmsrl(msr_data->msr, msr_data->val);
> > +        else if ( msr_data->cmd == XEN_SYSCTL_MSR_write )
> > +            wrmsrl(msr_data->msr, msr_data->val);
> > +    }
> 
> Missing preemption check.

Do you mean hypercall_preemption_check() here? Or the preemption between the 
MSR accesses?

> 
> > @@ -101,11 +118,48 @@ long arch_do_sysctl(
> >      }
> >      break;
> >
> > +    case XEN_SYSCTL_msr_op:
> > +    {
> > +        unsigned int cpu = sysctl->u.msr_op.cpu;
> > +        struct msr_access_info info;
> > +
> > +        info.nr_ops = sysctl->u.msr_op.nr_ops;
> > +        info.msr_data = xzalloc_array(xen_sysctl_msr_data_t, info.nr_ops);
> > +        if ( !info.msr_data )
> > +            return -ENOMEM;
> > +
> > +        if ( copy_from_guest(info.msr_data, sysctl->u.msr_op.msr_data,
> > +                             info.nr_ops) )
> > +        {
> > +            xfree(info.msr_data);
> > +            return -EFAULT;
> > +        }
> > +
> > +        if ( cpu == smp_processor_id() )
> > +            msr_access_helper(&info);
> > +        else
> > +            on_selected_cpus(cpumask_of(cpu), msr_access_helper, &info,
> 1);
> > +
> > +        if ( copy_to_guest(sysctl->u.msr_op.msr_data, info.msr_data,
> > +                           info.nr_ops ) )
> > +        {
> > +            xfree(info.msr_data);
> > +            return -EFAULT;
> > +        }
> > +
> > +        xfree(info.msr_data);
> > +        copyback = 1;
> 
> I don't see what you're meaning to copy back here.

Yes, thanks! This needs to be removed, at least for the MSR access since we 
already explicitly copy back the data to guest.

> 
> Anyway, together with the comments on the interface itself (further
> down) I think you'd be much better off basing this on
> continue_hypercall_on_cpu().

continue_hypercall_on_cpu() function schedules a tasklet to run the specific 
function on certain CPU.
However in our CQM case, the libxl/libxc functions want to get the result 
immediately when the function returns, so that's why I didn't use 
continue_hypercall_on_cpu().

> 
> > --- a/xen/include/public/sysctl.h
> > +++ b/xen/include/public/sysctl.h
> > @@ -636,6 +636,29 @@ struct xen_sysctl_coverage_op {
> >  typedef struct xen_sysctl_coverage_op xen_sysctl_coverage_op_t;
> >  DEFINE_XEN_GUEST_HANDLE(xen_sysctl_coverage_op_t);
> >
> > +#define XEN_SYSCTL_MSR_read                0
> > +#define XEN_SYSCTL_MSR_write               1
> > +
> > +struct xen_sysctl_msr_data {
> > +    uint32_t cmd;       /* XEN_SYSCTL_MSR_* */
> > +    uint32_t msr;
> > +    uint64_t val;
> > +};
> > +typedef struct xen_sysctl_msr_data xen_sysctl_msr_data_t;
> > +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_msr_data_t);
> > +struct xen_sysctl_msr_op {
> > +    uint32_t nr_ops;
> 
> Jusr "nr" would suffice.

Okay.

> 
> > +    uint32_t cpu;
> 
> This is rather limiting - you should be able to specify a CPU for
> each operation. That way you'll have another 32-bit field available
> for flags: You indicated earlier on that you'd want certain
> operations (like a write followed by a read) pairable without
> potentially getting preempted in between. The field then freed up
> here should then be reserved for use as flags field too (i.e. you'd
> need to check that it's zero).

Do you mean the following case?

Op1: CPU0, write MSR 0x100. Flag: 1 (indicating paring)
Op2: CPU1, read MSR 0x200. Flag: 0.
Op3: CPU0, read MSR 0x101. Flag: 1 (paring the above op1)

To avoid the preempt between certain operations, my previous solution is to 
pack all the operations towards a certain CPU via a single IPI. When the target 
CPU receives the IPI, it will execute the operations one by one (suppose during 
the execution for loop, no preemption will happen).
Now if we specify a CPU for each operation, can we pack the operations 
according to the target CPU, and finally issue one IPI per-target-CPU to avoid 
preemption? That will get rid of such flag usage.

> 
> > +    XEN_GUEST_HANDLE_64(xen_sysctl_msr_data_t) msr_data;
> > +};
> > +typedef struct xen_sysctl_msr_op xen_sysctl_msr_op_t;
> > +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_msr_op_t);
> 
> I think there shouldn't be any mention of "MSR" in other than the
> specific sub-op names. As already said earlier, I see this also as
> a vehicle to potentially to port accesses (namely when two of them
> need to be done in close succession, or one needs to be carried
> out on a particular CPU).

That's okay.

> 
> > +struct msr_access_info {
> > +    uint32_t nr_ops;
> > +    xen_sysctl_msr_data_t *msr_data;
> > +};
> 
> This can only be misplaced - there are no pointers in public headers.

Okay, will move it in other places.

Thanks,
Dongxiao

> 
> Jan

_______________________________________________
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®.