This patch should address all the issues Jimi has pointed out.

Now has been successfully tested boothing as dom0 & loading VIO modules
with DOMU. 

If a  structure that does not fit within 1 page is pointed to, we need
to create a structure on the stack to represent this structure for the
hypervisor. This code affects kernel module addresses which are do not
have physically contiguous memory.

Signed-off-by: Jerone Young <[EMAIL PROTECTED]>



diff -r bbf2db4ddf54 arch/powerpc/platforms/xen/gnttab.c
--- a/arch/powerpc/platforms/xen/gnttab.c	Tue Dec 19 09:22:37 2006 -0500
+++ b/arch/powerpc/platforms/xen/gnttab.c	Wed Jan 26 01:06:39 2028 -0600
@@ -263,8 +263,10 @@ int HYPERVISOR_grant_table_op(unsigned i
 		memcpy(&setup, op, sizeof(setup));
 		argsize = sizeof(setup);
 
-		frame_list = xencomm_create_inline(
-			xen_guest_handle(setup.frame_list));
+		frame_list = xencomm_map(
+			xen_guest_handle(setup.frame_list),
+			(sizeof(*xen_guest_handle(setup.frame_list)) 
+			* setup.nr_frames));
 
 		set_xen_guest_handle(setup.frame_list, frame_list);
 		memcpy(op, &setup, sizeof(setup));
@@ -286,7 +288,7 @@ int HYPERVISOR_grant_table_op(unsigned i
 		return -ENOSYS;
 	}
 
-	desc = xencomm_create_inline(op);
+	desc = xencomm_map_early(op, argsize);
 
 	ret = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_grant_table_op), cmd,
 				 desc, count);
diff -r bbf2db4ddf54 arch/powerpc/platforms/xen/hcall.c
--- a/arch/powerpc/platforms/xen/hcall.c	Tue Dec 19 09:22:37 2006 -0500
+++ b/arch/powerpc/platforms/xen/hcall.c	Wed Jan 26 02:53:15 2028 -0600
@@ -54,7 +54,7 @@
 
 int HYPERVISOR_console_io(int cmd, int count, char *str)
 {
-	void *desc = xencomm_create_inline(str);
+	void *desc =  xencomm_map_early(str, count); 
 
 	return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_console_io),
 				  cmd, count, desc);
@@ -63,14 +63,14 @@ EXPORT_SYMBOL(HYPERVISOR_console_io);
 
 int HYPERVISOR_event_channel_op(int cmd, void *op)
 {
-	void *desc = xencomm_create_inline(op);
+	void *desc = xencomm_map_early(op, sizeof(evtchn_op_t));
 
 	return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_event_channel_op),
 				cmd, desc);
 }
 EXPORT_SYMBOL(HYPERVISOR_event_channel_op);
 
-int HYPERVISOR_xen_version_userspace(int cmd, void *arg)
+int HYPERVISOR_xen_version(int cmd, void *arg)
 {
 	struct xencomm_desc *desc;
 	const unsigned long hcall = __HYPERVISOR_xen_version;
@@ -107,29 +107,20 @@ int HYPERVISOR_xen_version_userspace(int
 		return -ENOSYS;
 	}
 
-	rc = xencomm_create(arg, argsize, &desc, GFP_KERNEL);
-	if (rc)
-		return rc;
-
-	rc = plpar_hcall_norets(XEN_MARK(hcall), cmd, xencomm_pa(desc));
-
-	xencomm_free(desc);
+	desc = xencomm_map_early(arg, argsize);
+	if (desc == NULL)
+		return -1;
+
+	rc = plpar_hcall_norets(XEN_MARK(hcall), cmd, desc);
+
 	return rc;
 }
 EXPORT_SYMBOL(HYPERVISOR_xen_version);
 
-int HYPERVISOR_xen_version(int cmd, void *arg)
-{
-	if (is_kernel_addr((unsigned long)arg)) {
-		void *desc = xencomm_create_inline(arg);
-		return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_xen_version), cmd, desc);
-	}
-	return HYPERVISOR_xen_version_userspace(cmd, arg);
-}
 
 int HYPERVISOR_physdev_op(int cmd, void *op)
 {
-	void *desc = xencomm_create_inline(op);
+	void *desc = xencomm_map_early(op, sizeof(physdev_op_t)); 
 
 	return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_physdev_op),
 				cmd, desc);
