[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.