First patch to attempt to re introduce older code written by Hollis.

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.

This patch isn't perfect yet. But comments would be nice.
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 10 00:50:24 2007 -0600
@@ -264,7 +264,7 @@ int HYPERVISOR_grant_table_op(unsigned i
 		argsize = sizeof(setup);
 
 		frame_list = xencomm_create_inline(
-			xen_guest_handle(setup.frame_list));
+			xen_guest_handle(setup.frame_list), 0);
 
 		set_xen_guest_handle(setup.frame_list, frame_list);
 		memcpy(op, &setup, sizeof(setup));
@@ -286,7 +286,7 @@ int HYPERVISOR_grant_table_op(unsigned i
 		return -ENOSYS;
 	}
 
-	desc = xencomm_create_inline(op);
+	desc = xencomm_create_inline(op, 0);
 
 	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 10 10:30:08 2007 -0600
@@ -50,11 +50,31 @@
  * In general, we need a xencomm descriptor to cover the top-level data
  * structure (e.g. the domctl op), plus another for every embedded pointer to
  * another data structure (i.e. for every GUEST_HANDLE).
+ * 
+ * Some hypercalls are made before the memory subsystem is up, so instead of
+ * calling xencomm_create(), we allocate XENCOMM_MINI_AREA bytes from the stack
+ * to hold the xencomm descriptor.
  */
 
 int HYPERVISOR_console_io(int cmd, int count, char *str)
 {
-	void *desc = xencomm_create_inline(str);
+	char xc_area[XENCOMM_MINI_AREA];
+	struct xencomm_desc *x_desc;
+	int rc;
+
+	void *desc = xencomm_create_inline(str, count);
+
+	if (desc == NULL) {
+		rc = xencomm_create_mini(xc_area, XENCOMM_MINI_AREA, str, count,
+					&x_desc);
+		if (rc)
+			return rc;
+
+		rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_console_io),
+					cmd, count, __pa(x_desc));
+
+		return rc;
+	}
 
 	return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_console_io),
 				  cmd, count, desc);
@@ -63,7 +83,22 @@ EXPORT_SYMBOL(HYPERVISOR_console_io);
 
 int HYPERVISOR_event_channel_op(int cmd, void *op)
 {
-	void *desc = xencomm_create_inline(op);
+	char xc_area[XENCOMM_MINI_AREA];
+	struct xencomm_desc *x_desc;
+	int rc;
+
+	void *desc = xencomm_create_inline(op, sizeof(evtchn_op_t));
+
+	if (desc == NULL) {
+		rc = xencomm_create_mini(xc_area, XENCOMM_MINI_AREA, 
+					op, sizeof(evtchn_op_t), &x_desc);
+		if (rc)
+			return rc;
+
+		rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_event_channel_op),
+					cmd, __pa(x_desc));
+		return rc;
+	}
 
 	return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_event_channel_op),
 				cmd, desc);
@@ -121,7 +156,7 @@ int HYPERVISOR_xen_version(int cmd, void
 int HYPERVISOR_xen_version(int cmd, void *arg)
 {
 	if (is_kernel_addr((unsigned long)arg)) {
-		void *desc = xencomm_create_inline(arg);
+		void *desc = xencomm_create_inline(arg, 0);
 		return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_xen_version), cmd, desc);
 	}
 	return HYPERVISOR_xen_version_userspace(cmd, arg);
@@ -129,7 +164,7 @@ int HYPERVISOR_xen_version(int cmd, void
 
 int HYPERVISOR_physdev_op(int cmd, void *op)
 {
-	void *desc = xencomm_create_inline(op);
+	void *desc = xencomm_create_inline(op, sizeof(physdev_op_t));
 
 	return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_physdev_op),
 				cmd, desc);
@@ -154,7 +189,7 @@ int HYPERVISOR_sched_op(int cmd, void *a
 		memcpy(&sched_poll, arg, sizeof(sched_poll));
 
 		ports = xencomm_create_inline(
-			xen_guest_handle(sched_poll.ports));
+			xen_guest_handle(sched_poll.ports), 0);
 		set_xen_guest_handle(sched_poll.ports, ports);
 		memcpy(arg, &sched_poll, sizeof(sched_poll));
 		
@@ -168,7 +203,7 @@ int HYPERVISOR_sched_op(int cmd, void *a
 		return -ENOSYS;
 	}
 
-	desc = xencomm_create_inline(arg);
+	desc = xencomm_create_inline(arg, 0);
 
 	return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_sched_op),
 				cmd, desc);
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 10 01:15:50 2007 -0600
@@ -119,13 +119,59 @@ int xencomm_create(void *buffer, unsigne
 	return 0;
 }
 
-void *xencomm_create_inline(void *ptr)
+void *xencomm_create_inline(void *ptr, unsigned long bytes)
 {
 	unsigned long paddr;
-
-	BUG_ON(!is_kernel_addr((unsigned long)ptr));
-
+	unsigned long first;
+	unsigned long last;
+	
+	first = xencomm_vtop(ptr) & PAGE_MASK;
+	last = xencomm_vtop(ptr+bytes) & PAGE_MASK;
+	
+	if (first != last)
+		return NULL;
+	
 	paddr = (unsigned long)xencomm_pa(ptr);
 	BUG_ON(paddr & XENCOMM_INLINE_FLAG);
 	return (void *)(paddr | XENCOMM_INLINE_FLAG);
 }
+
+/* "mini" routines, for stack-based communications: */
+static void *xencomm_alloc_mini(void *area, int arealen)
+{
+	unsigned long base = (unsigned long)area;
+	unsigned int left_in_page;
+
+	left_in_page = PAGE_SIZE - base % PAGE_SIZE;
+
+	/* we probably fit right at the front of area */
+	if (left_in_page >= sizeof(struct xencomm_mini)) {
+		return area;
+	}
+
+	/* if not, see if area is big enough to advance to the next page */
+	if ((arealen - left_in_page) >= sizeof(struct xencomm_mini))
+		return (void *)(base + left_in_page);
+
+	/* area was too small */
+	return NULL;
+}
+
+int xencomm_create_mini(void *area, int arealen, void *buffer,
+		unsigned long bytes, struct xencomm_desc **ret)
+{
+	struct xencomm_desc *desc;
+	int rc;
+	
+	desc = xencomm_alloc_mini(area, arealen);
+	if (!desc)
+		return -ENOMEM;
+	desc->nr_addrs = XENCOMM_MINI_ADDRS;
+
+	rc = xencomm_init(desc, buffer, bytes);
+	if (rc)
+		return rc;
+
+	*ret = desc;
+	return 0;
+}
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	Tue Jan 09 16:07:21 2007 -0600
@@ -23,10 +23,19 @@
 
 #include <xen/interface/xencomm.h>
 
+#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 int xencomm_create(void *buffer, unsigned long bytes,
 			  struct xencomm_desc **desc, gfp_t type);
 extern void xencomm_free(struct xencomm_desc *desc);
-extern void *xencomm_create_inline(void *ptr);
+extern void *xencomm_create_inline(void *ptr, unsigned long bytes);
+extern int xencomm_create_mini(void *area, int arealen, void *buffer,
+			unsigned long bytes, struct xencomm_desc **ret);
 
 /* 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