aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@xensource.com>2007-05-30 11:55:38 +0100
committerIan Campbell <ian.campbell@xensource.com>2007-05-30 11:55:38 +0100
commitca938d8cc6d30f0c99e631e6fb050ce1c921ab08 (patch)
tree9d56aebbd52486d1042ef8d64c28ab3e5749b071
parent96469475a6848763fd542d1305660ee7a8561569 (diff)
downloadxen-ca938d8cc6d30f0c99e631e6fb050ce1c921ab08.tar.gz
xen-ca938d8cc6d30f0c99e631e6fb050ce1c921ab08.tar.bz2
xen-ca938d8cc6d30f0c99e631e6fb050ce1c921ab08.zip
Fix preemption of multicalls in compat mode.
mcs->call (struct multicall_entry) always needs to be translated into mcs->compat_call (struct compat_multicall_entry) when a multicall is preempted in compat mode. Previously this translation only occured for those hypercalls which explicitly called hypercall_xlat_continuation() which doesn't cover all hypercalls which could potentially be preempted. Change hypercall_xlat_continuation() to only translate only the hypercall arguments themselves and not the multicall_entry layout. Translate the layout for all hypercalls in in compat_multicall() instead. Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
-rw-r--r--xen/arch/x86/domain.c9
-rw-r--r--xen/common/compat/multicall.c7
-rw-r--r--xen/common/multicall.c4
3 files changed, 15 insertions, 5 deletions
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 281ae7b793..085e90d4da 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1456,13 +1456,12 @@ int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
id = NULL;
}
if ( (mask & 1) && mcs->call.args[i] == nval )
- ++rc;
- else
{
- cval = mcs->call.args[i];
- BUG_ON(mcs->call.args[i] != cval);
+ mcs->call.args[i] = cval;
+ ++rc;
}
- mcs->compat_call.args[i] = cval;
+ else
+ BUG_ON(mcs->call.args[i] != (unsigned int)mcs->call.args[i]);
}
}
else
diff --git a/xen/common/compat/multicall.c b/xen/common/compat/multicall.c
index 17b12d6462..0eb1212772 100644
--- a/xen/common/compat/multicall.c
+++ b/xen/common/compat/multicall.c
@@ -10,6 +10,13 @@
typedef int ret_t;
#undef do_multicall_call
+static inline void xlat_multicall_entry(struct mc_state *mcs)
+{
+ int i;
+ for (i=0; i<6; i++)
+ mcs->compat_call.args[i] = mcs->call.args[i];
+}
+
DEFINE_XEN_GUEST_HANDLE(multicall_entry_compat_t);
#define multicall_entry compat_multicall_entry
#define multicall_entry_t multicall_entry_compat_t
diff --git a/xen/common/multicall.c b/xen/common/multicall.c
index c03002256e..7ee21b47c1 100644
--- a/xen/common/multicall.c
+++ b/xen/common/multicall.c
@@ -17,6 +17,7 @@
#ifndef COMPAT
DEFINE_PER_CPU(struct mc_state, mc_state);
typedef long ret_t;
+#define xlat_multicall_entry(mcs)
#endif
ret_t
@@ -62,6 +63,9 @@ do_multicall(
if ( test_bit(_MCSF_call_preempted, &mcs->flags) )
{
+ /* Translate sub-call continuation to guest layout */
+ xlat_multicall_entry(mcs);
+
/* Copy the sub-call continuation. */
(void)__copy_to_guest(call_list, &mcs->call, 1);
goto preempted;