@@ -17,6 +17,7 @@
*/
#include <xen/config.h>
+#include <xen/stdbool.h>
#include <xen/init.h>
#include <xen/string.h>
#include <xen/version.h>
@@ -1012,6 +1013,7 @@ static arm_hypercall_t arm_hypercall_table[] = {
HYPERCALL(sysctl, 2),
HYPERCALL(hvm_op, 2),
HYPERCALL(grant_table_op, 3),
+ HYPERCALL(multicall, 2),
HYPERCALL_ARM(vcpu_op, 3),
};
@@ -1159,6 +1161,24 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
#endif
}
+static bool_t check_multicall_32bit_clean(struct multicall_entry *multi)
+{
+ int i;
+
+ for ( i = 0; i < arm_hypercall_table[multi->op].nr_args; i++ )
+ {
+ if ( unlikely(multi->args[i] & 0xffffffff00000000ULL) )
+ {
+ printk("%pv: multicall argument %d is not 32-bit clean %"PRIx64"\n",
+ current, i, multi->args[i]);
+ domain_crash(current->domain);
+ return false;
+ }
+ }
+
+ return true;
+}
+
void do_multicall_call(struct multicall_entry *multi)
{
arm_hypercall_fn_t call = NULL;
@@ -1176,9 +1196,13 @@ void do_multicall_call(struct multicall_entry *multi)
return;
}
+ if ( is_32bit_domain(current->domain) &&
+ !check_multicall_32bit_clean(multi) )
+ return;
+
multi->result = call(multi->args[0], multi->args[1],
- multi->args[2], multi->args[3],
- multi->args[4]);
+ multi->args[2], multi->args[3],
+ multi->args[4]);
}
/*
@@ -29,7 +29,7 @@ DEFINE_XEN_GUEST_HANDLE(multicall_entry_compat_t);
static void __trace_multicall_call(multicall_entry_t *call)
{
- unsigned long args[6];
+ xen_ulong_t args[6];
int i;
for ( i = 0; i < ARRAY_SIZE(args); i++ )
@@ -35,10 +35,10 @@ static void trace_multicall_call(multicall_entry_t *call)
ret_t
do_multicall(
- XEN_GUEST_HANDLE_PARAM(multicall_entry_t) call_list, unsigned int nr_calls)
+ XEN_GUEST_HANDLE_PARAM(multicall_entry_t) call_list, uint32_t nr_calls)
{
struct mc_state *mcs = ¤t->mc_state;
- unsigned int i;
+ uint32_t i;
int rc = 0;
if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
@@ -817,7 +817,7 @@ unlock:
}
void __trace_hypercall(uint32_t event, unsigned long op,
- const unsigned long *args)
+ const xen_ulong_t *args)
{
struct __packed {
uint32_t op;
@@ -541,13 +541,15 @@ DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
/*
* ` enum neg_errnoval
* ` HYPERVISOR_multicall(multicall_entry_t call_list[],
- * ` unsigned int nr_calls);
+ * ` uint32_t nr_calls);
*
- * NB. The fields are natural register size for this architecture.
+ * NB. The fields are logically the natural register size for this
+ * architecture. In cases where xen_ulong_t is larger than this then
+ * any unused bits in the upper portion must be zero.
*/
struct multicall_entry {
- unsigned long op, result;
- unsigned long args[6];
+ xen_ulong_t op, result;
+ xen_ulong_t args[6];
};
typedef struct multicall_entry multicall_entry_t;
DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
@@ -45,7 +45,7 @@ static inline void trace_var(u32 event, int cycles, int extra,
}
void __trace_hypercall(uint32_t event, unsigned long op,
- const unsigned long *args);
+ const xen_ulong_t *args);
/* Convenience macros for calling the trace function. */
#define TRACE_0D(_e) \