return rc;
}
+/*
+ * Note that this value is effectively part of the ABI, even if we don't need
+ * to make it a formal part of it: A guest suspended for migration in the
+ * middle of a continuation would fail to work if resumed on a hypervisor
+ * using a different value.
+ */
#define HVMOP_op_mask 0xff
long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
{
struct domain *curr_d = current->domain;
- unsigned long start_iter = op & ~HVMOP_op_mask;
+ unsigned long start_iter, mask;
long rc = 0;
- switch ( op &= HVMOP_op_mask )
+ switch ( op & HVMOP_op_mask )
+ {
+ default:
+ mask = ~0UL;
+ break;
+ case HVMOP_modified_memory:
+ case HVMOP_set_mem_type:
+ mask = HVMOP_op_mask;
+ break;
+ }
+
+ start_iter = op & ~mask;
+ switch ( op &= mask )
{
case HVMOP_create_ioreq_server:
rc = hvmop_create_ioreq_server(
if ( rc == -ERESTART )
{
- ASSERT(!(start_iter & HVMOP_op_mask));
+ ASSERT(!(start_iter & mask));
rc = hypercall_create_continuation(__HYPERVISOR_hvm_op, "lh",
op | start_iter, arg);
}
long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
{
int rc;
- int op = cmd & MEMOP_CMD_MASK;
- switch ( op )
+ switch ( cmd )
{
case XENMEM_set_memory_map:
{
if ( d == NULL )
return -ESRCH;
- if ( op == XENMEM_set_pod_target )
+ if ( cmd == XENMEM_set_pod_target )
rc = xsm_set_pod_target(XSM_PRIV, d);
else
rc = xsm_get_pod_target(XSM_PRIV, d);
if ( rc != 0 )
goto pod_target_out_unlock;
- if ( op == XENMEM_set_pod_target )
+ if ( cmd == XENMEM_set_pod_target )
{
if ( target.target_pages > d->max_pages )
{
if ( rc == -ERESTART )
{
rc = hypercall_create_continuation(
- __HYPERVISOR_memory_op, "lh", op, arg);
+ __HYPERVISOR_memory_op, "lh", cmd, arg);
}
else if ( rc >= 0 )
{
compat_pfn_t mfn;
unsigned int i;
int rc = 0;
- int op = cmd & MEMOP_CMD_MASK;
- switch ( op )
+ switch ( cmd )
{
case XENMEM_set_memory_map:
{
xen_mem_event_op_t meo;
if ( copy_from_guest(&meo, arg, 1) )
return -EFAULT;
- rc = do_mem_event_op(op, meo.domain, (void *) &meo);
+ rc = do_mem_event_op(cmd, meo.domain, &meo);
if ( !rc && __copy_to_guest(arg, &meo, 1) )
return -EFAULT;
break;
return -EFAULT;
if ( mso.op == XENMEM_sharing_op_audit )
return mem_sharing_audit();
- rc = do_mem_event_op(op, mso.domain, (void *) &mso);
+ rc = do_mem_event_op(cmd, mso.domain, &mso);
if ( !rc && __copy_to_guest(arg, &mso, 1) )
return -EFAULT;
break;
xen_pfn_t mfn, last_mfn;
unsigned int i;
long rc = 0;
- int op = cmd & MEMOP_CMD_MASK;
- switch ( op )
+ switch ( cmd )
{
case XENMEM_machphys_mfn_list:
if ( copy_from_guest(&xmml, arg, 1) )
xen_mem_event_op_t meo;
if ( copy_from_guest(&meo, arg, 1) )
return -EFAULT;
- rc = do_mem_event_op(op, meo.domain, (void *) &meo);
+ rc = do_mem_event_op(cmd, meo.domain, &meo);
if ( !rc && __copy_to_guest(arg, &meo, 1) )
return -EFAULT;
break;
return -EFAULT;
if ( mso.op == XENMEM_sharing_op_audit )
return mem_sharing_audit();
- rc = do_mem_event_op(op, mso.domain, (void *) &mso);
+ rc = do_mem_event_op(cmd, mso.domain, &mso);
if ( !rc && __copy_to_guest(arg, &mso, 1) )
return -EFAULT;
break;
set_xen_guest_handle(cnt_uop, NULL);
cmd_op = cmd & GNTTABOP_CMD_MASK;
+ if ( cmd_op != GNTTABOP_cache_flush )
+ cmd_op = cmd;
switch ( cmd_op )
{
#define CASE(name) \
static unsigned int __read_mostly max_maptrack_frames;
integer_param("gnttab_max_maptrack_frames", max_maptrack_frames);
+/*
+ * Note that the three values below are effectively part of the ABI, even if
+ * we don't need to make them a formal part of it: A guest suspended for
+ * migration in the middle of a continuation would fail to work if resumed on
+ * a hypervisor using different values.
+ */
#define GNTTABOP_CONTINUATION_ARG_SHIFT 12
#define GNTTABOP_CMD_MASK ((1<<GNTTABOP_CONTINUATION_ARG_SHIFT)-1)
#define GNTTABOP_ARG_MASK (~GNTTABOP_CMD_MASK)
if ( (int)count < 0 )
return -EINVAL;
+
+ if ( (cmd &= GNTTABOP_CMD_MASK) != GNTTABOP_cache_flush && opaque_in )
+ return -ENOSYS;
rc = -EFAULT;
- switch ( cmd &= GNTTABOP_CMD_MASK )
+ switch ( cmd )
{
case GNTTABOP_map_grant_ref:
{
int mem_access_memop(unsigned long cmd,
XEN_GUEST_HANDLE_PARAM(xen_mem_access_op_t) arg)
{
+ unsigned long start_iter = cmd & ~MEMOP_CMD_MASK;
long rc;
xen_mem_access_op_t mao;
struct domain *d;
switch ( mao.op )
{
case XENMEM_access_op_resume:
- mem_access_resume(d);
- rc = 0;
+ if ( unlikely(start_iter) )
+ rc = -ENOSYS;
+ else
+ {
+ mem_access_resume(d);
+ rc = 0;
+ }
break;
case XENMEM_access_op_set_access:
- {
- unsigned long start_iter = cmd & ~MEMOP_CMD_MASK;
-
rc = -EINVAL;
if ( (mao.pfn != ~0ull) &&
(mao.nr < start_iter ||
XENMEM_access_op | rc, arg);
}
break;
- }
case XENMEM_access_op_get_access:
{
xenmem_access_t access;
+ rc = -ENOSYS;
+ if ( unlikely(start_iter) )
+ break;
+
rc = -EINVAL;
if ( (mao.pfn > domain_get_maximum_gpfn(d)) && mao.pfn != ~0ull )
break;
break;
case XENMEM_exchange:
+ if ( unlikely(start_extent) )
+ return -ENOSYS;
+
rc = memory_exchange(guest_handle_cast(arg, xen_memory_exchange_t));
break;
case XENMEM_maximum_ram_page:
+ if ( unlikely(start_extent) )
+ return -ENOSYS;
+
rc = max_page;
break;
case XENMEM_current_reservation:
case XENMEM_maximum_reservation:
case XENMEM_maximum_gpfn:
+ if ( unlikely(start_extent) )
+ return -ENOSYS;
+
if ( copy_from_guest(&domid, arg, 1) )
return -EFAULT;
struct page_info *page;
struct domain *d;
+ if ( unlikely(start_extent) )
+ return -ENOSYS;
+
if ( copy_from_guest(&xrfp, arg, 1) )
return -EFAULT;
break;
case XENMEM_claim_pages:
+ if ( unlikely(start_extent) )
+ return -ENOSYS;
+
if ( copy_from_guest(&reservation, arg, 1) )
return -EFAULT;
unsigned int dom_vnodes, dom_vranges, dom_vcpus;
struct vnuma_info tmp;
+ if ( unlikely(start_extent) )
+ return -ENOSYS;
+
/*
* Guest passes nr_vnodes, number of regions and nr_vcpus thus
* we know how much memory guest has allocated.
* To allow safe resume of do_memory_op() after preemption, we need to know
* at what point in the page list to resume. For this purpose I steal the
* high-order bits of the @cmd parameter, which are otherwise unused and zero.
+ *
+ * Note that both of these values are effectively part of the ABI, even if
+ * we don't need to make them a formal part of it: A guest suspended for
+ * migration in the middle of a continuation would fail to work if resumed on
+ * a hypervisor using different values.
*/
#define MEMOP_EXTENT_SHIFT 6 /* cmd[:6] == start_extent */
#define MEMOP_CMD_MASK ((1 << MEMOP_EXTENT_SHIFT) - 1)