[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] [XEN][LINUX][POWERPC] Implement xencomm translation for ACM hypercalls.
# HG changeset patch # User Hollis Blanchard <hollisb@xxxxxxxxxx> # Date 1184353290 18000 # Node ID 696817986e686fd410605a4757f36814f294b2ed # Parent 9debaf36090515b4ce54712c4641781bc263b1a6 [XEN][LINUX][POWERPC] Implement xencomm translation for ACM hypercalls. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx> Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> --- arch/powerpc/platforms/xen/hcall.c | 146 ++++++++++++++++++++++++++++++++++++- 1 files changed, 143 insertions(+), 3 deletions(-) diff -r 9debaf360905 -r 696817986e68 arch/powerpc/platforms/xen/hcall.c --- a/arch/powerpc/platforms/xen/hcall.c Fri Jul 13 16:15:37 2007 +0100 +++ b/arch/powerpc/platforms/xen/hcall.c Fri Jul 13 14:01:30 2007 -0500 @@ -34,6 +34,7 @@ #include <xen/interface/event_channel.h> #include <xen/interface/physdev.h> #include <xen/interface/vcpu.h> +#include <xen/interface/acm_ops.h> #include <xen/interface/kexec.h> #include <xen/public/privcmd.h> #include <asm/hypercall.h> @@ -680,6 +681,145 @@ static int xenppc_privcmd_event_channel_ return ret; } +static int xenppc_acmcmd_op(privcmd_hypercall_t *hypercall) +{ + xen_acmctl_t kern_op; + xen_acmctl_t __user *user_op = (xen_acmctl_t __user *)hypercall->arg[0]; + void *op_desc; + void *desc = NULL, *desc2 = NULL, *desc3 = NULL, *desc4 = NULL; + int ret = 0; + + if (copy_from_user(&kern_op, user_op, sizeof(xen_acmctl_t))) + return -EFAULT; + + if (kern_op.interface_version != ACM_INTERFACE_VERSION) { + printk(KERN_WARNING "%s: %s %x != %x\n", __func__, current->comm, + kern_op.interface_version, ACM_INTERFACE_VERSION); + return -EACCES; + } + + op_desc = xencomm_map(&kern_op, sizeof(xen_acmctl_t)); + if (op_desc == NULL) + return -ENOMEM; + + switch (kern_op.cmd) { + case ACMOP_setpolicy: + desc = xencomm_map( + xen_guest_handle(kern_op.u.setpolicy.pushcache), + kern_op.u.setpolicy.pushcache_size); + + if (desc == NULL) + ret = -ENOMEM; + + set_xen_guest_handle(kern_op.u.setpolicy.pushcache, + desc); + break; + case ACMOP_getpolicy: + desc = xencomm_map( + xen_guest_handle(kern_op.u.getpolicy.pullcache), + kern_op.u.getpolicy.pullcache_size); + + if (desc == NULL) + ret = -ENOMEM; + + set_xen_guest_handle(kern_op.u.getpolicy.pullcache, + desc); + break; + case ACMOP_dumpstats: + desc = xencomm_map( + xen_guest_handle(kern_op.u.dumpstats.pullcache), + kern_op.u.dumpstats.pullcache_size); + + if (desc == NULL) + ret = -ENOMEM; + + set_xen_guest_handle(kern_op.u.dumpstats.pullcache, + desc); + break; + case ACMOP_getssid: + desc = xencomm_map( + xen_guest_handle(kern_op.u.getssid.ssidbuf), + kern_op.u.getssid.ssidbuf_size); + + if (desc == NULL) + ret = -ENOMEM; + + set_xen_guest_handle(kern_op.u.getssid.ssidbuf, + desc); + break; + case ACMOP_getdecision: + break; + case ACMOP_chgpolicy: + desc = xencomm_map( + xen_guest_handle(kern_op.u.change_policy.policy_pushcache), + kern_op.u.change_policy.policy_pushcache_size); + desc2 = xencomm_map( + xen_guest_handle(kern_op.u.change_policy.del_array), + kern_op.u.change_policy.delarray_size); + desc3 = xencomm_map( + xen_guest_handle(kern_op.u.change_policy.chg_array), + kern_op.u.change_policy.chgarray_size); + desc4 = xencomm_map( + xen_guest_handle(kern_op.u.change_policy.err_array), + kern_op.u.change_policy.errarray_size); + + if (desc == NULL || desc2 == NULL || + desc3 == NULL || desc4 == NULL) { + ret = -ENOMEM; + goto out; + } + + set_xen_guest_handle(kern_op.u.change_policy.policy_pushcache, + desc); + set_xen_guest_handle(kern_op.u.change_policy.del_array, + desc2); + set_xen_guest_handle(kern_op.u.change_policy.chg_array, + desc3); + set_xen_guest_handle(kern_op.u.change_policy.err_array, + desc4); + break; + case ACMOP_relabeldoms: + desc = xencomm_map( + xen_guest_handle(kern_op.u.relabel_doms.relabel_map), + kern_op.u.relabel_doms.relabel_map_size); + desc2 = xencomm_map( + xen_guest_handle(kern_op.u.relabel_doms.err_array), + kern_op.u.relabel_doms.errarray_size); + + if (desc == NULL || desc2 == NULL) { + ret = -ENOMEM; + goto out; + } + + set_xen_guest_handle(kern_op.u.relabel_doms.relabel_map, + desc); + set_xen_guest_handle(kern_op.u.relabel_doms.err_array, + desc2); + break; + default: + printk(KERN_ERR "%s: unknown/unsupported acmctl cmd %d\n", + __func__, kern_op.cmd); + return -ENOSYS; + } + + if (ret) + goto out; /* error mapping the nested pointer */ + + ret = plpar_hcall_norets(XEN_MARK(hypercall->op),op_desc); + + if (copy_to_user(user_op, &kern_op, sizeof(xen_acmctl_t))) + ret = -EFAULT; + +out: + xencomm_free(desc); + xencomm_free(desc2); + xencomm_free(desc3); + xencomm_free(desc4); + xencomm_free(op_desc); + return ret; +} + + /* The PowerPC hypervisor runs in a separate address space from Linux * kernel/userspace, i.e. real mode. We must therefore translate userspace * pointers to something the hypervisor can make sense of. */ @@ -698,11 +838,11 @@ int privcmd_hypercall(privcmd_hypercall_ return xenppc_privcmd_version(hypercall); case __HYPERVISOR_event_channel_op: return xenppc_privcmd_event_channel_op(hypercall); + case __HYPERVISOR_acm_op: + return xenppc_acmcmd_op(hypercall); default: printk(KERN_ERR "%s: unknown hcall (%ld)\n", __func__, hypercall->op); - /* fallthru */ - /* below are the hcalls we know will fail and its ok */ - case __HYPERVISOR_acm_op: + /* maybe we'll get lucky and the hcall needs no translation. */ return plpar_hcall_norets(XEN_MARK(hypercall->op), hypercall->arg[0], hypercall->arg[1], _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |