aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/sysctl.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2012-12-10 11:18:25 +0100
committerJan Beulich <jbeulich@suse.com>2012-12-10 11:18:25 +0100
commite93e0d9d73ce77bd1f3471af68a194b47e0e8c45 (patch)
treebe7768d89381228bc3ed5f4867db23f631a78054 /xen/common/sysctl.c
parentedaa3f893f8f046e05099bc0d087b276a90451d4 (diff)
downloadxen-e93e0d9d73ce77bd1f3471af68a194b47e0e8c45.tar.gz
xen-e93e0d9d73ce77bd1f3471af68a194b47e0e8c45.tar.bz2
xen-e93e0d9d73ce77bd1f3471af68a194b47e0e8c45.zip
streamline guest copy operations
- use the variants not validating the VA range when writing back structures/fields to the same space that they were previously read from - when only a single field of a structure actually changed, copy back just that field where possible - consolidate copying back results in a few places Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/common/sysctl.c')
-rw-r--r--xen/common/sysctl.c91
1 files changed, 22 insertions, 69 deletions
diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c
index 47142f41fc..261b3c41de 100644
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -30,6 +30,7 @@
long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
{
long ret = 0;
+ int copyback = -1;
struct xen_sysctl curop, *op = &curop;
static DEFINE_SPINLOCK(sysctl_lock);
@@ -55,42 +56,28 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
switch ( op->cmd )
{
case XEN_SYSCTL_readconsole:
- {
ret = xsm_readconsole(op->u.readconsole.clear);
if ( ret )
break;
ret = read_console_ring(&op->u.readconsole);
- if ( copy_to_guest(u_sysctl, op, 1) )
- ret = -EFAULT;
- }
- break;
+ break;
case XEN_SYSCTL_tbuf_op:
- {
ret = xsm_tbufcontrol();
if ( ret )
break;
ret = tb_control(&op->u.tbuf_op);
- if ( copy_to_guest(u_sysctl, op, 1) )
- ret = -EFAULT;
- }
- break;
+ break;
case XEN_SYSCTL_sched_id:
- {
ret = xsm_sched_id();
if ( ret )
break;
op->u.sched_id.sched_id = sched_id();
- if ( copy_to_guest(u_sysctl, op, 1) )
- ret = -EFAULT;
- else
- ret = 0;
- }
- break;
+ break;
case XEN_SYSCTL_getdomaininfolist:
{
@@ -129,38 +116,27 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
break;
op->u.getdomaininfolist.num_domains = num_domains;
-
- if ( copy_to_guest(u_sysctl, op, 1) )
- ret = -EFAULT;
}
break;
#ifdef PERF_COUNTERS
case XEN_SYSCTL_perfc_op:
- {
ret = xsm_perfcontrol();
if ( ret )
break;
ret = perfc_control(&op->u.perfc_op);
- if ( copy_to_guest(u_sysctl, op, 1) )
- ret = -EFAULT;
- }
- break;
+ break;
#endif
#ifdef LOCK_PROFILE
case XEN_SYSCTL_lockprof_op:
- {
ret = xsm_lockprof();
if ( ret )
break;
ret = spinlock_profile_control(&op->u.lockprof_op);
- if ( copy_to_guest(u_sysctl, op, 1) )
- ret = -EFAULT;
- }
- break;
+ break;
#endif
case XEN_SYSCTL_debug_keys:
{
@@ -179,6 +155,7 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
handle_keypress(c, guest_cpu_user_regs());
}
ret = 0;
+ copyback = 0;
}
break;
@@ -193,22 +170,21 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
if ( ret )
break;
+ ret = -EFAULT;
for ( i = 0; i < nr_cpus; i++ )
{
cpuinfo.idletime = get_cpu_idle_time(i);
- ret = -EFAULT;
if ( copy_to_guest_offset(op->u.getcpuinfo.info, i, &cpuinfo, 1) )
goto out;
}
op->u.getcpuinfo.nr_cpus = i;
- ret = copy_to_guest(u_sysctl, op, 1) ? -EFAULT : 0;
+ ret = 0;
}
break;
case XEN_SYSCTL_availheap:
- {
ret = xsm_availheap();
if ( ret )
break;
@@ -218,47 +194,26 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
op->u.availheap.min_bitwidth,
op->u.availheap.max_bitwidth);
op->u.availheap.avail_bytes <<= PAGE_SHIFT;
-
- ret = copy_to_guest(u_sysctl, op, 1) ? -EFAULT : 0;
- }
- break;
+ break;
#ifdef HAS_ACPI
case XEN_SYSCTL_get_pmstat:
- {
ret = xsm_get_pmstat();
if ( ret )
break;
ret = do_get_pm_info(&op->u.get_pmstat);
- if ( ret )
- break;
-
- if ( copy_to_guest(u_sysctl, op, 1) )
- {
- ret = -EFAULT;
- break;
- }
- }
- break;
+ break;
case XEN_SYSCTL_pm_op:
- {
ret = xsm_pm_op();
if ( ret )
break;
ret = do_pm_op(&op->u.pm_op);
- if ( ret && (ret != -EAGAIN) )
- break;
-
- if ( copy_to_guest(u_sysctl, op, 1) )
- {
- ret = -EFAULT;
- break;
- }
- }
- break;
+ if ( ret == -EAGAIN )
+ copyback = 1;
+ break;
#endif
case XEN_SYSCTL_page_offline_op:
@@ -317,41 +272,39 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
}
xfree(status);
+ copyback = 0;
}
break;
case XEN_SYSCTL_cpupool_op:
- {
ret = xsm_cpupool_op();
if ( ret )
break;
ret = cpupool_do_sysctl(&op->u.cpupool_op);
- if ( (ret == 0) && copy_to_guest(u_sysctl, op, 1) )
- ret = -EFAULT;
- }
- break;
+ break;
case XEN_SYSCTL_scheduler_op:
- {
ret = xsm_sched_op();
if ( ret )
break;
ret = sched_adjust_global(&op->u.scheduler_op);
- if ( (ret == 0) && copy_to_guest(u_sysctl, op, 1) )
- ret = -EFAULT;
- }
- break;
+ break;
default:
ret = arch_do_sysctl(op, u_sysctl);
+ copyback = 0;
break;
}
out:
spin_unlock(&sysctl_lock);
+ if ( copyback && (!ret || copyback > 0) &&
+ __copy_to_guest(u_sysctl, op, 1) )
+ ret = -EFAULT;
+
return ret;
}