|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |