Changeset 696817986e68 :
http://xenbits.xensource.com/ext/ppc/linux-2.6.18-xen.hg?cmd=changeset;node=696817986e68
[XEN][LINUX][POWERPC] Implement xencomm translation for ACM hypercalls.
Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>
diffstat:
1 files changed, 143 insertions(+), 3 deletions(-)
arch/powerpc/platforms/xen/hcall.c | 146 +++++++++++++++++++++++++++++++++++-
diffs (172 lines):
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-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|