mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86/hvm: Split the hypercall dispatching infrastructure out of hvm.c
Into a new hypercall.c. This is purely code motion. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Wei Liu <wei.liu2@citrix.com> Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
55fa23d907
commit
e637e8d12e
3 files changed
+333
-298
No files matched your search
@@ -6,6 +6,7 @@ obj-y += dm.o
|
||||
obj-y += emulate.o
|
||||
obj-y += hpet.o
|
||||
obj-y += hvm.o
|
||||
obj-y += hypercall.o
|
||||
obj-y += i8254.o
|
||||
obj-y += intercept.o
|
||||
obj-y += io.o
|
||||
|
||||
@@ -3719,304 +3719,6 @@ enum hvm_intblk hvm_interrupt_blocked(struct vcpu *v, struct hvm_intack intack)
|
||||
return hvm_intblk_none;
|
||||
}
|
||||
|
||||
static int grant_table_op_is_allowed(unsigned int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case GNTTABOP_query_size:
|
||||
case GNTTABOP_setup_table:
|
||||
case GNTTABOP_set_version:
|
||||
case GNTTABOP_get_version:
|
||||
case GNTTABOP_copy:
|
||||
case GNTTABOP_map_grant_ref:
|
||||
case GNTTABOP_unmap_grant_ref:
|
||||
case GNTTABOP_swap_grant_ref:
|
||||
return 1;
|
||||
default:
|
||||
/* all other commands need auditing */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static long hvm_grant_table_op(
|
||||
unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) uop, unsigned int count)
|
||||
{
|
||||
if ( !grant_table_op_is_allowed(cmd) )
|
||||
return -ENOSYS; /* all other commands need auditing */
|
||||
return do_grant_table_op(cmd, uop, count);
|
||||
}
|
||||
|
||||
static long hvm_memory_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
long rc;
|
||||
|
||||
switch ( cmd & MEMOP_CMD_MASK )
|
||||
{
|
||||
case XENMEM_machine_memory_map:
|
||||
case XENMEM_machphys_mapping:
|
||||
return -ENOSYS;
|
||||
case XENMEM_decrease_reservation:
|
||||
rc = do_memory_op(cmd, arg);
|
||||
current->domain->arch.hvm_domain.qemu_mapcache_invalidate = 1;
|
||||
return rc;
|
||||
}
|
||||
return do_memory_op(cmd, arg);
|
||||
}
|
||||
|
||||
static long hvm_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
switch ( cmd )
|
||||
{
|
||||
default:
|
||||
if ( !is_pvh_vcpu(current) || !is_hardware_domain(current->domain) )
|
||||
return -ENOSYS;
|
||||
/* fall through */
|
||||
case PHYSDEVOP_map_pirq:
|
||||
case PHYSDEVOP_unmap_pirq:
|
||||
case PHYSDEVOP_eoi:
|
||||
case PHYSDEVOP_irq_status_query:
|
||||
case PHYSDEVOP_get_free_pirq:
|
||||
return do_physdev_op(cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static long hvm_grant_table_op_compat32(unsigned int cmd,
|
||||
XEN_GUEST_HANDLE_PARAM(void) uop,
|
||||
unsigned int count)
|
||||
{
|
||||
if ( !grant_table_op_is_allowed(cmd) )
|
||||
return -ENOSYS;
|
||||
return compat_grant_table_op(cmd, uop, count);
|
||||
}
|
||||
|
||||
static long hvm_memory_op_compat32(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch ( cmd & MEMOP_CMD_MASK )
|
||||
{
|
||||
case XENMEM_machine_memory_map:
|
||||
case XENMEM_machphys_mapping:
|
||||
return -ENOSYS;
|
||||
case XENMEM_decrease_reservation:
|
||||
rc = compat_memory_op(cmd, arg);
|
||||
current->domain->arch.hvm_domain.qemu_mapcache_invalidate = 1;
|
||||
return rc;
|
||||
}
|
||||
return compat_memory_op(cmd, arg);
|
||||
}
|
||||
|
||||
static long hvm_physdev_op_compat32(
|
||||
int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
switch ( cmd )
|
||||
{
|
||||
case PHYSDEVOP_map_pirq:
|
||||
case PHYSDEVOP_unmap_pirq:
|
||||
case PHYSDEVOP_eoi:
|
||||
case PHYSDEVOP_irq_status_query:
|
||||
case PHYSDEVOP_get_free_pirq:
|
||||
return compat_physdev_op(cmd, arg);
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define HYPERCALL(x) \
|
||||
[ __HYPERVISOR_ ## x ] = { (hypercall_fn_t *) do_ ## x, \
|
||||
(hypercall_fn_t *) do_ ## x }
|
||||
|
||||
#define COMPAT_CALL(x) \
|
||||
[ __HYPERVISOR_ ## x ] = { (hypercall_fn_t *) do_ ## x, \
|
||||
(hypercall_fn_t *) compat_ ## x }
|
||||
|
||||
#define do_memory_op hvm_memory_op
|
||||
#define compat_memory_op hvm_memory_op_compat32
|
||||
#define do_physdev_op hvm_physdev_op
|
||||
#define compat_physdev_op hvm_physdev_op_compat32
|
||||
#define do_grant_table_op hvm_grant_table_op
|
||||
#define compat_grant_table_op hvm_grant_table_op_compat32
|
||||
#define do_arch_1 paging_domctl_continuation
|
||||
|
||||
static const hypercall_table_t hvm_hypercall_table[] = {
|
||||
COMPAT_CALL(memory_op),
|
||||
COMPAT_CALL(grant_table_op),
|
||||
COMPAT_CALL(vcpu_op),
|
||||
COMPAT_CALL(physdev_op),
|
||||
COMPAT_CALL(xen_version),
|
||||
HYPERCALL(console_io),
|
||||
HYPERCALL(event_channel_op),
|
||||
COMPAT_CALL(sched_op),
|
||||
COMPAT_CALL(set_timer_op),
|
||||
HYPERCALL(xsm_op),
|
||||
HYPERCALL(hvm_op),
|
||||
HYPERCALL(sysctl),
|
||||
HYPERCALL(domctl),
|
||||
#ifdef CONFIG_TMEM
|
||||
HYPERCALL(tmem_op),
|
||||
#endif
|
||||
COMPAT_CALL(platform_op),
|
||||
COMPAT_CALL(mmuext_op),
|
||||
HYPERCALL(xenpmu_op),
|
||||
COMPAT_CALL(dm_op),
|
||||
HYPERCALL(arch_1)
|
||||
};
|
||||
|
||||
#undef do_memory_op
|
||||
#undef compat_memory_op
|
||||
#undef do_physdev_op
|
||||
#undef compat_physdev_op
|
||||
#undef do_grant_table_op
|
||||
#undef compat_grant_table_op
|
||||
#undef do_arch_1
|
||||
|
||||
#undef HYPERCALL
|
||||
#undef COMPAT_CALL
|
||||
|
||||
int hvm_hypercall(struct cpu_user_regs *regs)
|
||||
{
|
||||
struct vcpu *curr = current;
|
||||
struct domain *currd = curr->domain;
|
||||
int mode = hvm_guest_x86_mode(curr);
|
||||
unsigned long eax = regs->_eax;
|
||||
|
||||
switch ( mode )
|
||||
{
|
||||
case 8:
|
||||
eax = regs->rax;
|
||||
/* Fallthrough to permission check. */
|
||||
case 4:
|
||||
case 2:
|
||||
if ( unlikely(hvm_get_cpl(curr)) )
|
||||
{
|
||||
default:
|
||||
regs->rax = -EPERM;
|
||||
return HVM_HCALL_completed;
|
||||
}
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (eax & 0x80000000) && is_viridian_domain(currd) )
|
||||
return viridian_hypercall(regs);
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(hvm_hypercall_table) >
|
||||
ARRAY_SIZE(hypercall_args_table));
|
||||
|
||||
if ( (eax >= ARRAY_SIZE(hvm_hypercall_table)) ||
|
||||
!hvm_hypercall_table[eax].native )
|
||||
{
|
||||
regs->rax = -ENOSYS;
|
||||
return HVM_HCALL_completed;
|
||||
}
|
||||
|
||||
curr->arch.hvm_vcpu.hcall_preempted = 0;
|
||||
|
||||
if ( mode == 8 )
|
||||
{
|
||||
unsigned long rdi = regs->rdi;
|
||||
unsigned long rsi = regs->rsi;
|
||||
unsigned long rdx = regs->rdx;
|
||||
unsigned long r10 = regs->r10;
|
||||
unsigned long r8 = regs->r8;
|
||||
unsigned long r9 = regs->r9;
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_HCALL, "hcall%lu(%lx, %lx, %lx, %lx, %lx, %lx)",
|
||||
eax, rdi, rsi, rdx, r10, r8, r9);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Deliberately corrupt parameter regs not used by this hypercall. */
|
||||
switch ( hypercall_args_table[eax].native )
|
||||
{
|
||||
case 0: rdi = 0xdeadbeefdeadf00dUL;
|
||||
case 1: rsi = 0xdeadbeefdeadf00dUL;
|
||||
case 2: rdx = 0xdeadbeefdeadf00dUL;
|
||||
case 3: r10 = 0xdeadbeefdeadf00dUL;
|
||||
case 4: r8 = 0xdeadbeefdeadf00dUL;
|
||||
case 5: r9 = 0xdeadbeefdeadf00dUL;
|
||||
}
|
||||
#endif
|
||||
|
||||
curr->arch.hvm_vcpu.hcall_64bit = 1;
|
||||
regs->rax = hvm_hypercall_table[eax].native(rdi, rsi, rdx, r10, r8,
|
||||
r9);
|
||||
|
||||
curr->arch.hvm_vcpu.hcall_64bit = 0;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ( !curr->arch.hvm_vcpu.hcall_preempted )
|
||||
{
|
||||
/* Deliberately corrupt parameter regs used by this hypercall. */
|
||||
switch ( hypercall_args_table[eax].native )
|
||||
{
|
||||
case 6: regs->r9 = 0xdeadbeefdeadf00dUL;
|
||||
case 5: regs->r8 = 0xdeadbeefdeadf00dUL;
|
||||
case 4: regs->r10 = 0xdeadbeefdeadf00dUL;
|
||||
case 3: regs->rdx = 0xdeadbeefdeadf00dUL;
|
||||
case 2: regs->rsi = 0xdeadbeefdeadf00dUL;
|
||||
case 1: regs->rdi = 0xdeadbeefdeadf00dUL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int ebx = regs->_ebx;
|
||||
unsigned int ecx = regs->_ecx;
|
||||
unsigned int edx = regs->_edx;
|
||||
unsigned int esi = regs->_esi;
|
||||
unsigned int edi = regs->_edi;
|
||||
unsigned int ebp = regs->_ebp;
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_HCALL, "hcall%lu(%x, %x, %x, %x, %x, %x)", eax,
|
||||
ebx, ecx, edx, esi, edi, ebp);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Deliberately corrupt parameter regs not used by this hypercall. */
|
||||
switch ( hypercall_args_table[eax].compat )
|
||||
{
|
||||
case 0: ebx = 0xdeadf00d;
|
||||
case 1: ecx = 0xdeadf00d;
|
||||
case 2: edx = 0xdeadf00d;
|
||||
case 3: esi = 0xdeadf00d;
|
||||
case 4: edi = 0xdeadf00d;
|
||||
case 5: ebp = 0xdeadf00d;
|
||||
}
|
||||
#endif
|
||||
|
||||
regs->rax = hvm_hypercall_table[eax].compat(ebx, ecx, edx, esi, edi,
|
||||
ebp);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ( !curr->arch.hvm_vcpu.hcall_preempted )
|
||||
{
|
||||
/* Deliberately corrupt parameter regs used by this hypercall. */
|
||||
switch ( hypercall_args_table[eax].compat )
|
||||
{
|
||||
case 6: regs->rbp = 0xdeadf00d;
|
||||
case 5: regs->rdi = 0xdeadf00d;
|
||||
case 4: regs->rsi = 0xdeadf00d;
|
||||
case 3: regs->rdx = 0xdeadf00d;
|
||||
case 2: regs->rcx = 0xdeadf00d;
|
||||
case 1: regs->rbx = 0xdeadf00d;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_HCALL, "hcall%lu -> %lx", eax, regs->rax);
|
||||
|
||||
if ( curr->arch.hvm_vcpu.hcall_preempted )
|
||||
return HVM_HCALL_preempted;
|
||||
|
||||
if ( unlikely(currd->arch.hvm_domain.qemu_mapcache_invalidate) &&
|
||||
test_and_clear_bool(currd->arch.hvm_domain.qemu_mapcache_invalidate) )
|
||||
send_invalidate_req();
|
||||
|
||||
return HVM_HCALL_completed;
|
||||
}
|
||||
|
||||
static void hvm_latch_shinfo_size(struct domain *d)
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
/******************************************************************************
|
||||
* arch/hvm/hypercall.c
|
||||
*
|
||||
* HVM hypercall dispatching routines
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright (c) 2017 Citrix Systems Ltd.
|
||||
*/
|
||||
#include <xen/lib.h>
|
||||
#include <xen/hypercall.h>
|
||||
|
||||
#include <asm/hvm/support.h>
|
||||
|
||||
static int grant_table_op_is_allowed(unsigned int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case GNTTABOP_query_size:
|
||||
case GNTTABOP_setup_table:
|
||||
case GNTTABOP_set_version:
|
||||
case GNTTABOP_get_version:
|
||||
case GNTTABOP_copy:
|
||||
case GNTTABOP_map_grant_ref:
|
||||
case GNTTABOP_unmap_grant_ref:
|
||||
case GNTTABOP_swap_grant_ref:
|
||||
return 1;
|
||||
default:
|
||||
/* all other commands need auditing */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static long hvm_grant_table_op(
|
||||
unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) uop, unsigned int count)
|
||||
{
|
||||
if ( !grant_table_op_is_allowed(cmd) )
|
||||
return -ENOSYS; /* all other commands need auditing */
|
||||
return do_grant_table_op(cmd, uop, count);
|
||||
}
|
||||
|
||||
static long hvm_memory_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
long rc;
|
||||
|
||||
switch ( cmd & MEMOP_CMD_MASK )
|
||||
{
|
||||
case XENMEM_machine_memory_map:
|
||||
case XENMEM_machphys_mapping:
|
||||
return -ENOSYS;
|
||||
case XENMEM_decrease_reservation:
|
||||
rc = do_memory_op(cmd, arg);
|
||||
current->domain->arch.hvm_domain.qemu_mapcache_invalidate = 1;
|
||||
return rc;
|
||||
}
|
||||
return do_memory_op(cmd, arg);
|
||||
}
|
||||
|
||||
static long hvm_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
switch ( cmd )
|
||||
{
|
||||
default:
|
||||
if ( !is_pvh_vcpu(current) || !is_hardware_domain(current->domain) )
|
||||
return -ENOSYS;
|
||||
/* fall through */
|
||||
case PHYSDEVOP_map_pirq:
|
||||
case PHYSDEVOP_unmap_pirq:
|
||||
case PHYSDEVOP_eoi:
|
||||
case PHYSDEVOP_irq_status_query:
|
||||
case PHYSDEVOP_get_free_pirq:
|
||||
return do_physdev_op(cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static long hvm_grant_table_op_compat32(unsigned int cmd,
|
||||
XEN_GUEST_HANDLE_PARAM(void) uop,
|
||||
unsigned int count)
|
||||
{
|
||||
if ( !grant_table_op_is_allowed(cmd) )
|
||||
return -ENOSYS;
|
||||
return compat_grant_table_op(cmd, uop, count);
|
||||
}
|
||||
|
||||
static long hvm_memory_op_compat32(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch ( cmd & MEMOP_CMD_MASK )
|
||||
{
|
||||
case XENMEM_machine_memory_map:
|
||||
case XENMEM_machphys_mapping:
|
||||
return -ENOSYS;
|
||||
case XENMEM_decrease_reservation:
|
||||
rc = compat_memory_op(cmd, arg);
|
||||
current->domain->arch.hvm_domain.qemu_mapcache_invalidate = 1;
|
||||
return rc;
|
||||
}
|
||||
return compat_memory_op(cmd, arg);
|
||||
}
|
||||
|
||||
static long hvm_physdev_op_compat32(
|
||||
int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
{
|
||||
switch ( cmd )
|
||||
{
|
||||
case PHYSDEVOP_map_pirq:
|
||||
case PHYSDEVOP_unmap_pirq:
|
||||
case PHYSDEVOP_eoi:
|
||||
case PHYSDEVOP_irq_status_query:
|
||||
case PHYSDEVOP_get_free_pirq:
|
||||
return compat_physdev_op(cmd, arg);
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define HYPERCALL(x) \
|
||||
[ __HYPERVISOR_ ## x ] = { (hypercall_fn_t *) do_ ## x, \
|
||||
(hypercall_fn_t *) do_ ## x }
|
||||
|
||||
#define COMPAT_CALL(x) \
|
||||
[ __HYPERVISOR_ ## x ] = { (hypercall_fn_t *) do_ ## x, \
|
||||
(hypercall_fn_t *) compat_ ## x }
|
||||
|
||||
#define do_memory_op hvm_memory_op
|
||||
#define compat_memory_op hvm_memory_op_compat32
|
||||
#define do_physdev_op hvm_physdev_op
|
||||
#define compat_physdev_op hvm_physdev_op_compat32
|
||||
#define do_grant_table_op hvm_grant_table_op
|
||||
#define compat_grant_table_op hvm_grant_table_op_compat32
|
||||
#define do_arch_1 paging_domctl_continuation
|
||||
|
||||
static const hypercall_table_t hvm_hypercall_table[] = {
|
||||
COMPAT_CALL(memory_op),
|
||||
COMPAT_CALL(grant_table_op),
|
||||
COMPAT_CALL(vcpu_op),
|
||||
COMPAT_CALL(physdev_op),
|
||||
COMPAT_CALL(xen_version),
|
||||
HYPERCALL(console_io),
|
||||
HYPERCALL(event_channel_op),
|
||||
COMPAT_CALL(sched_op),
|
||||
COMPAT_CALL(set_timer_op),
|
||||
HYPERCALL(xsm_op),
|
||||
HYPERCALL(hvm_op),
|
||||
HYPERCALL(sysctl),
|
||||
HYPERCALL(domctl),
|
||||
#ifdef CONFIG_TMEM
|
||||
HYPERCALL(tmem_op),
|
||||
#endif
|
||||
COMPAT_CALL(platform_op),
|
||||
COMPAT_CALL(mmuext_op),
|
||||
HYPERCALL(xenpmu_op),
|
||||
COMPAT_CALL(dm_op),
|
||||
HYPERCALL(arch_1)
|
||||
};
|
||||
|
||||
#undef do_memory_op
|
||||
#undef compat_memory_op
|
||||
#undef do_physdev_op
|
||||
#undef compat_physdev_op
|
||||
#undef do_grant_table_op
|
||||
#undef compat_grant_table_op
|
||||
#undef do_arch_1
|
||||
|
||||
#undef HYPERCALL
|
||||
#undef COMPAT_CALL
|
||||
|
||||
int hvm_hypercall(struct cpu_user_regs *regs)
|
||||
{
|
||||
struct vcpu *curr = current;
|
||||
struct domain *currd = curr->domain;
|
||||
int mode = hvm_guest_x86_mode(curr);
|
||||
unsigned long eax = regs->_eax;
|
||||
|
||||
switch ( mode )
|
||||
{
|
||||
case 8:
|
||||
eax = regs->rax;
|
||||
/* Fallthrough to permission check. */
|
||||
case 4:
|
||||
case 2:
|
||||
if ( unlikely(hvm_get_cpl(curr)) )
|
||||
{
|
||||
default:
|
||||
regs->rax = -EPERM;
|
||||
return HVM_HCALL_completed;
|
||||
}
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (eax & 0x80000000) && is_viridian_domain(currd) )
|
||||
return viridian_hypercall(regs);
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(hvm_hypercall_table) >
|
||||
ARRAY_SIZE(hypercall_args_table));
|
||||
|
||||
if ( (eax >= ARRAY_SIZE(hvm_hypercall_table)) ||
|
||||
!hvm_hypercall_table[eax].native )
|
||||
{
|
||||
regs->rax = -ENOSYS;
|
||||
return HVM_HCALL_completed;
|
||||
}
|
||||
|
||||
curr->arch.hvm_vcpu.hcall_preempted = 0;
|
||||
|
||||
if ( mode == 8 )
|
||||
{
|
||||
unsigned long rdi = regs->rdi;
|
||||
unsigned long rsi = regs->rsi;
|
||||
unsigned long rdx = regs->rdx;
|
||||
unsigned long r10 = regs->r10;
|
||||
unsigned long r8 = regs->r8;
|
||||
unsigned long r9 = regs->r9;
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_HCALL, "hcall%lu(%lx, %lx, %lx, %lx, %lx, %lx)",
|
||||
eax, rdi, rsi, rdx, r10, r8, r9);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Deliberately corrupt parameter regs not used by this hypercall. */
|
||||
switch ( hypercall_args_table[eax].native )
|
||||
{
|
||||
case 0: rdi = 0xdeadbeefdeadf00dUL;
|
||||
case 1: rsi = 0xdeadbeefdeadf00dUL;
|
||||
case 2: rdx = 0xdeadbeefdeadf00dUL;
|
||||
case 3: r10 = 0xdeadbeefdeadf00dUL;
|
||||
case 4: r8 = 0xdeadbeefdeadf00dUL;
|
||||
case 5: r9 = 0xdeadbeefdeadf00dUL;
|
||||
}
|
||||
#endif
|
||||
|
||||
curr->arch.hvm_vcpu.hcall_64bit = 1;
|
||||
regs->rax = hvm_hypercall_table[eax].native(rdi, rsi, rdx, r10, r8,
|
||||
r9);
|
||||
|
||||
curr->arch.hvm_vcpu.hcall_64bit = 0;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ( !curr->arch.hvm_vcpu.hcall_preempted )
|
||||
{
|
||||
/* Deliberately corrupt parameter regs used by this hypercall. */
|
||||
switch ( hypercall_args_table[eax].native )
|
||||
{
|
||||
case 6: regs->r9 = 0xdeadbeefdeadf00dUL;
|
||||
case 5: regs->r8 = 0xdeadbeefdeadf00dUL;
|
||||
case 4: regs->r10 = 0xdeadbeefdeadf00dUL;
|
||||
case 3: regs->rdx = 0xdeadbeefdeadf00dUL;
|
||||
case 2: regs->rsi = 0xdeadbeefdeadf00dUL;
|
||||
case 1: regs->rdi = 0xdeadbeefdeadf00dUL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int ebx = regs->_ebx;
|
||||
unsigned int ecx = regs->_ecx;
|
||||
unsigned int edx = regs->_edx;
|
||||
unsigned int esi = regs->_esi;
|
||||
unsigned int edi = regs->_edi;
|
||||
unsigned int ebp = regs->_ebp;
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_HCALL, "hcall%lu(%x, %x, %x, %x, %x, %x)", eax,
|
||||
ebx, ecx, edx, esi, edi, ebp);
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Deliberately corrupt parameter regs not used by this hypercall. */
|
||||
switch ( hypercall_args_table[eax].compat )
|
||||
{
|
||||
case 0: ebx = 0xdeadf00d;
|
||||
case 1: ecx = 0xdeadf00d;
|
||||
case 2: edx = 0xdeadf00d;
|
||||
case 3: esi = 0xdeadf00d;
|
||||
case 4: edi = 0xdeadf00d;
|
||||
case 5: ebp = 0xdeadf00d;
|
||||
}
|
||||
#endif
|
||||
|
||||
regs->rax = hvm_hypercall_table[eax].compat(ebx, ecx, edx, esi, edi,
|
||||
ebp);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ( !curr->arch.hvm_vcpu.hcall_preempted )
|
||||
{
|
||||
/* Deliberately corrupt parameter regs used by this hypercall. */
|
||||
switch ( hypercall_args_table[eax].compat )
|
||||
{
|
||||
case 6: regs->rbp = 0xdeadf00d;
|
||||
case 5: regs->rdi = 0xdeadf00d;
|
||||
case 4: regs->rsi = 0xdeadf00d;
|
||||
case 3: regs->rdx = 0xdeadf00d;
|
||||
case 2: regs->rcx = 0xdeadf00d;
|
||||
case 1: regs->rbx = 0xdeadf00d;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_HCALL, "hcall%lu -> %lx", eax, regs->rax);
|
||||
|
||||
if ( curr->arch.hvm_vcpu.hcall_preempted )
|
||||
return HVM_HCALL_preempted;
|
||||
|
||||
if ( unlikely(currd->arch.hvm_domain.qemu_mapcache_invalidate) &&
|
||||
test_and_clear_bool(currd->arch.hvm_domain.qemu_mapcache_invalidate) )
|
||||
send_invalidate_req();
|
||||
|
||||
return HVM_HCALL_completed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||