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

Re: [Xen-devel] [PATCH v19 01/10] x86: add generic resource (e.g. MSR) access hypercall



>>> On 02.10.14 at 13:35, <chao.p.peng@xxxxxxxxxxxxxxx> wrote:
> +static void check_resource_access(struct xen_resource_access *ra)
> +{
> +    xenpf_resource_entry_t *entry;
> +    int ret = 0;
> +    unsigned int i;
> +
> +    for ( i = 0; i < ra->nr_entries; i++ )
> +    {
> +        entry = ra->entries + i;
> +
> +        if ( entry->rsvd )
> +        {
> +            entry->u.ret = -EINVAL;
> +            break;
> +        }
> +
> +        switch ( entry->u.cmd )
> +        {
> +        case XEN_RESOURCE_OP_MSR_READ:
> +        case XEN_RESOURCE_OP_MSR_WRITE:
> +            if ( entry->idx >> 32 )
> +                ret = -EINVAL;
> +            else if ( !allow_access_msr(entry->idx) )
> +                ret = -EACCES;
> +            break;
> +        default:
> +            ret = -EOPNOTSUPP;
> +            break;
> +        }
> +
> +        if ( ret )
> +        {
> +           entry->u.ret = ret;
> +           break;
> +        }
> +    }
> +
> +    ra->idx_done = i;

This is slightly abusing the field (considering its name) when all
entries succeeded, but I guess we can live with that. Beyond
that I have only cosmetic remarks to make, which I could equally
well address when committing (unless other issue get noticed by
someone else):

> +static void resource_access(void *info)
> +{
> +    struct xen_resource_access *ra = info;
> +    xenpf_resource_entry_t *entry;
> +    int ret;

I'd prefer these two to be inside the loop (also again in the earlier
function).

> +    unsigned int i;
> +
> +    for ( i = 0; i < ra->idx_done; i++ )
> +    {
> +        entry = ra->entries + i;
> +
> +        switch ( entry->u.cmd )
> +        {
> +        case XEN_RESOURCE_OP_MSR_READ:
> +            ret = rdmsr_safe(entry->idx, entry->val);
> +            break;
> +        case XEN_RESOURCE_OP_MSR_WRITE:
> +            ret = wrmsr_safe(entry->idx, entry->val);
> +            break;
> +        default:
> +            BUG();
> +            break;
> +        }
> +
> +        entry->u.ret = ret;
> +        if ( ret )
> +           break;

I continue to wonder whether we wouldn't be better off not
overwriting the command in the success case.

> @@ -601,6 +685,80 @@ ret_t 
> do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
>      }
>      break;
>  
> +    case XENPF_resource_op:
> +    {
> +        struct xen_resource_access ra;
> +        uint32_t cpu;

unsigned int

> +        XEN_GUEST_HANDLE(xenpf_resource_entry_t) guest_entries;
> +
> +        ra.nr_entries = op->u.resource_op.nr_entries;
> +        if ( ra.nr_entries == 0 )
> +        {
> +            ret = 0;
> +            break;
> +        }
> +        else if ( ra.nr_entries > RESOURCE_ACCESS_MAX_ENTRIES )

Pointless "else".

> +        {
> +            ret = -EINVAL;
> +            break;
> +        }
> +
> +        ra.entries = xmalloc_array(xenpf_resource_entry_t, ra.nr_entries);
> +        if ( !ra.entries )
> +        {
> +            ret = -ENOMEM;
> +            break;
> +        }
> +
> +        guest_from_compat_handle(guest_entries, op->u.resource_op.entries);
> +
> +        if ( copy_from_guest(ra.entries, guest_entries, ra.nr_entries) )
> +        {
> +            xfree(ra.entries);
> +            ret = -EFAULT;
> +            break;
> +        }
> +
> +        /* Do sanity check earlier to omit the potential IPI overhead. */
> +        check_resource_access(&ra);
> +        if ( ra.idx_done == 0 )
> +        {
> +            /* Copy the return value for entry 0 if it failed. */
> +            if ( __copy_to_guest_offset(guest_entries, 0, ra.entries, 1) )

__copy_to_guest()

> +                ret = -EFAULT;
> +            else
> +                ret = 0;
> +
> +            xfree(ra.entries);
> +            break;
> +        }
> +
> +        cpu = op->u.resource_op.cpu;
> +        if ( (cpu >= nr_cpu_ids) || !cpu_online(cpu) )
> +        {
> +            xfree(ra.entries);
> +            ret = -ENODEV;
> +            break;
> +        }
> +        else if ( cpu == smp_processor_id() )

Pointless "else" again.

> +            resource_access(&ra);
> +        else
> +            on_selected_cpus(cpumask_of(cpu), resource_access, &ra, 1);
> +
> +        /* Copy all if succeeded or up to the failed entry. */
> +        if ( __copy_to_guest_offset(guest_entries, 0, ra.entries,

__copy_to_guest()

> +                                    min(ra.nr_entries, ra.idx_done + 1)) )

I still think it would be more natural to code

ra.idx_done < ra.nr_entries ? ra.idx_done + 1 : ra.nr_entries

This has the same effect, but avoids the slight abuse of min() here
(and would look even more natural if idx_done was renamed to
nr_done or nr_valid).

> +        {
> +            xfree(ra.entries);
> +            ret = -EFAULT;
> +            break;
> +        }
> +
> +        ret = ra.idx_done;

And this again is a slight abuse. Also, handling this as an "else" to the
preceding "if" would save you an xfree() invocation and a "break".

> --- a/xen/include/public/platform.h
> +++ b/xen/include/public/platform.h
> @@ -528,6 +528,40 @@ typedef struct xenpf_core_parking xenpf_core_parking_t;
>  DEFINE_XEN_GUEST_HANDLE(xenpf_core_parking_t);
>  
>  /*
> + * Access generic platform resources(e.g., accessing MSR, port I/O, etc)
> + * in unified way. Batch resource operations in one call are supported and
> + * thay are always non-preemptible and executed in their original order.

they

> + * The batch itself returns a negative integer for general errors, or a
> + * non-negative integer for the number of successful operations. For latter

For the latter

> + * case, the @ret in the failed entry(if have) indicates the exact error and

entry (if any)

> + * it's meaningful only when it has a negative value.

???

> + */
> +#define XENPF_resource_op   61
> +
> +#define XEN_RESOURCE_OP_MSR_READ  0
> +#define XEN_RESOURCE_OP_MSR_WRITE 1
> +
> +struct xenpf_resource_entry {
> +    union {
> +        uint32_t cmd;   /* IN: XEN_RESOURCE_OP_* */
> +        int32_t  ret;   /* OUT: return value for this entry */

Imprecise comment (not all entries have this set).

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