@@ -138,6 +129,7 @@ EXPORT_SYMBOL(HYPERVISOR_physdev_op);
 
 int HYPERVISOR_sched_op(int cmd, void *arg)
 {
+	int argsize = 0;
 	struct xencomm_desc *desc;
 
 	switch (cmd) {
@@ -151,24 +143,30 @@ int HYPERVISOR_sched_op(int cmd, void *a
 		evtchn_port_t *ports;
 		struct sched_poll sched_poll;
 
+		argsize = sizeof(struct sched_poll);
+
 		memcpy(&sched_poll, arg, sizeof(sched_poll));
 
-		ports = xencomm_create_inline(
-			xen_guest_handle(sched_poll.ports));
+		ports = xencomm_map(
+				xen_guest_handle(sched_poll.ports),
+				(sizeof(evtchn_port_t) * sched_poll.nr_ports));
 		set_xen_guest_handle(sched_poll.ports, ports);
 		memcpy(arg, &sched_poll, sizeof(sched_poll));
 		
 	}
 		break;
 	case SCHEDOP_shutdown:
+		argsize = sizeof(struct sched_shutdown);
+		break;
 	case SCHEDOP_remote_shutdown:
+		argsize = sizeof(struct sched_remote_shutdown);
 		break;
 	default:
 		printk(KERN_ERR "%s: unknown sched op %d\n", __func__, cmd);
 		return -ENOSYS;
 	}
 
-	desc = xencomm_create_inline(arg);
+	desc = xencomm_map_early(arg, argsize); 
 
 	return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_sched_op),
 				cmd, desc);
@@ -234,7 +232,7 @@ static int xenppc_privcmd_domctl(privcmd
 	xen_domctl_t kern_op;
 	xen_domctl_t __user *user_op = (xen_domctl_t __user *)hypercall->arg[0];
 	struct xencomm_desc *op_desc;
-	struct xencomm_desc *desc = NULL;
+	void *desc = NULL;
 	int ret = 0;
 
 	if (copy_from_user(&kern_op, user_op, sizeof(xen_domctl_t)))
@@ -246,9 +244,9 @@ static int xenppc_privcmd_domctl(privcmd
 		return -EACCES;
 	}
 
-	ret = xencomm_create(&kern_op, sizeof(xen_domctl_t), &op_desc, GFP_KERNEL);
-	if (ret)
-		return ret;
+	op_desc = xencomm_map(&kern_op, sizeof(xen_domctl_t));
+	if (op_desc)
+		return -1;
 
 	switch (kern_op.cmd) {
 	case XEN_DOMCTL_createdomain:
@@ -258,52 +256,67 @@ static int xenppc_privcmd_domctl(privcmd
 	case XEN_DOMCTL_getdomaininfo:
 		break;
 	case XEN_DOMCTL_getmemlist:
-		ret = xencomm_create(
+		desc = xencomm_map(
 			xen_guest_handle(kern_op.u.getmemlist.buffer),
-			kern_op.u.getmemlist.max_pfns * sizeof(unsigned long),
-			&desc, GFP_KERNEL);
+			kern_op.u.getmemlist.max_pfns * sizeof(unsigned long));
+
+		if (desc == NULL)
+			ret = -1;
+
 		set_xen_guest_handle(kern_op.u.getmemlist.buffer,
-				     xencomm_pa(desc));
+				     desc);
 		break;
 	case XEN_DOMCTL_getpageframeinfo:
 		break;
 	case XEN_DOMCTL_getpageframeinfo2:
-		ret = xencomm_create(
+		desc = xencomm_map(
 			xen_guest_handle(kern_op.u.getpageframeinfo2.array),
-			kern_op.u.getpageframeinfo2.num,
-			&desc, GFP_KERNEL);
+			kern_op.u.getpageframeinfo2.num);
+		
+		if (desc == NULL)
+			ret = -1;
+
 		set_xen_guest_handle(kern_op.u.getpageframeinfo2.array,
-				     xencomm_pa(desc));
+				     desc);
 		break;
 	case XEN_DOMCTL_shadow_op:
-		ret = xencomm_create(
+		desc = xencomm_map(
 			xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap),
-			kern_op.u.shadow_op.pages * sizeof(unsigned long),
-			&desc, GFP_KERNEL);
+			kern_op.u.shadow_op.pages * sizeof(unsigned long));
+	
+		if (desc == NULL)
+			ret = -1;
+
 		set_xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap,
-				     xencomm_pa(desc));
+				     desc);
 		break;
 	case XEN_DOMCTL_max_mem:
 		break;
 	case XEN_DOMCTL_setvcpucontext:
 	case XEN_DOMCTL_getvcpucontext:
-		ret = xencomm_create(
+		desc = xencomm_map(
 			xen_guest_handle(kern_op.u.vcpucontext.ctxt),
-			sizeof(vcpu_guest_context_t),
-			&desc, GFP_KERNEL);
+			sizeof(vcpu_guest_context_t));
+
+		if (desc == NULL)
+			ret = -1;
+
 		set_xen_guest_handle(kern_op.u.vcpucontext.ctxt,
-				     xencomm_pa(desc));
+				     desc);
 		break;
 	case XEN_DOMCTL_getvcpuinfo:
 		break;
 	case XEN_DOMCTL_setvcpuaffinity:
 	case XEN_DOMCTL_getvcpuaffinity:
-		ret = xencomm_create(
+		desc = xencomm_map(
 			xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap),
-			(kern_op.u.vcpuaffinity.cpumap.nr_cpus + 7) / 8,
-			&desc, GFP_KERNEL);
+			(kern_op.u.vcpuaffinity.cpumap.nr_cpus + 7) / 8);
+		
+		if (desc == NULL)
+			ret = -1;
+		
 		set_xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap,
-				     xencomm_pa(desc));
+				     desc);
 		break;
 	case XEN_DOMCTL_max_vcpus:
 	case XEN_DOMCTL_scheduler_op:
@@ -325,7 +338,7 @@ static int xenppc_privcmd_domctl(privcmd
 	if (ret)
 		goto out; /* error mapping the nested pointer */
 
-	ret = plpar_hcall_norets(XEN_MARK(hypercall->op), xencomm_pa(op_desc));
+	ret = plpar_hcall_norets(XEN_MARK(hypercall->op),op_desc);
 
 	if (copy_to_user(user_op, &kern_op, sizeof(xen_domctl_t)))
 		ret = -EFAULT;
@@ -341,7 +354,7 @@ static int xenppc_privcmd_sysctl(privcmd
 	xen_sysctl_t kern_op;
 	xen_sysctl_t __user *user_op = (xen_sysctl_t __user *)hypercall->arg[0];
 	struct xencomm_desc *op_desc;
-	struct xencomm_desc *desc = NULL;
+	void *desc = NULL;
 	int ret = 0;
 
 	if (copy_from_user(&kern_op, user_op, sizeof(xen_sysctl_t)))
@@ -353,18 +366,20 @@ static int xenppc_privcmd_sysctl(privcmd
 		return -EACCES;
 	}
 
-	ret = xencomm_create(&kern_op, sizeof(xen_sysctl_t), &op_desc, GFP_KERNEL);
-	if (ret)
-		return ret;
+	op_desc = xencomm_map(&kern_op, sizeof(xen_sysctl_t));
+	if (op_desc == NULL)
+		return -1;
 
 	switch (kern_op.cmd) {
 	case XEN_SYSCTL_readconsole:
-		ret = xencomm_create(
+		desc = xencomm_map(
 			xen_guest_handle(kern_op.u.readconsole.buffer),
-			kern_op.u.readconsole.count,
-			&desc, GFP_KERNEL);
+			kern_op.u.readconsole.count);
+		if (desc == NULL)
+			ret = -1;
+	
 		set_xen_guest_handle(kern_op.u.readconsole.buffer,
-				     xencomm_pa(desc));
+				     desc);
 		break;
 	case XEN_SYSCTL_tbuf_op:
 	case XEN_SYSCTL_physinfo:
@@ -376,13 +391,16 @@ static int xenppc_privcmd_sysctl(privcmd
 		printk(KERN_ERR "%s: unknown sysctl cmd %d\n", __func__, kern_op.cmd);
 		return -ENOSYS;
 	case XEN_SYSCTL_getdomaininfolist:
-		ret = xencomm_create(
+		desc = xencomm_map(
 			xen_guest_handle(kern_op.u.getdomaininfolist.buffer),
 			kern_op.u.getdomaininfolist.max_domains *
-					sizeof(xen_domctl_getdomaininfo_t),
-			&desc, GFP_KERNEL);
+					sizeof(xen_domctl_getdomaininfo_t));
+
+		if (desc == NULL)
+			ret = -1;
+
 		set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer,
-				     xencomm_pa(desc));
+				     desc);
 		break;
 	default:
 		printk(KERN_ERR "%s: unknown sysctl cmd %d\n", __func__, kern_op.cmd);
@@ -392,7 +410,7 @@ static int xenppc_privcmd_sysctl(privcmd
 	if (ret)
 		goto out; /* error mapping the nested pointer */
 
-	ret = plpar_hcall_norets(XEN_MARK(hypercall->op), xencomm_pa(op_desc));
+	ret = plpar_hcall_norets(XEN_MARK(hypercall->op), op_desc);
 
 	if (copy_to_user(user_op, &kern_op, sizeof(xen_sysctl_t)))
 		ret = -EFAULT;
@@ -421,10 +439,9 @@ static int xenppc_privcmd_platform_op(pr
 		return -EACCES;
 	}
 
-	ret = xencomm_create(&kern_op, sizeof(xen_platform_op_t), &op_desc,
-			GFP_KERNEL);
-	if (ret)
-		return ret;
+	op_desc = xencomm_map(&kern_op, sizeof(xen_platform_op_t));
+	if (op_desc == NULL)
+		return -1;
 
 	switch (kern_op.cmd) {
 	case XENPF_settime:
@@ -443,7 +460,7 @@ static int xenppc_privcmd_platform_op(pr
 	if (ret)
 		goto out; /* error mapping the nested pointer */
 
-	ret = plpar_hcall_norets(XEN_MARK(hypercall->op), xencomm_pa(op_desc));
+	ret = plpar_hcall_norets(XEN_MARK(hypercall->op), op_desc);
 
 	if (copy_to_user(user_op, &kern_op, sizeof(xen_platform_op_t)))
 		ret = -EFAULT;
@@ -462,32 +479,31 @@ int HYPERVISOR_memory_op(unsigned int cm
 
 
 	mop = (xen_memory_reservation_t *)arg;
-	ret = xencomm_create(mop, sizeof(xen_memory_reservation_t),
-			     &op_desc, GFP_KERNEL);
-	if (ret)
-		return ret;
+	op_desc = xencomm_map(mop, sizeof(xen_memory_reservation_t));
+	if (op_desc == NULL)
+		return -1;
 
 	switch (cmd) {
 	case XENMEM_increase_reservation:
 	case XENMEM_decrease_reservation:
 	{
-		struct xencomm_desc *desc = NULL;
+		void *desc = NULL;
 
 		if (xen_guest_handle(mop->extent_start)) {
-			ret = xencomm_create(
+			desc = xencomm_map(
 				xen_guest_handle(mop->extent_start),
 				mop->nr_extents *
-				sizeof(*xen_guest_handle(mop->extent_start)),
-				&desc, GFP_KERNEL);
-			if (ret)
-				return ret;
+				sizeof(*xen_guest_handle(mop->extent_start)));
+
+			if (desc == NULL)
+				return -1;
 
 			set_xen_guest_handle(mop->extent_start,
-					     xencomm_pa(desc));
+					     desc);
 		}
 
 		ret = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_memory_op),
-					 cmd, xencomm_pa(op_desc));
+					 cmd, op_desc);
 
 		xencomm_free(desc);
 	}
@@ -556,12 +572,12 @@ static int xenppc_privcmd_event_channel_
 		return -EINVAL;
 	}
 
-	ret = xencomm_create((void *)hypercall->arg[1], argsize, &desc, GFP_KERNEL);
-	if (ret)
-		return ret;
+	desc = xencomm_map((void *)hypercall->arg[1], argsize);
+	if (desc == NULL)
+		return -1;
 
 	ret = plpar_hcall_norets(XEN_MARK(hypercall->op), hypercall->arg[0],
-			xencomm_pa(desc));
+				desc);
 
 	xencomm_free(desc);
 	return ret;
diff -r bbf2db4ddf54 drivers/xen/core/xencomm.c
--- a/drivers/xen/core/xencomm.c	Tue Dec 19 09:22:37 2006 -0500
+++ b/drivers/xen/core/xencomm.c	Wed Jan 26 02:59:31 2028 -0600
@@ -82,11 +82,11 @@ static struct xencomm_desc *xencomm_allo
 
 void xencomm_free(struct xencomm_desc *desc)
 {
-	if (desc)
+	if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG))
 		free_page((unsigned long)desc);
 }
 
-int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc **ret, gfp_t gfp_mask)
+static int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc **ret, gfp_t gfp_mask)
 {
 	struct xencomm_desc *desc;
 	int rc;
@@ -119,13 +119,68 @@ int xencomm_create(void *buffer, unsigne
 	return 0;
 }
 
-void *xencomm_create_inline(void *ptr)
+static void *xencomm_create_inline(void *ptr)
 {
 	unsigned long paddr;
 
-	BUG_ON(!is_kernel_addr((unsigned long)ptr));
+	BUG_ON(!is_phys_contiguous((unsigned long)ptr));
 
 	paddr = (unsigned long)xencomm_pa(ptr);
 	BUG_ON(paddr & XENCOMM_INLINE_FLAG);
 	return (void *)(paddr | XENCOMM_INLINE_FLAG);
 }
+
+/* "mini" routine, for stack-based communications: */
+static int xencomm_create_mini(int arealen, void *buffer,
+	unsigned long bytes, struct xencomm_desc **ret)
+{
+	struct xencomm_desc desc;
+	int rc = 0;
+
+	desc.nr_addrs = XENCOMM_MINI_ADDRS;
+
+	if (! (rc = xencomm_init(&desc, buffer, bytes)));
+		*ret = &desc;
+
+	return rc;
+}
+
+void *xencomm_map(void *ptr, unsigned long bytes)
+{
+	int rc;
+	struct xencomm_desc *desc;
+
+	if (is_phys_contiguous((unsigned long)ptr))
+		return xencomm_create_inline(ptr);
+
+	rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
+
+	if (rc)
+		return NULL;
+
+	return xencomm_pa(desc); 
+}
+
+void *__xencomm_map_early(void *ptr, unsigned long bytes, 
+			struct xencomm_mini *xc_area)
+{
+	int rc;
+	struct xencomm_desc *desc = NULL;
+
+	if (is_phys_contiguous((unsigned long)ptr))
+		return xencomm_create_inline(ptr);
+
+	rc = xencomm_create_mini(XENCOMM_MINI_AREA,ptr, bytes,
+				&desc);
+
+	if (rc)
+		return NULL;
+ 
+	return (void*)__pa(desc);
+}
+
+/* check if is physically contiguous memory */
+int is_phys_contiguous(unsigned long addr)
+{
+	return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
+}
diff -r bbf2db4ddf54 include/xen/xencomm.h
--- a/include/xen/xencomm.h	Tue Dec 19 09:22:37 2006 -0500
+++ b/include/xen/xencomm.h	Wed Jan 26 02:17:31 2028 -0600
@@ -16,6 +16,7 @@
  * Copyright (C) IBM Corp. 2006
  *
  * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
+ *          Jerone Young <[EMAIL PROTECTED]>
  */
 
 #ifndef _LINUX_XENCOMM_H_
@@ -23,10 +24,23 @@
 
 #include <xen/interface/xencomm.h>
 
-extern int xencomm_create(void *buffer, unsigned long bytes,
-			  struct xencomm_desc **desc, gfp_t type);
+#define XENCOMM_MINI_ADDRS 3
+struct xencomm_mini {
+	struct xencomm_desc _desc;
+	uint64_t address[XENCOMM_MINI_ADDRS];
+};
+#define XENCOMM_MINI_AREA (sizeof(struct xencomm_mini) * 2)
+
 extern void xencomm_free(struct xencomm_desc *desc);
-extern void *xencomm_create_inline(void *ptr);
+extern void *xencomm_map(void *ptr, unsigned long bytes);
+extern void *__xencomm_map_early(void *ptr, unsigned long bytes, 
+				struct xencomm_mini *xc_area);
+extern int is_phys_contiguous(unsigned long addr);
+
+#define xencomm_map_early(ptr, bytes) \
+	({struct xencomm_mini xc_area\
+		__attribute__((__aligned__(sizeof(struct xencomm_mini))));\
+		__xencomm_map_early(ptr, bytes, &xc_area);})
 
 /* provided by architecture code: */
 extern unsigned long xencomm_vtop(unsigned long vaddr);
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to