diff options
author | Ian Campbell <ian.campbell@xensource.com> | 2007-05-30 11:55:38 +0100 |
---|---|---|
committer | Ian Campbell <ian.campbell@xensource.com> | 2007-05-30 11:55:38 +0100 |
commit | ca938d8cc6d30f0c99e631e6fb050ce1c921ab08 (patch) | |
tree | 9d56aebbd52486d1042ef8d64c28ab3e5749b071 | |
parent | 96469475a6848763fd542d1305660ee7a8561569 (diff) | |
download | xen-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.c | 9 | ||||
-rw-r--r-- | xen/common/compat/multicall.c | 7 | ||||
-rw-r--r-- | xen/common/multicall.c | 4 |
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; |