Hi,
these are the patches to port xencomm on ia64. This is just an RFC. I have
to clean-up the code so that it could be shared between ia64 and ppc.
I have added the xencomm_inline feature which makes (IMHO) hcall.c more
readable and safer (particularly at boot time). Wether or not xencomm_mini
should be deprecated is a question for ppc people (xencomm_mini is buggy: the
area should be reserved as an array of struct xencomm_mini for alignment).
I have also fixed a few bugs in guest_access.h
Many files should be shared between ia64 and ppc.
In xen:
* guest_access.h should be the same. I will propose to put as
include/xen/xencomm_access.h
* usercopy.c sould be shared too. The paddr_to_maddr() function should be
defined in arch files as xencomm_paddr_to_maddr. I will propose to put this
file into xen/common/xencomm.c
In linux:
* drivers/xen/core/xencomm.c should be shared. We just need to agree on
xen_pa(). On linux-ia64, __pa() doesn't work for this use. asm/xencomm.h
should define this macro/function.
* hcall.c should be shared because it is the biggest and the most boring file.
This won't be that easy, but it will try to made a proposal soon.
Tristan.
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/Kconfig
--- a/linux-2.6-xen-sparse/arch/ia64/Kconfig Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig Fri Aug 18 14:26:09 2006 +0200
@@ -530,6 +530,9 @@ config XEN_REBOOT
config XEN_SMPBOOT
default n
+
+config XEN_XENCOMM
+ default y
endif
source "drivers/xen/Kconfig"
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Fri Aug 18 14:26:09 2006 +0200
@@ -433,6 +433,9 @@ setup_arch (char **cmdline_p)
#ifdef CONFIG_XEN
if (is_running_on_xen()) {
+ extern unsigned long kernel_start_pa;
+
+ kernel_start_pa = KERNEL_START - ia64_tpa (KERNEL_START);
setup_xen_features();
/* Register a call for panic conditions. */
notifier_chain_register(&panic_notifier_list, &xen_panic_block);
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/Makefile
--- a/linux-2.6-xen-sparse/arch/ia64/xen/Makefile Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/Makefile Fri Aug 18 14:26:09 2006 +0200
@@ -3,6 +3,6 @@
#
obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o \
- hypervisor.o pci-dma-xen.o util.o
+ hypervisor.o pci-dma-xen.o util.o hcall.o
pci-dma-xen-y := ../../i386/kernel/pci-dma-xen.o
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Fri Aug 18 14:26:09 2006 +0200
@@ -371,8 +371,6 @@ int
int
HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
{
- __u64 va1, va2, pa1, pa2;
-
if (cmd == GNTTABOP_map_grant_ref) {
unsigned int i;
for (i = 0; i < count; i++) {
@@ -380,29 +378,7 @@ HYPERVISOR_grant_table_op(unsigned int c
(struct gnttab_map_grant_ref*)uop + i);
}
}
- va1 = (__u64)uop & PAGE_MASK;
- pa1 = pa2 = 0;
- if ((REGION_NUMBER(va1) == 5) &&
- ((va1 - KERNEL_START) >= KERNEL_TR_PAGE_SIZE)) {
- pa1 = ia64_tpa(va1);
- if (cmd <= GNTTABOP_transfer) {
- static uint32_t uop_size[GNTTABOP_transfer + 1] = {
- sizeof(struct gnttab_map_grant_ref),
- sizeof(struct gnttab_unmap_grant_ref),
- sizeof(struct gnttab_setup_table),
- sizeof(struct gnttab_dump_table),
- sizeof(struct gnttab_transfer),
- };
- va2 = (__u64)uop + (uop_size[cmd] * count) - 1;
- va2 &= PAGE_MASK;
- if (va1 != va2) {
- /* maximum size of uop is 2pages */
- BUG_ON(va2 > va1 + PAGE_SIZE);
- pa2 = ia64_tpa(va2);
- }
- }
- }
- return ____HYPERVISOR_grant_table_op(cmd, uop, count, pa1, pa2);
+ return ____HYPERVISOR_grant_table_op(cmd, uop, count);
}
EXPORT_SYMBOL(HYPERVISOR_grant_table_op);
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/Kconfig
--- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Fri Aug 18 14:26:09 2006 +0200
@@ -257,4 +257,7 @@ config XEN_SMPBOOT
default y
depends on SMP
+config XEN_XENCOMM
+ bool
+ default n
endif
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/core/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile Fri Aug 18 14:26:09 2006 +0200
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SKBUFF) += skbuff.o
obj-$(CONFIG_XEN_SKBUFF) += skbuff.o
obj-$(CONFIG_XEN_REBOOT) += reboot.o
obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o
+obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Aug 18 14:26:09 2006 +0200
@@ -34,6 +34,8 @@
static struct proc_dir_entry *privcmd_intf;
static struct proc_dir_entry *capabilities_intf;
+
+extern int xencomm_privcmd_hypercall(privcmd_hypercall_t *hypercall);
#define NR_HYPERCALLS 64
static DECLARE_BITMAP(hypercall_permission_map, NR_HYPERCALLS);
@@ -92,18 +94,7 @@ static int privcmd_ioctl(struct inode *i
: "r8", "r10", "memory" );
}
#elif defined (__ia64__)
- __asm__ __volatile__ (
- ";; mov r14=%2; mov r15=%3; "
- "mov r16=%4; mov r17=%5; mov r18=%6;"
- "mov r2=%1; break 0x1000;; mov %0=r8 ;;"
- : "=r" (ret)
- : "r" (hypercall.op),
- "r" (hypercall.arg[0]),
- "r" (hypercall.arg[1]),
- "r" (hypercall.arg[2]),
- "r" (hypercall.arg[3]),
- "r" (hypercall.arg[4])
- : "r14","r15","r16","r17","r18","r2","r8","memory");
+ ret = xencomm_privcmd_hypercall (&hypercall);
#endif
}
break;
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Fri Aug 18 14:26:09 2006 +0200
@@ -157,19 +157,13 @@
(type)__res; \
})
-static inline int
-HYPERVISOR_sched_op_compat(
- int cmd, unsigned long arg)
-{
- return _hypercall2(int, sched_op_compat, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_sched_op(
- int cmd, void *arg)
-{
- return _hypercall2(int, sched_op, cmd, arg);
-}
+#if 0
+extern int
+HYPERVISOR_sched_op_compat(int cmd, unsigned long arg);
+#endif
+
+extern int
+HYPERVISOR_sched_op(int cmd, void *arg);
static inline long
HYPERVISOR_set_timer_op(
@@ -180,29 +174,16 @@ HYPERVISOR_set_timer_op(
return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
}
-static inline int
-HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- return _hypercall1(int, dom0_op, dom0_op);
-}
-
-static inline int
-HYPERVISOR_multicall(
- void *call_list, int nr_calls)
-{
- return _hypercall2(int, multicall, call_list, nr_calls);
-}
+extern int
+HYPERVISOR_dom0_op(dom0_op_t *dom0_op);
+
+extern int
+HYPERVISOR_multicall(multicall_entry_t *call_list, int nr_calls);
//XXX xen/ia64 copy_from_guest() is broken.
// This is a temporal work around until it is fixed.
-static inline int
-____HYPERVISOR_memory_op(
- unsigned int cmd, void *arg)
-{
- return _hypercall2(int, memory_op, cmd, arg);
-}
+extern int
+____HYPERVISOR_memory_op(unsigned int cmd, void *arg);
#include <xen/interface/memory.h>
int ia64_xenmem_reservation_op(unsigned long op,
@@ -223,81 +204,33 @@ HYPERVISOR_memory_op(
/* NOTREACHED */
}
-static inline int
-HYPERVISOR_event_channel_op(
- int cmd, void *arg)
-{
- int rc = _hypercall2(int, event_channel_op, cmd, arg);
- if (unlikely(rc == -ENOSYS)) {
- struct evtchn_op op;
- op.cmd = cmd;
- memcpy(&op.u, arg, sizeof(op.u));
- rc = _hypercall1(int, event_channel_op_compat, &op);
- }
- return rc;
-}
-
-static inline int
-HYPERVISOR_acm_op(
- unsigned int cmd, void *arg)
-{
- return _hypercall2(int, acm_op, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_xen_version(
- int cmd, void *arg)
-{
- return _hypercall2(int, xen_version, cmd, arg);
-}
-
-static inline int
-HYPERVISOR_console_io(
- int cmd, int count, char *str)
-{
- return _hypercall3(int, console_io, cmd, count, str);
-}
-
-static inline int
-HYPERVISOR_physdev_op(
- int cmd, void *arg)
-{
- int rc = _hypercall2(int, physdev_op, cmd, arg);
- if (unlikely(rc == -ENOSYS)) {
- struct physdev_op op;
- op.cmd = cmd;
- memcpy(&op.u, arg, sizeof(op.u));
- rc = _hypercall1(int, physdev_op_compat, &op);
- }
- return rc;
-}
+extern int
+HYPERVISOR_event_channel_op(int cmd, void *arg);
+
+extern int
+HYPERVISOR_acm_op(unsigned int cmd, void *arg);
+
+extern int
+HYPERVISOR_xen_version(int cmd, void *arg);
+
+extern int
+HYPERVISOR_console_io(int cmd, int count, char *str);
+
+extern int
+HYPERVISOR_physdev_op(int cmd, void *arg);
//XXX __HYPERVISOR_grant_table_op is used for this hypercall constant.
-static inline int
-____HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count,
- unsigned long pa1, unsigned long pa2)
-{
- return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2);
-}
+extern int
+____HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
+// unsigned long pa1, unsigned long pa2);
int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
-static inline int
-HYPERVISOR_vcpu_op(
- int cmd, int vcpuid, void *extra_args)
-{
- return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
-}
+extern int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
extern int HYPERVISOR_suspend(unsigned long srec);
-static inline int
-HYPERVISOR_callback_op(
- int cmd, void *arg)
-{
- return _hypercall2(int, callback_op, cmd, arg);
-}
+extern int HYPERVISOR_callback_op(int cmd, void *arg);
extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
static inline void exit_idle(void) {}
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Wed Aug 16 14:28:57 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Fri Aug 18 14:26:09 2006 +0200
@@ -70,9 +70,6 @@ HYPERVISOR_yield(
{
int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
- if (rc == -ENOSYS)
- rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
-
return rc;
}
@@ -81,9 +78,6 @@ HYPERVISOR_block(
void)
{
int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
-
- if (rc == -ENOSYS)
- rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
return rc;
}
@@ -97,9 +91,6 @@ HYPERVISOR_shutdown(
};
int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
-
- if (rc == -ENOSYS)
- rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
return rc;
}
@@ -117,8 +108,6 @@ HYPERVISOR_poll(
set_xen_guest_handle(sched_poll.ports, ports);
rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
- if (rc == -ENOSYS)
- rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
return rc;
}
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/arch/ia64/xen/hcall.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hcall.c Fri Aug 18 14:26:09 2006 +0200
@@ -0,0 +1,669 @@
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/dom0_ops.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/xencomm.h>
+#include <xen/interface/version.h>
+#include <xen/interface/sched.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/callback.h>
+#include <xen/interface/acm_ops.h>
+#include <xen/public/privcmd.h>
+#include <asm/hypercall.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <xen/xencomm.h>
+
+#ifdef __ia64__
+extern unsigned long xen_pa(void *ptr);
+#endif
+
+#define xen_guest_handle(hnd) ((hnd).p)
+
+/* Xencomm notes:
+ *
+ * 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.
+ *
+ * In general, we need a xencomm descriptor to cover the top-level data
+ * structure (e.g. the dom0 op), plus another for every embedded pointer to
+ * another data structure (i.e. for every GUEST_HANDLE).
+ */
+
+int HYPERVISOR_console_io(int cmd, int count, char *str)
+{
+ struct xencomm_desc *desc;
+ int rc;
+
+ desc = xencomm_create_inline (str, count);
+
+ rc = _hypercall3(int, console_io, cmd, count, desc);
+
+ return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_console_io);
+
+int HYPERVISOR_event_channel_op(int cmd, void *op)
+{
+ struct xencomm_desc *desc;
+ int rc;
+
+ desc = xencomm_create_inline(op, sizeof(evtchn_op_t));
+
+ rc = _hypercall2(int, event_channel_op, cmd, desc);
+
+ return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_event_channel_op);
+
+int HYPERVISOR_xen_version(int cmd, void *arg)
+{
+ struct xencomm_desc *desc;
+ int argsize;
+ int rc;
+
+ switch (cmd) {
+ case XENVER_version:
+ /* do not actually pass an argument */
+ return _hypercall2(int, xen_version, cmd, 0);
+ case XENVER_extraversion:
+ argsize = sizeof(xen_extraversion_t);
+ break;
+ case XENVER_compile_info:
+ argsize = sizeof(xen_compile_info_t);
+ break;
+ case XENVER_capabilities:
+ argsize = sizeof(xen_capabilities_info_t);
+ break;
+ case XENVER_changeset:
+ argsize = sizeof(xen_changeset_info_t);
+ break;
+ case XENVER_platform_parameters:
+ argsize = sizeof(xen_platform_parameters_t);
+ break;
+ case XENVER_pagesize:
+ argsize = (arg == NULL) ? 0 : sizeof(void *);
+ break;
+ case XENVER_get_features:
+ argsize = (arg == NULL) ? 0 : sizeof(xen_feature_info_t);
+ break;
+ default:
+ printk("%s: unknown version cmd %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_create_inline(arg, argsize);
+
+ rc = _hypercall2(int, xen_version, cmd, desc);
+
+ return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_xen_version);
+
+int HYPERVISOR_physdev_op(int cmd, void *op)
+{
+ struct xencomm_desc *desc;
+ int rc;
+
+ desc = xencomm_create_inline(op, sizeof(physdev_op_t));
+
+ rc = _hypercall2(int, physdev_op, cmd, desc);
+
+ return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_physdev_op);
+
+int ____HYPERVISOR_grant_table_op(unsigned int cmd, void *op,
+ unsigned int count)
+{
+ struct xencomm_desc *desc;
+ struct xencomm_desc *frame_list;
+ long rc;
+ int argsize;
+
+ switch (cmd) {
+ case GNTTABOP_map_grant_ref:
+ argsize = sizeof(struct gnttab_map_grant_ref);
+ break;
+ case GNTTABOP_unmap_grant_ref:
+ argsize = sizeof(struct gnttab_unmap_grant_ref);
+ break;
+ case GNTTABOP_setup_table:
+ {
+ struct gnttab_setup_table *setup = op;
+ argsize = sizeof(struct gnttab_setup_table);
+
+ frame_list = xencomm_create_inline
+ (xen_guest_handle(setup->frame_list),
+ setup->nr_frames
+ * sizeof(*xen_guest_handle(setup->frame_list)));
+
+ set_xen_guest_handle(setup->frame_list, (void *)frame_list);
+ break;
+ }
+ case GNTTABOP_dump_table:
+ argsize = sizeof(struct gnttab_dump_table);
+ break;
+ case GNTTABOP_transfer:
+ argsize = sizeof(struct gnttab_transfer);
+ break;
+ default:
+ printk("%s: unknown grant table op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_create_inline(op, count * argsize);
+
+ rc = _hypercall3(int, grant_table_op, cmd, desc, count);
+
+ return rc;
+}
+/*EXPORT_SYMBOL(HYPERVISOR_grant_table_op);*/
+
+int HYPERVISOR_sched_op(int cmd, void *arg)
+{
+ int rc;
+ struct xencomm_desc *desc;
+ ulong argsize;
+
+ switch (cmd) {
+ case SCHEDOP_yield:
+ case SCHEDOP_block:
+ return _hypercall2(int, sched_op, cmd, 0);
+ break;
+
+ case SCHEDOP_shutdown:
+ argsize = sizeof(sched_shutdown_t);
+ break;
+ case SCHEDOP_poll:
+ argsize = sizeof(sched_poll_t);
+ break;
+ case SCHEDOP_remote_shutdown:
+ argsize = sizeof(sched_remote_shutdown_t);
+ break;
+ default:
+ printk("%s: unknown sched op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_create_inline(arg, argsize);
+
+ rc = _hypercall2(int, sched_op, cmd, desc);
+
+ return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_sched_op);
+
+int HYPERVISOR_multicall(multicall_entry_t *call_list, int nr_calls)
+{
+ int i;
+ multicall_entry_t *mce;
+ struct xencomm_desc *desc;
+
+ for (i = 0; i < nr_calls; i++) {
+ mce = call_list + i;
+
+ switch (mce->op) {
+ case __HYPERVISOR_update_va_mapping:
+ case __HYPERVISOR_mmu_update:
+ /* No-op on ia64. */
+ break;
+ case __HYPERVISOR_memory_op:
+ default:
+ printk("%s: unhandled multicall op entry op %lu from %p\n",
+ __func__, mce->op, __builtin_return_address (0));
+ return -ENOSYS;
+ }
+ }
+
+ desc = xencomm_create_inline
+ (call_list, nr_calls * sizeof(multicall_entry_t));
+
+ return _hypercall2(int, multicall, desc, nr_calls);
+}
+EXPORT_SYMBOL(HYPERVISOR_multicall);
+
+int
+HYPERVISOR_callback_op(
+ int cmd, void *arg)
+{
+ int rc;
+ struct xencomm_desc *desc;
+
+ switch (cmd)
+ {
+ case CALLBACKOP_register:
+ desc = xencomm_create_inline
+ (arg, sizeof(callback_register_t));
+ break;
+ case CALLBACKOP_unregister:
+ desc = xencomm_create_inline
+ (arg, sizeof(callback_unregister_t));
+ break;
+ default:
+ printk("%s: unknown callback op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ rc = _hypercall2(int, callback_op, cmd, desc);
+
+ return rc;
+}
+
+static void xencommize_memory_reservation (xen_memory_reservation_t *mop)
+{
+ if (xen_guest_handle(mop->extent_start)) {
+ struct xencomm_desc *desc;
+ void * addr;
+
+ addr = xen_guest_handle(mop->extent_start);
+ desc = xencomm_create_inline
+ (addr,
+ mop->nr_extents *
+ sizeof(*xen_guest_handle(mop->extent_start)));
+ set_xen_guest_handle(mop->extent_start, (void *)desc);
+ }
+}
+
+int ____HYPERVISOR_memory_op(unsigned int cmd, void *arg)
+{
+ int ret;
+
+ switch (cmd) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ case XENMEM_populate_physmap:
+ {
+ struct xencomm_desc *desc;
+
+ desc = xencomm_create_inline
+ (arg, sizeof(xen_memory_reservation_t));
+
+ xencommize_memory_reservation
+ ((xen_memory_reservation_t *)arg);
+
+ ret = _hypercall2(int, memory_op, cmd, desc);
+ }
+ break;
+
+ case XENMEM_maximum_ram_page:
+ /* arg is NULL so we can call thru here */
+ ret = _hypercall2(int, memory_op, cmd, NULL);
+
+ break;
+
+ case XENMEM_exchange:
+ {
+ struct xencomm_desc *desc;
+
+ desc = xencomm_create_inline
+ (arg, sizeof (xen_memory_exchange_t));
+
+ xencommize_memory_reservation
+ (&((xen_memory_exchange_t *)arg)->in);
+ xencommize_memory_reservation
+ (&((xen_memory_exchange_t *)arg)->out);
+
+ ret = _hypercall2(int, memory_op, cmd, desc);
+ }
+ break;
+
+ default:
+ printk("%s: unknown memory op %d\n", __func__, cmd);
+ ret = -ENOSYS;
+ }
+ return ret;
+
+}
+/* EXPORT_SYMBOL(HYPERVISOR_memory_op);*/
+
+static int xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall)
+{
+ dom0_op_t kern_op;
+ dom0_op_t __user *user_op = (dom0_op_t __user *)hypercall->arg[0];
+ struct xencomm_desc *op_desc;
+ struct xencomm_desc *desc = NULL;
+ int ret = 0;
+
+ if (copy_from_user(&kern_op, user_op, sizeof(dom0_op_t)))
+ return -EFAULT;
+
+ if (kern_op.interface_version != DOM0_INTERFACE_VERSION)
+ return -EACCES;
+
+ op_desc = xencomm_create_inline (&kern_op, sizeof(dom0_op_t));
+
+ switch (kern_op.cmd) {
+ case DOM0_GETMEMLIST:
+ {
+ unsigned long nr_pages = kern_op.u.getmemlist.max_pfns;
+#ifdef __ia64__
+ /* Xen/ia64 pass first_page and nr_pages in max_pfns! */
+ nr_pages &= 0xffffffff;
+#endif
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.getmemlist.buffer),
+ nr_pages * sizeof(unsigned long),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.getmemlist.buffer,
+ (void *)xen_pa(desc));
+ break;
+ }
+ case DOM0_SETVCPUCONTEXT:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.setvcpucontext.ctxt),
+ sizeof(vcpu_guest_context_t),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.setvcpucontext.ctxt,
+ (void *)xen_pa(desc));
+ break;
+ case DOM0_READCONSOLE:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.readconsole.buffer),
+ kern_op.u.readconsole.count,
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.readconsole.buffer,
+ (void *)xen_pa(desc));
+ break;
+ case DOM0_GETPAGEFRAMEINFO2:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.getpageframeinfo2.array),
+ kern_op.u.getpageframeinfo2.num,
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.getpageframeinfo2.array,
+ (void *)xen_pa(desc));
+ break;
+ case DOM0_PERFCCONTROL:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.perfccontrol.desc),
+ kern_op.u.perfccontrol.nr_counters *
+ sizeof(dom0_perfc_desc_t),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.perfccontrol.desc,
+ (void *)xen_pa(desc));
+ break;
+ case DOM0_GETVCPUCONTEXT:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.getvcpucontext.ctxt),
+ sizeof(vcpu_guest_context_t),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.getvcpucontext.ctxt,
+ (void *)xen_pa(desc));
+ break;
+ case DOM0_GETDOMAININFOLIST:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.getdomaininfolist.buffer),
+ kern_op.u.getdomaininfolist.num_domains *
+ sizeof(dom0_getdomaininfo_t),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer,
+ (void *)xen_pa(desc));
+ break;
+ case DOM0_PHYSICAL_MEMORY_MAP:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.physical_memory_map.memory_map),
+ kern_op.u.physical_memory_map.nr_map_entries *
+ sizeof(struct dom0_memory_map_entry),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.physical_memory_map.memory_map,
+ (void *)xen_pa(desc));
+ break;
+
+ case DOM0_SCHEDCTL:
+ case DOM0_ADJUSTDOM:
+ case DOM0_CREATEDOMAIN:
+ case DOM0_DESTROYDOMAIN:
+ case DOM0_PAUSEDOMAIN:
+ case DOM0_UNPAUSEDOMAIN:
+ case DOM0_GETDOMAININFO:
+ case DOM0_MSR:
+ case DOM0_SETTIME:
+ case DOM0_GETPAGEFRAMEINFO:
+ case DOM0_SETVCPUAFFINITY:
+ case DOM0_TBUFCONTROL:
+ case DOM0_PHYSINFO:
+ case DOM0_SCHED_ID:
+ case DOM0_SETDOMAINMAXMEM:
+ case DOM0_ADD_MEMTYPE:
+ case DOM0_DEL_MEMTYPE:
+ case DOM0_READ_MEMTYPE:
+ case DOM0_IOPORT_PERMISSION:
+ case DOM0_GETVCPUINFO:
+ case DOM0_PLATFORM_QUIRK:
+ case DOM0_MAX_VCPUS:
+ case DOM0_SETDOMAINHANDLE:
+ case DOM0_SETDEBUGGING:
+ case DOM0_DOMAIN_SETUP:
+ /* no munging needed */
+ break;
+
+ default:
+ printk("%s: unknown dom0 cmd %d\n", __func__, kern_op.cmd);
+ return -ENOSYS;
+ }
+
+ if (ret)
+ goto out; /* error mapping the nested pointer */
+
+ ret = _hypercall1(int, dom0_op, op_desc);
+
+ /* FIXME: should we restore the handle? */
+ if (copy_to_user(user_op, &kern_op, sizeof(dom0_op_t)))
+ ret = -EFAULT;
+
+ if (desc)
+ xencomm_free(desc);
+out:
+ return ret;
+}
+
+static int xencomm_privcmd_acm_op(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
+ void __user *arg = (void __user *)hypercall->arg[1];
+ struct xencomm_desc *op_desc;
+ struct xencomm_desc *desc = NULL;
+ int ret;
+
+ switch (cmd) {
+ case ACMOP_getssid:
+ {
+ struct acm_getssid kern_arg;
+
+ if (copy_from_user (&kern_arg, arg, sizeof (kern_arg)))
+ return -EFAULT;
+
+ op_desc = xencomm_create_inline (&kern_arg, sizeof(kern_arg));
+
+ ret = xencomm_create(xen_guest_handle(kern_arg.ssidbuf),
+ kern_arg.ssidbuf_size,
+ &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ set_xen_guest_handle(kern_arg.ssidbuf, (void *)xen_pa(desc));
+
+ ret = _hypercall1(int, acm_op, op_desc);
+
+ xencomm_free (desc);
+
+ if (copy_to_user (arg, &kern_arg, sizeof (kern_arg)))
+ return -EFAULT;
+
+ return ret;
+ }
+ default:
+ printk("%s: unknown acm_op cmd %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return ret;
+}
+
+static int xencomm_privcmd_memory_op(privcmd_hypercall_t *hypercall)
+{
+ const unsigned long cmd = hypercall->arg[0];
+ int ret = 0;
+
+ switch (cmd) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ {
+ xen_memory_reservation_t kern_op;
+ xen_memory_reservation_t __user *user_op;
+ struct xencomm_desc *desc = NULL;
+ struct xencomm_desc *desc_op;
+
+ user_op = (xen_memory_reservation_t __user *)hypercall->arg[1];
+ if (copy_from_user(&kern_op, user_op,
+ sizeof(xen_memory_reservation_t)))
+ return -EFAULT;
+ desc_op = xencomm_create_inline (&kern_op, sizeof (kern_op));
+
+ if (xen_guest_handle(kern_op.extent_start)) {
+ void * addr;
+
+ addr = xen_guest_handle(kern_op.extent_start);
+ ret = xencomm_create
+ (addr,
+ kern_op.nr_extents *
+ sizeof(*xen_guest_handle
+ (kern_op.extent_start)),
+ &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+ set_xen_guest_handle(kern_op.extent_start,
+ (void *)xen_pa (desc));
+ }
+
+ ret = _hypercall2(int, memory_op, cmd, desc_op);
+
+ if (desc)
+ xencomm_free (desc);
+
+ if (ret != 0)
+ return ret;
+
+ if (copy_to_user(user_op, &kern_op,
+ sizeof(xen_memory_reservation_t)))
+ return -EFAULT;
+
+ return ret;
+ }
+ default:
+ printk("%s: unknown memory op %lu\n", __func__, cmd);
+ ret = -ENOSYS;
+ }
+ return ret;
+}
+
+static int xencomm_privcmd_version(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
+ void __user *arg = (void __user *)hypercall->arg[1];
+ struct xencomm_desc *desc;
+ size_t argsize;
+ int rc;
+
+ switch (cmd) {
+ case XENVER_version:
+ /* do not actually pass an argument */
+ return _hypercall2(int, xen_version, cmd, 0);
+ case XENVER_extraversion:
+ argsize = sizeof(xen_extraversion_t);
+ break;
+ case XENVER_compile_info:
+ argsize = sizeof(xen_compile_info_t);
+ break;
+ case XENVER_capabilities:
+ argsize = sizeof(xen_capabilities_info_t);
+ break;
+ case XENVER_changeset:
+ argsize = sizeof(xen_changeset_info_t);
+ break;
+ case XENVER_platform_parameters:
+ argsize = sizeof(xen_platform_parameters_t);
+ break;
+ case XENVER_pagesize:
+ argsize = (arg == NULL) ? 0 : sizeof(void *);
+ break;
+ case XENVER_get_features:
+ argsize = (arg == NULL) ? 0 : sizeof(xen_feature_info_t);
+ break;
+
+ default:
+ printk("%s: unknown version op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ rc = xencomm_create(arg, argsize, &desc, GFP_KERNEL);
+ if (rc)
+ return rc;
+
+ rc = _hypercall2(int, xen_version, cmd, xen_pa (desc));
+
+ xencomm_free(desc);
+
+ return rc;
+}
+
+static int xencomm_privcmd_event_channel_op(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
+ struct xencomm_desc *desc;
+ unsigned int argsize;
+ int ret;
+
+ switch (cmd) {
+ case EVTCHNOP_alloc_unbound:
+ argsize = sizeof(evtchn_alloc_unbound_t);
+ break;
+
+ case EVTCHNOP_status:
+ argsize = sizeof(evtchn_status_t);
+ break;
+
+ default:
+ printk("%s: unknown EVTCHNOP %d\n", __func__, cmd);
+ return -EINVAL;
+ }
+
+ ret = xencomm_create((void *)hypercall->arg[1], argsize,
+ &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ ret = _hypercall2(int, event_channel_op, cmd, xen_pa (desc));
+
+ xencomm_free(desc);
+ return ret;
+}
+
+int xencomm_privcmd_hypercall(privcmd_hypercall_t *hypercall)
+{
+ switch (hypercall->op) {
+ case __HYPERVISOR_dom0_op:
+ return xencomm_privcmd_dom0_op(hypercall);
+ case __HYPERVISOR_acm_op:
+ return xencomm_privcmd_acm_op(hypercall);
+ case __HYPERVISOR_xen_version:
+ return xencomm_privcmd_version(hypercall);
+ case __HYPERVISOR_memory_op:
+ return xencomm_privcmd_memory_op(hypercall);
+ case __HYPERVISOR_event_channel_op:
+ return xencomm_privcmd_event_channel_op(hypercall);
+ default:
+ printk("%s: unknown hcall (%ld)\n", __func__, hypercall->op);
+ return -ENOSYS;
+ /* fallthru */
+ /* below are the hcalls we know will fail and its ok */
+ }
+}
+
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/drivers/xen/core/xencomm.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/core/xencomm.c Fri Aug 18 14:26:09 2006 +0200
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <[EMAIL PROTECTED]>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <xen/xencomm.h>
+
+int xencomm_debug;
+
+#ifdef __ia64__
+unsigned long kernel_start_pa;
+
+unsigned long xen_pa(void *ptr)
+{
+ unsigned long addr = (unsigned long)ptr;
+
+ if (addr >= KERNEL_START
+ && addr < (KERNEL_START + KERNEL_TR_PAGE_SIZE))
+ return addr - kernel_start_pa;
+ else
+ return __pa(addr);
+}
+#else
+#define xen_pa(addr) __pa(addr)
+#endif
+
+/* translate virtual address to physical address */
+static unsigned long __vaddr_to_paddr(unsigned long vaddr)
+{
+ struct page *page;
+ struct vm_area_struct *vma;
+
+ if (vaddr > TASK_SIZE) {
+ /* kernel address */
+ return xen_pa((void *)vaddr);
+ }
+
+ /* XXX double-check (lack of) locking */
+ vma = find_extend_vma(current->mm, vaddr);
+ if (!vma)
+ return ~0UL;
+
+ page = follow_page(vma, vaddr, 0);
+ if (!page)
+ return ~0UL;
+
+ return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
+}
+
+/* for use with kernel buffers before __vaddr_to_paddr works (e.g. boot
+ * console) */
+static unsigned long __kern_paddr(unsigned long vaddr)
+{
+ return xen_pa((void *)vaddr);
+}
+
+static int __xencomm_init(struct xencomm_desc *desc, void *buffer,
+ unsigned long bytes, unsigned long (*to_phys)(unsigned long))
+{
+ unsigned long recorded = 0;
+ int i = 0;
+
+ BUG_ON((buffer == NULL) && (bytes > 0));
+
+ /* record the physical pages used */
+ if (buffer == NULL)
+ desc->nr_addrs = 0;
+
+ while ((recorded < bytes) && (i < desc->nr_addrs)) {
+ unsigned long vaddr = (unsigned long)buffer + recorded;
+ unsigned long paddr;
+ int offset;
+ int chunksz;
+
+ offset = vaddr % PAGE_SIZE; /* handle partial pages */
+ chunksz = min(PAGE_SIZE - offset, bytes - recorded);
+
+ paddr = to_phys(vaddr);
+ if (paddr == ~0UL) {
+ printk("%s: couldn't translate vaddr %lx\n",
+ __func__, vaddr);
+ return -EINVAL;
+ }
+
+ desc->address[i++] = paddr;
+ recorded += chunksz;
+ }
+
+ if (recorded < bytes) {
+ printk("%s: could only translate %ld of %ld bytes\n",
+ __func__, recorded, bytes);
+ return -ENOSPC;
+ }
+
+ /* mark remaining addresses invalid (just for safety) */
+ while (i < desc->nr_addrs)
+ desc->address[i++] = XENCOMM_INVALID;
+
+ desc->magic = XENCOMM_MAGIC;
+
+ return 0;
+}
+
+/* XXX use slab allocator */
+static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask)
+{
+ struct xencomm_desc *desc;
+
+ /* XXX could we call this from irq context? */
+ desc = (struct xencomm_desc *)__get_free_page(gfp_mask);
+ if (desc == NULL)
+ return NULL;
+ desc->nr_addrs = (PAGE_SIZE - sizeof(struct xencomm_desc)) /
+ sizeof(*desc->address);
+
+ return desc;
+}
+
+void xencomm_free(struct xencomm_desc *desc)
+{
+ if (desc)
+ free_page((unsigned long)desc);
+}
+
+int xencomm_create(void *buffer, unsigned long bytes, struct xencomm_desc **ret, gfp_t gfp_mask)
+{
+ struct xencomm_desc *desc;
+ int rc;
+
+ if (xencomm_debug) {
+ if ((!buffer) || (bytes == 0)) {
+ printk(KERN_ERR "%s: NULL buffer\n", __func__);
+ return 0;
+ }
+ printk("%s: %p[%ld]\n", __func__, buffer, bytes);
+ }
+
+ if (buffer == NULL || bytes == 0) {
+ *ret = NULL;
+ return 0;
+ }
+
+ desc = xencomm_alloc(gfp_mask);
+ if (!desc) {
+ printk("%s failure from %p\n", "xencomm_alloc",
+ __builtin_return_address (0));
+ return -ENOMEM;
+ }
+
+ rc = __xencomm_init(desc, buffer, bytes, __vaddr_to_paddr);
+ if (rc) {
+ printk("%s failure: %d\n", "__xencomm_init", rc);
+ xencomm_free(desc);
+ return rc;
+ }
+
+ *ret = desc;
+ return 0;
+}
+
+/* "mini" routines, for stack-based communications: */
+
+static void *__xencomm_alloc_mini(void *area, int arealen)
+{
+ unsigned long base = (unsigned long)area;
+ unsigned int pageoffset;
+
+ pageoffset = base % PAGE_SIZE;
+
+ /* we probably fit right at the front of area */
+ if ((PAGE_SIZE - pageoffset) >= sizeof(struct xencomm_mini)) {
+ return area;
+ }
+
+ /* if not, see if area is big enough to advance to the next page */
+ if ((arealen - pageoffset) >= sizeof(struct xencomm_mini))
+ return (void *)(base + pageoffset);
+
+ /* 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, __kern_paddr);
+ if (rc)
+ return rc;
+
+ *ret = desc;
+ return 0;
+}
+
+struct xencomm_desc *xencomm_create_inline (void *buffer, unsigned long bytes)
+{
+ return (struct xencomm_desc *)
+ (__kern_paddr((unsigned long)buffer) | XENCOMM_INLINE);
+}
diff -r 8c6bb45901e7 linux-2.6-xen-sparse/include/xen/xencomm.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/include/xen/xencomm.h Fri Aug 18 14:26:09 2006 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <[EMAIL PROTECTED]>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINUX_XENCOMM_H_
+#define _LINUX_XENCOMM_H_
+
+#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 int xencomm_create_mini(void *area, int arealen, void *buffer,
+ unsigned long bytes, struct xencomm_desc **ret);
+struct xencomm_desc *xencomm_create_inline (void *buffer, unsigned long bytes);
+
+#endif /* _LINUX_XENCOMM_H_ */
diff -r 8c6bb45901e7 xen/arch/ia64/xen/Makefile
--- a/xen/arch/ia64/xen/Makefile Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/arch/ia64/xen/Makefile Fri Aug 18 14:26:09 2006 +0200
@@ -25,5 +25,6 @@ obj-y += xentime.o
obj-y += xentime.o
obj-y += flushd.o
obj-y += privop_stat.o
+obj-y += usercopy.o
obj-$(crash_debug) += gdbstub.o
diff -r 8c6bb45901e7 xen/arch/ia64/xen/faults.c
--- a/xen/arch/ia64/xen/faults.c Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/arch/ia64/xen/faults.c Fri Aug 18 14:26:09 2006 +0200
@@ -225,10 +228,10 @@ void ia64_do_page_fault (unsigned long a
// indicate a bad xen pointer
printk("*** xen_handle_domain_access: exception table"
" lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
- iip, address);
+ iip, address);
panic_domain(regs,"*** xen_handle_domain_access: exception table"
- " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
- iip, address);
+ " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
+ iip, address);
}
return;
}
diff -r 8c6bb45901e7 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/arch/ia64/xen/hypercall.c Fri Aug 18 14:26:09 2006 +0200
@@ -29,7 +30,6 @@
#include <public/callback.h>
#include <xen/event.h>
-static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop);
static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg);
static long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg);
@@ -51,10 +51,10 @@ const hypercall_t ia64_hypercall_table[N
(hypercall_t)do_multicall,
(hypercall_t)do_ni_hypercall, /* do_update_va_mapping */
(hypercall_t)do_ni_hypercall, /* do_set_timer_op */ /* 15 */
- (hypercall_t)do_event_channel_op_compat,
+ (hypercall_t)do_ni_hypercall,
(hypercall_t)do_xen_version,
(hypercall_t)do_console_io,
- (hypercall_t)do_physdev_op_compat,
+ (hypercall_t)do_ni_hypercall,
(hypercall_t)do_grant_table_op, /* 20 */
(hypercall_t)do_ni_hypercall, /* do_vm_assist */
(hypercall_t)do_ni_hypercall, /* do_update_va_mapping_othe */
@@ -105,19 +105,6 @@ xen_hypercall (struct pt_regs *regs)
xen_hypercall (struct pt_regs *regs)
{
uint32_t cmd = (uint32_t)regs->r2;
- struct vcpu *v = current;
-
- if (cmd == __HYPERVISOR_grant_table_op) {
- XEN_GUEST_HANDLE(void) uop;
-
- v->arch.hypercall_param.va = regs->r15;
- v->arch.hypercall_param.pa1 = regs->r17;
- v->arch.hypercall_param.pa2 = regs->r18;
- set_xen_guest_handle(uop, (void *)regs->r15);
- regs->r8 = do_grant_table_op(regs->r14, uop, regs->r16);
- v->arch.hypercall_param.va = 0;
- return IA64_NO_FAULT;
- }
if (cmd < NR_hypercalls) {
perfc_incra(hypercalls, cmd);
@@ -130,7 +117,7 @@ xen_hypercall (struct pt_regs *regs)
regs->r19);
} else
regs->r8 = -ENOSYS;
-
+
return IA64_NO_FAULT;
}
@@ -456,28 +443,6 @@ static long do_physdev_op(int cmd, XEN_G
return ret;
}
-/* Legacy hypercall (as of 0x00030202). */
-static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop)
-{
- struct physdev_op op;
-
- if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
- return -EFAULT;
-
- return do_physdev_op(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
-}
-
-/* Legacy hypercall (as of 0x00030202). */
-long do_event_channel_op_compat(XEN_GUEST_HANDLE(evtchn_op_t) uop)
-{
- struct evtchn_op op;
-
- if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
- return -EFAULT;
-
- return do_event_channel_op(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
-}
-
static long register_guest_callback(struct callback_register *reg)
{
long ret = 0;
diff -r 8c6bb45901e7 xen/include/asm-ia64/guest_access.h
--- a/xen/include/asm-ia64/guest_access.h Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/include/asm-ia64/guest_access.h Fri Aug 18 14:26:09 2006 +0200
@@ -1,91 +1,103 @@
-/******************************************************************************
- * guest_access.h
- *
- * Copyright (c) 2006, K A Fraser
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
*/
-#ifndef __ASM_IA64_GUEST_ACCESS_H__
-#define __ASM_IA64_GUEST_ACCESS_H__
+#ifndef __ASM_GUEST_ACCESS_H__
+#define __ASM_GUEST_ACCESS_H__
-#include <asm/uaccess.h>
+extern unsigned long xencomm_copy_to_guest(void *to, const void *from,
+ unsigned int len, unsigned int skip);
+extern unsigned long xencomm_copy_from_guest(void *to, const void *from,
+ unsigned int len, unsigned int skip);
+extern void *xencomm_add_offset(void *handle, unsigned int bytes);
+extern int xencomm_handle_is_null(void *ptr);
+
/* Is the guest handle a NULL reference? */
-#define guest_handle_is_null(hnd) ((hnd).p == NULL)
+#define guest_handle_is_null(hnd) \
+ ((hnd).p == NULL || xencomm_handle_is_null((hnd).p))
/* Offset the given guest handle into the array it refers to. */
-#define guest_handle_add_offset(hnd, nr) ((hnd).p += (nr))
+#define guest_handle_add_offset(hnd, nr) ({ \
+ const typeof((hnd).p) _ptr = (hnd).p; \
+ (hnd).p = xencomm_add_offset(_ptr, nr * sizeof(*_ptr)); \
+})
/* Cast a guest handle to the specified type of handle. */
#define guest_handle_cast(hnd, type) ({ \
type *_x = (hnd).p; \
- (XEN_GUEST_HANDLE(type)) { _x }; \
+ XEN_GUEST_HANDLE(type) _y; \
+ set_xen_guest_handle(_y, _x); \
+ _y; \
})
-#define guest_handle_from_ptr(ptr, type) ((XEN_GUEST_HANDLE(type)) { (type *)ptr })
+
+/* Since we run in real mode, we can safely access all addresses. That also
+ * means our __routines are identical to our "normal" routines. */
+#define guest_handle_okay(hnd, nr) 1
/*
- * Copy an array of objects to guest context via a guest handle,
- * specifying an offset into the guest array.
+ * Copy an array of objects to guest context via a guest handle.
+ * Optionally specify an offset into the guest array.
*/
-#define copy_to_guest_offset(hnd, off, ptr, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
- copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \
+#define copy_to_guest_offset(hnd, idx, ptr, nr) \
+ __copy_to_guest_offset(hnd, idx, ptr, nr)
+
+/* Copy sub-field of a structure to guest context via a guest handle. */
+#define copy_field_to_guest(hnd, ptr, field) \
+ __copy_field_to_guest(hnd, ptr, field)
+
+/*
+ * Copy an array of objects from guest context via a guest handle.
+ * Optionally specify an offset into the guest array.
+ */
+#define copy_from_guest_offset(ptr, hnd, idx, nr) \
+ __copy_from_guest_offset(ptr, hnd, idx, nr)
+
+/* Copy sub-field of a structure from guest context via a guest handle. */
+#define copy_field_from_guest(ptr, hnd, field) \
+ __copy_field_from_guest(ptr, hnd, field)
+
+#define __copy_to_guest_offset(hnd, idx, ptr, nr) ({ \
+ const typeof(ptr) _d = (hnd).p; \
+ const typeof(ptr) _s = (ptr); \
+ xencomm_copy_to_guest(_d, _s, sizeof(*_s)*(nr), sizeof(*_s)*(idx)); \
})
-/*
- * Copy an array of objects from guest context via a guest handle,
- * specifying an offset into the guest array.
- */
-#define copy_from_guest_offset(ptr, hnd, off, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
- copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \
+#define __copy_field_to_guest(hnd, ptr, field) ({ \
+ const int _off = offsetof(typeof(*ptr), field); \
+ const typeof(ptr) _d = (hnd).p; \
+ const typeof(&(ptr)->field) _s = &(ptr)->field; \
+ xencomm_copy_to_guest(_d, _s, sizeof(*_s), _off); \
})
-/* Copy sub-field of a structure to guest context via a guest handle. */
-#define copy_field_to_guest(hnd, ptr, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
- copy_to_user(_x, _y, sizeof(*_x)); \
+#define __copy_from_guest_offset(ptr, hnd, idx, nr) ({ \
+ const typeof(ptr) _s = (hnd).p; \
+ const typeof(ptr) _d = (ptr); \
+ xencomm_copy_from_guest(_d, _s, sizeof(*_s)*(nr), sizeof(*_s)*(idx)); \
})
-/* Copy sub-field of a structure from guest context via a guest handle. */
-#define copy_field_from_guest(ptr, hnd, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
- copy_from_user(_y, _x, sizeof(*_x)); \
+#define __copy_field_from_guest(ptr, hnd, field) ({ \
+ const int _off = offsetof(typeof(*ptr), field); \
+ const typeof(ptr) _s = (hnd).p; \
+ const typeof(&(ptr)->field) _d = &(ptr)->field; \
+ xencomm_copy_from_guest(_d, _s, sizeof(*_d), _off); \
})
-/*
- * Pre-validate a guest handle.
- * Allows use of faster __copy_* functions.
- */
-#define guest_handle_okay(hnd, nr) \
- array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))
-
-#define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
- __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \
-})
-
-#define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
- __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \
-})
-
-#define __copy_field_to_guest(hnd, ptr, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
- __copy_to_user(_x, _y, sizeof(*_x)); \
-})
-
-#define __copy_field_from_guest(ptr, hnd, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
- __copy_from_user(_y, _x, sizeof(*_x)); \
-})
-
-#endif /* __ASM_IA64_GUEST_ACCESS_H__ */
+#endif /* __ASM_GUEST_ACCESS_H__ */
diff -r 8c6bb45901e7 xen/include/public/xencomm.h
--- a/xen/include/public/xencomm.h Wed Aug 16 14:28:57 2006 -0600
+++ b/xen/include/public/xencomm.h Fri Aug 18 14:26:09 2006 +0200
@@ -34,4 +34,10 @@ struct xencomm_desc {
uint64_t address[0];
};
+/* If the inline flag is set, the descriptor is simply the physical address
+ of the buffer which is known to be contiguous in physical memory.
+ Because the kernels are often 1:1 mapped, this is interesting for kernel
+ issued hypercalls. */
+#define XENCOMM_INLINE (1UL << 63)
+
#endif /* _XEN_XENCOMM_H_ */
diff -r 8c6bb45901e7 xen/arch/ia64/xen/usercopy.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ia64/xen/usercopy.c Fri Aug 18 14:26:09 2006 +0200
@@ -0,0 +1,303 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <[EMAIL PROTECTED]>
+ */
+
+#include <xen/config.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <asm/current.h>
+#include <asm/guest_access.h>
+#include <public/xen.h>
+#include <public/xencomm.h>
+
+#undef DEBUG
+#ifdef DEBUG
+static int xencomm_debug = 1; /* extremely verbose */
+#else
+#define xencomm_debug 0
+#endif
+
+/* XXX need to return error, not panic, if domain passed a bad pointer */
+static unsigned long paddr_to_maddr(unsigned long paddr)
+{
+ struct vcpu *v = current;
+ struct domain *d = v->domain;
+ u64 pa;
+
+ pa = ____lookup_domain_mpa (d, paddr);
+ if (pa == INVALID_MFN)
+ panic_domain(NULL,
+ "%s: called with bad memory address type: 0x%lx\n",
+ __func__, paddr);
+ return __va_ul ((pa & _PFN_MASK) | (paddr & ~PAGE_MASK));
+}
+
+/**
+ * xencomm_copy_from_guest: Copy a block of data from domain space.
+ * @to: Machine address.
+ * @from: Physical address to a xencomm buffer descriptor.
+ * @n: Number of bytes to copy.
+ * @skip: Number of bytes from the start to skip.
+ *
+ * Copy data from domain to hypervisor.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long
+xencomm_copy_from_guest(void *to, const void *from, unsigned int n,
+ unsigned int skip)
+{
+ struct xencomm_desc *desc;
+ unsigned int from_pos = 0;
+ unsigned int to_pos = 0;
+ unsigned int i = 0;
+
+ if (xencomm_debug)
+ printf ("xencomm_copy_from_guest: from=%lx+%u n=%u\n",
+ (unsigned long)from, skip, n);
+
+ if ((unsigned long)from & XENCOMM_INLINE) {
+ unsigned long src_paddr = (unsigned long)from & ~XENCOMM_INLINE;
+
+ src_paddr += skip;
+
+ while (n > 0) {
+ unsigned int chunksz;
+ unsigned long src_maddr;
+ unsigned int bytes;
+
+ chunksz = PAGE_SIZE - (src_paddr % PAGE_SIZE);
+
+ bytes = min(chunksz, n);
+
+ src_maddr = paddr_to_maddr(src_paddr);
+ if (xencomm_debug > 1)
+ printk("%lx[%d] -> %lx\n",
+ src_maddr, bytes, (unsigned long)to);
+ memcpy(to, (void *)src_maddr, bytes);
+ src_paddr += bytes;
+ to += bytes;
+ n -= bytes;
+ }
+
+ /* Always successful. */
+ return 0;
+ }
+
+ /* first we need to access the descriptor */
+ desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)from);
+ if (desc->magic != XENCOMM_MAGIC) {
+ printk("%s: error: %p magic was 0x%x\n",
+ __func__, desc, desc->magic);
+ return n;
+ }
+
+ /* iterate through the descriptor, copying up to a page at a time */
+ while ((to_pos < n) && (i < desc->nr_addrs)) {
+ unsigned long src_paddr = desc->address[i];
+ unsigned int pgoffset;
+ unsigned int chunksz;
+ unsigned int chunk_skip;
+
+ if (src_paddr == XENCOMM_INVALID) {
+ i++;
+ continue;
+ }
+
+ pgoffset = src_paddr % PAGE_SIZE;
+ chunksz = PAGE_SIZE - pgoffset;
+
+ chunk_skip = min(chunksz, skip);
+ from_pos += chunk_skip;
+ chunksz -= chunk_skip;
+ skip -= chunk_skip;
+
+ if (skip == 0) {
+ unsigned long src_maddr;
+ unsigned long dest = (unsigned long)to + to_pos;
+ unsigned int bytes = min(chunksz, n - to_pos);
+
+ if (xencomm_debug > 1)
+ printf ("src_paddr=%lx i=%d, skip=%d\n",
+ src_paddr, i, chunk_skip);
+ src_maddr = paddr_to_maddr(src_paddr + chunk_skip);
+ if (xencomm_debug > 1)
+ printk("%lx[%d] -> %lx\n", src_maddr, bytes, dest);
+ memcpy((void *)dest, (void *)src_maddr, bytes);
+ from_pos += bytes;
+ to_pos += bytes;
+ }
+
+ i++;
+ }
+
+ return n - to_pos;
+}
+
+/**
+ * xencomm_copy_to_guest: Copy a block of data to domain space.
+ * @to: Physical address to xencomm buffer descriptor.
+ * @from: Machine address.
+ * @n: Number of bytes to copy.
+ * @skip: Number of bytes from the start to skip.
+ *
+ * Copy data from hypervisor to domain.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long
+xencomm_copy_to_guest(void *to, const void *from, unsigned int n,
+ unsigned int skip)
+{
+ struct xencomm_desc *desc;
+ unsigned int from_pos = 0;
+ unsigned int to_pos = 0;
+ unsigned int i = 0;
+
+ if (xencomm_debug)
+ printf ("xencomm_copy_to_guest: to=%lx+%u n=%u\n",
+ (unsigned long)to, skip, n);
+
+ if ((unsigned long)to & XENCOMM_INLINE) {
+ unsigned long dest_paddr = (unsigned long)to & ~XENCOMM_INLINE;
+
+ dest_paddr += skip;
+
+ while (n > 0) {
+ unsigned int chunksz;
+ unsigned long dest_maddr;
+ unsigned int bytes;
+
+ chunksz = PAGE_SIZE - (dest_paddr % PAGE_SIZE);
+
+ bytes = min(chunksz, n);
+
+ dest_maddr = paddr_to_maddr(dest_paddr);
+ if (xencomm_debug > 1)
+ printk("%lx[%d] -> %lx\n",
+ (unsigned long)from, bytes, dest_maddr);
+ memcpy((void *)dest_maddr, (void *)from, bytes);
+ dest_paddr += bytes;
+ from += bytes;
+ n -= bytes;
+ }
+
+ /* Always successful. */
+ return 0;
+ }
+
+ /* first we need to access the descriptor */
+ desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)to);
+ if (desc->magic != XENCOMM_MAGIC) {
+ printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+ return n;
+ }
+
+ /* iterate through the descriptor, copying up to a page at a time */
+ while ((from_pos < n) && (i < desc->nr_addrs)) {
+ unsigned long dest_paddr = desc->address[i];
+ unsigned int pgoffset;
+ unsigned int chunksz;
+ unsigned int chunk_skip;
+
+ if (dest_paddr == XENCOMM_INVALID) {
+ i++;
+ continue;
+ }
+
+ pgoffset = dest_paddr % PAGE_SIZE;
+ chunksz = PAGE_SIZE - pgoffset;
+
+ chunk_skip = min(chunksz, skip);
+ to_pos += chunk_skip;
+ chunksz -= chunk_skip;
+ skip -= chunk_skip;
+
+ if (skip == 0) {
+ unsigned long dest_maddr;
+ unsigned long source = (unsigned long)from + from_pos;
+ unsigned int bytes = min(chunksz, n - from_pos);
+
+ dest_maddr = paddr_to_maddr(dest_paddr + chunk_skip);
+ if (xencomm_debug > 1)
+ printk("%lx[%d] -> %lx\n", source, bytes, dest_maddr);
+ memcpy((void *)dest_maddr, (void *)source, bytes);
+ from_pos += bytes;
+ to_pos += bytes;
+ }
+
+ i++;
+ }
+
+ return n - from_pos;
+}
+
+/* Offset page addresses in 'handle' to skip 'bytes' bytes. Set completely
+ * exhausted pages to XENCOMM_INVALID. */
+void *xencomm_add_offset(void *handle, unsigned int bytes)
+{
+ struct xencomm_desc *desc;
+ int i = 0;
+
+ if ((unsigned long)handle & XENCOMM_INLINE) {
+ return (void *)((unsigned long)handle + bytes);
+ }
+
+ /* first we need to access the descriptor */
+ desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)handle);
+ if (desc->magic != XENCOMM_MAGIC) {
+ printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+ return NULL;
+ }
+
+ /* iterate through the descriptor incrementing addresses */
+ while ((bytes > 0) && (i < desc->nr_addrs)) {
+ unsigned long dest_paddr = desc->address[i];
+ unsigned int pgoffset;
+ unsigned int chunksz;
+ unsigned int chunk_skip;
+
+ pgoffset = dest_paddr % PAGE_SIZE;
+ chunksz = PAGE_SIZE - pgoffset;
+
+ chunk_skip = min(chunksz, bytes);
+ if (chunk_skip == chunksz) {
+ /* exhausted this page */
+ desc->address[i] = XENCOMM_INVALID;
+ } else {
+ desc->address[i] += chunk_skip;
+ }
+ bytes -= chunk_skip;
+ }
+ return handle;
+}
+
+int xencomm_handle_is_null(void *ptr)
+{
+ struct xencomm_desc *desc;
+
+ if ((unsigned long)ptr & XENCOMM_INLINE)
+ return (unsigned long)ptr == XENCOMM_INLINE;
+ else {
+ desc = (struct xencomm_desc *)paddr_to_maddr((unsigned long)ptr);
+ return (desc->address[0] == XENCOMM_INVALID);
+ }
+}
_______________________________________________
Xen-ppc-devel mailing list
[email protected]
http://lists.xensource.com/xen-ppc-devel