550 lines
16 KiB
C
550 lines
16 KiB
C
|
/*
|
||
|
*
|
||
|
* Copyright (C) 2015 MCST
|
||
|
*
|
||
|
* Defenition of traps handling routines.
|
||
|
*/
|
||
|
|
||
|
#ifndef _E2K_KVM_TRAP_TABLE_ASM_H
|
||
|
#define _E2K_KVM_TRAP_TABLE_ASM_H
|
||
|
|
||
|
#ifdef __ASSEMBLY__
|
||
|
|
||
|
#include <asm/thread_info.h>
|
||
|
#include <asm/e2k_api.h>
|
||
|
#include <asm/cpu_regs_types.h>
|
||
|
#include <asm/glob_regs.h>
|
||
|
#include <asm/mmu_regs_types.h>
|
||
|
|
||
|
#include <generated/asm-offsets.h>
|
||
|
|
||
|
#if defined CONFIG_SMP
|
||
|
# define SMP_ONLY(...) __VA_ARGS__
|
||
|
#else
|
||
|
# define SMP_ONLY(...)
|
||
|
#endif
|
||
|
|
||
|
#ifdef CONFIG_KVM_HOST_MODE
|
||
|
/* it is host kernel with virtualization support */
|
||
|
/* or paravirtualized host and guest kernel */
|
||
|
|
||
|
.macro DO_SWITCH_TO_KERNEL_IMAGE_PGD rti, predN, rtmp0, rtmp1, rtmp2
|
||
|
/* do switch to host kernel image */
|
||
|
/* thread_info_t *ti = rti */
|
||
|
/* %pred_no is true to switch to kernel image pgd */
|
||
|
/* if guest and host kernel images are loaded to equal */
|
||
|
/* addresses, then switch from one to another must */
|
||
|
/* flush all caches, including TLB */
|
||
|
/* if (%pred_no) { */
|
||
|
/* native_flush_TLB_all(); */
|
||
|
/* native_flush_CACHE_all(); */
|
||
|
/* E2K_WAIT_FLUSH; */
|
||
|
/* } */
|
||
|
{
|
||
|
ldd [\rti + TI_KERNEL_IMAGE_PGD_P], \rtmp1 ? \predN;
|
||
|
ldd [\rti + TI_KERNEL_IMAGE_PGD], \rtmp2 ? \predN;
|
||
|
addd 0, 0, \rtmp0 ? \predN;
|
||
|
}
|
||
|
{
|
||
|
std,2 \rtmp0, [_FLUSH_TLB_ALL_OP] MAS_TLB_FLUSH ? \predN;
|
||
|
std \rtmp2, [\rtmp1] ? \predN;
|
||
|
}
|
||
|
{
|
||
|
std,2 \rtmp0, [_FLUSH_CACHE_L12_OP] MAS_CACHE_FLUSH ? \predN;
|
||
|
}
|
||
|
wait fl_c = 1;
|
||
|
.endm /* DO_SWITCH_TO_KERNEL_IMAGE_PGD */
|
||
|
|
||
|
.macro SWITCH_TO_KERNEL_IMAGE_PGD rti predN rtmp0, rtmp1, rtmp2
|
||
|
/* switch to host kernel image */
|
||
|
/* thread_info_t *ti = rti; */
|
||
|
/* if (ti->flags & _TIF_PARAVIRT_GUEST) { */
|
||
|
/* *ti->kernel_image_pgd_p = ti->kernel_image_pgd; */
|
||
|
/* native_flush_TLB_all(); */
|
||
|
/* native_flush_CACHE_all(); */
|
||
|
/* E2K_WAIT_FLUSH; */
|
||
|
/* } */
|
||
|
/* rti: current_thread_info */
|
||
|
ldd [\rti + TI_FLAGS], \rtmp0;
|
||
|
cmpandedb \rtmp0, _TIF_PARAVIRT_GUEST, \predN;
|
||
|
{
|
||
|
pass \predN, @p0;
|
||
|
landp ~@p0, ~@p0, @p4;
|
||
|
pass @p4, \predN;
|
||
|
}
|
||
|
DO_SWITCH_TO_KERNEL_IMAGE_PGD \rti, \predN, \rtmp0, \rtmp1, \rtmp2
|
||
|
.endm
|
||
|
|
||
|
/*
|
||
|
* goto guest kernel system call table entry, if system call is from guest user
|
||
|
* rti: register of current_thread_info()
|
||
|
* rtmp0 rtmp1 rtmp2: temporary registers
|
||
|
* ptmp0 ptmp1 ptmp2: temporary predicates
|
||
|
*/
|
||
|
.macro GOTO_GUEST_KERNEL_TTABLE entry_num rti rtmp0 rtmp1 rtmp2 \
|
||
|
ptmp0 ptmp1 ptmp2
|
||
|
/* thread_info_t *ti = %dr7 */
|
||
|
/* e2k_cr1_lo_t cr1_lo = NATIVE_READ_CR1_LO_REG(); */
|
||
|
/* */
|
||
|
/* if ((ti->flags & _TIF_VIRTUALIZED_GUEST)) && { */
|
||
|
/* !(cr1_lo.CR1_lo_psr & PSR_PM)) { */
|
||
|
/* if (ti->flags & _TIF_PARAVIRT_GUEST) { */
|
||
|
/* DO_SWITCH_TO_KERNEL_IMAGE_PGD() */
|
||
|
/* } */
|
||
|
/* goto goto_guest_kernel_ttable_C( */
|
||
|
/* sys_num << 32 | entry, */
|
||
|
/* arg1, arg2, arg3, arg4, */
|
||
|
/* arg5, arg6); */
|
||
|
/* } */
|
||
|
|
||
|
.global goto_guest_kernel_ttable_C;
|
||
|
{
|
||
|
rrd %cr1.lo, \rtmp1;
|
||
|
ldd [\rti + TI_FLAGS], \rtmp0;
|
||
|
sxt 2, %r0, %dr0;
|
||
|
}
|
||
|
{
|
||
|
cmpandedb \rtmp1, CR1_LO_PSR_PM_MASK, \ptmp1;
|
||
|
cmpandedb \rtmp0, _TIF_VIRTUALIZED_GUEST, \ptmp0;
|
||
|
cmpandedb \rtmp0, _TIF_PARAVIRT_GUEST, \ptmp2;
|
||
|
}
|
||
|
{
|
||
|
pass \ptmp0, @p0;
|
||
|
pass \ptmp1, @p1;
|
||
|
landp ~@p0, @p1, @p4;
|
||
|
pass @p4, \ptmp0;
|
||
|
pass \ptmp2, @p2;
|
||
|
landp ~@p2, ~@p2, @p5;
|
||
|
pass @p5, \ptmp1;
|
||
|
}
|
||
|
{
|
||
|
puttagd %dr1, 0, %dr1 ? \ptmp0;
|
||
|
puttagd %dr2, 0, %dr2 ? \ptmp0;
|
||
|
shld %dr0, 32, %dr0 ? \ptmp0;
|
||
|
}
|
||
|
{
|
||
|
SMP_ONLY(shld,1 GCPUID, 3, GCPUOFFSET ? \ptmp0)
|
||
|
puttagd %dr3, 0, %dr3 ? \ptmp0;
|
||
|
puttagd %dr4, 0, %dr4 ? \ptmp0;
|
||
|
ord %dr0, \entry_num, %dr0 ? \ptmp0;
|
||
|
}
|
||
|
{
|
||
|
puttagd %dr5, 0, %dr5 ? \ptmp0;
|
||
|
puttagd %dr6, 0, %dr6 ? \ptmp0;
|
||
|
}
|
||
|
/* rti: current_thread_info */
|
||
|
/* ptmp1 : predicate is true if need switch kernel image pgd */
|
||
|
/* rtmp0, rtmp1, rtmp2: temporary registers */
|
||
|
DO_SWITCH_TO_KERNEL_IMAGE_PGD \rti, \ptmp1, \rtmp0, \rtmp1, \rtmp2
|
||
|
{
|
||
|
SMP_ONLY(ldd,2 [ __per_cpu_offset + GCPUOFFSET ], GCPUOFFSET ? \ptmp0)
|
||
|
puttagd %dr7, 0, %dr7 ? \ptmp0;
|
||
|
ibranch goto_guest_kernel_ttable_C ? \ptmp0;
|
||
|
}
|
||
|
.endm /* GOTO_GUEST_KERNEL_TTABLE */
|
||
|
|
||
|
/*
|
||
|
* goto guest kernel system call table entry, if system call is from guest user
|
||
|
* rti: register of current_thread_info()
|
||
|
* rtmp0 rtmp1 rtmp2: temporary registers
|
||
|
* ptmp0 ptmp1: temporary predicates
|
||
|
*/
|
||
|
.macro GOTO_PV_VCPU_KERNEL_TTABLE entry_num rti rtmp0 rtmp1 rtmp2 \
|
||
|
ptmp0 ptmp1
|
||
|
/* thread_info_t *ti = %dr7 */
|
||
|
/* e2k_cr1_lo_t cr1_lo = NATIVE_READ_CR1_LO_REG(); */
|
||
|
/* */
|
||
|
/* if ((ti->flags & TIF_HOST_AT_VCPU_MODE)) { */
|
||
|
/* if (ti->flags & _TIF_PARAVIRT_GUEST) { */
|
||
|
/* DO_SWITCH_TO_KERNEL_IMAGE_PGD() */
|
||
|
/* } */
|
||
|
/* goto goto_guest_kernel_ttable_C( */
|
||
|
/* sys_num << 32 | entry, */
|
||
|
/* arg1, arg2, arg3, arg4, */
|
||
|
/* arg5, arg6); */
|
||
|
/* } */
|
||
|
|
||
|
{
|
||
|
ldd [\rti + TI_FLAGS], \rtmp0;
|
||
|
sxt 2, %r0, %dr0;
|
||
|
}
|
||
|
{
|
||
|
cmpandedb \rtmp0, _TIF_HOST_AT_VCPU_MODE, \ptmp0;
|
||
|
cmpandedb \rtmp0, _TIF_PARAVIRT_GUEST, \ptmp1;
|
||
|
}
|
||
|
{
|
||
|
pass \ptmp0, @p0;
|
||
|
landp ~@p0, ~@p0, @p4;
|
||
|
pass @p4, \ptmp0;
|
||
|
pass \ptmp1, @p2;
|
||
|
landp ~@p2, ~@p2, @p5;
|
||
|
pass @p5, \ptmp1;
|
||
|
}
|
||
|
/* rti: current_thread_info */
|
||
|
/* ptmp1 : predicate is true if need switch kernel image pgd */
|
||
|
/* rtmp0, rtmp1, rtmp2: temporary registers */
|
||
|
DO_SWITCH_TO_KERNEL_IMAGE_PGD \rti, \ptmp1, \rtmp0, \rtmp1, \rtmp2
|
||
|
.endm /* GOTO_GUEST_KERNEL_TTABLE */
|
||
|
|
||
|
/*
|
||
|
* goto guest kernel fast system call table entry, if system call is
|
||
|
* from guest user
|
||
|
* rtmpti: temporary register to read current_thread_info()
|
||
|
* rtmp0 rtmp1 rtmp2: temporary registers
|
||
|
* ptmp0 ptmp1 ptmp2: temporary predicates
|
||
|
*/
|
||
|
.macro GOTO_GUEST_KERNEL_FAST_TTABLE entry_num rtmpti rtmp0 rtmp1 rtmp2 \
|
||
|
ptmp0 ptmp1 ptmp2
|
||
|
{
|
||
|
setwd wsz = 8, nfx = 1;
|
||
|
nop 1;
|
||
|
rrd %osr0, \rtmpti;
|
||
|
ipd 2;
|
||
|
}
|
||
|
GOTO_GUEST_KERNEL_TTABLE \entry_num, \rtmpti, \rtmp0, \rtmp1, \rtmp2, \
|
||
|
\ptmp0, \ptmp1, \ptmp2
|
||
|
.endm /* GOTO_GUEST_KERNEL_FAST_TTABLE */
|
||
|
|
||
|
/*
|
||
|
* goto guest kernel protected system call table entry, if system call is
|
||
|
* from guest user
|
||
|
* rti: register of current_thread_info()
|
||
|
* rtmp0 rtmp1 rtmp2: temporary registers
|
||
|
* ptmp0 ptmp1 ptmp2: temporary predicates
|
||
|
* FIXME: is not implemented
|
||
|
*/
|
||
|
.macro GOTO_GUEST_KERNEL_PROT_TTABLE entry_num rti rtmp0 rtmp1 rtmp2 \
|
||
|
ptmp0 ptmp1 ptmp2
|
||
|
GOTO_GUEST_KERNEL_TTABLE \entry_num, \rti, \rtmp0, \rtmp1, \rtmp2, \
|
||
|
\ptmp0, \ptmp1, \ptmp2
|
||
|
.endm /* GOTO_GUEST_KERNEL_PROT_TTABLE */
|
||
|
|
||
|
#else /* ! CONFIG_KVM_HOST_MODE */
|
||
|
.macro SWITCH_TO_KERNEL_IMAGE_PGD rti predN rtmp0, rtmp1, rtmp2
|
||
|
/* not used */
|
||
|
.endm /* SWITCH_TO_KERNEL_IMAGE_PGD */
|
||
|
|
||
|
.macro GOTO_GUEST_KERNEL_TTABLE entry_num rti rtmp0 rtmp1 rtmp2 \
|
||
|
ptmp0 ptmp1 ptmp2
|
||
|
/* not used */
|
||
|
.endm /* GOTO_GUEST_KERNEL_TTABLE */
|
||
|
.macro GOTO_GUEST_KERNEL_FAST_TTABLE entry_num rtmpti rtmp0 rtmp1 rtmp2 \
|
||
|
ptmp0 ptmp1 ptmp2
|
||
|
/* not used */
|
||
|
.endm /* GOTO_GUEST_KERNEL_FAST_TTABLE */
|
||
|
.macro GOTO_GUEST_KERNEL_PROT_TTABLE entry_num rti rtmp0 rtmp1 rtmp2 \
|
||
|
ptmp0 ptmp1 ptmp2
|
||
|
/* not used */
|
||
|
.endm /* GOTO_GUEST_KERNEL_PROT_TTABLE */
|
||
|
.macro GOTO_PV_VCPU_KERNEL_TTABLE entry_num rti rtmp0 rtmp1 rtmp2 \
|
||
|
ptmp0 ptmp1
|
||
|
/* not used */
|
||
|
.endm /* GOTO_PV_VCPU_KERNEL_TTABLE */
|
||
|
#endif /* CONFIG_KVM_HOST_MODE */
|
||
|
|
||
|
/*
|
||
|
* Save current state of pair of global registers with tags and extensions
|
||
|
* gpair_lo/gpair_hi is pair of adjacent global registers, lo is even
|
||
|
* and hi is odd (for example GCURTI/GCURTASK)
|
||
|
* kreg_lo, kreg_hi is pair of indexes of global registers into structure
|
||
|
* to save these k_gregs.g[kregd_lo/kreg_hi]
|
||
|
* rbase is register containing base address to save global
|
||
|
* registers pair values (for example glob_regs_t structure
|
||
|
* or thread_info_t thread_info->k_gregs/h_gregs)
|
||
|
* predSAVE conditional save on this predicate
|
||
|
* rtmp0/rtmp1 two temporary registers (for example %dr20, %dr21)
|
||
|
*/
|
||
|
|
||
|
.macro SAVE_GREGS_PAIR_COND_V2 gpair_lo, gpair_hi, kreg_lo, kreg_hi, rbase, \
|
||
|
predSAVE, rtmp0, rtmp1
|
||
|
{
|
||
|
strd,2 %dg\gpair_lo, [\rbase + (TAGGED_MEM_STORE_REC_OPC + \
|
||
|
\kreg_lo * GLOB_REG_SIZE + \
|
||
|
GLOB_REG_BASE)] ? \predSAVE;
|
||
|
strd,5 %dg\gpair_hi, [\rbase + (TAGGED_MEM_STORE_REC_OPC + \
|
||
|
\kreg_hi * GLOB_REG_SIZE + \
|
||
|
GLOB_REG_BASE)] ? \predSAVE;
|
||
|
movfi,1 %dg\gpair_lo, \rtmp0 ? \predSAVE;
|
||
|
movfi,4 %dg\gpair_hi, \rtmp1 ? \predSAVE;
|
||
|
}
|
||
|
{
|
||
|
sth \rtmp0, [\rbase + (\kreg_lo * GLOB_REG_SIZE + \
|
||
|
GLOB_REG_EXT)] ? \predSAVE;
|
||
|
sth \rtmp1, [\rbase + (\kreg_hi * GLOB_REG_SIZE + \
|
||
|
GLOB_REG_EXT)] ? \predSAVE;
|
||
|
}
|
||
|
.endm /* SAVE_GREGS_PAIR_COND_V2 */
|
||
|
|
||
|
/* Bug 116851 - all strqp must be speculative if dealing with tags */
|
||
|
.macro SAVE_GREGS_PAIR_COND_V5 gpair_lo, gpair_hi, kreg_lo, kreg_hi, rbase, \
|
||
|
predSAVE
|
||
|
{
|
||
|
strqp,2,sm %dg\gpair_lo, [\rbase + (TAGGED_MEM_STORE_REC_OPC + \
|
||
|
\kreg_lo * GLOB_REG_SIZE + \
|
||
|
GLOB_REG_BASE)] ? \predSAVE;
|
||
|
strqp,5,sm %dg\gpair_hi, [\rbase + (TAGGED_MEM_STORE_REC_OPC + \
|
||
|
\kreg_hi * GLOB_REG_SIZE + \
|
||
|
GLOB_REG_BASE)] ? \predSAVE;
|
||
|
}
|
||
|
.endm /* SAVE_GREGS_PAIR_COND_V5 */
|
||
|
|
||
|
.macro SAVE_GREG_UNEXT greg, kreg, rbase
|
||
|
strqp,sm \greg, [\rbase + (TAGGED_MEM_STORE_REC_OPC + \
|
||
|
\kreg * GLOB_REG_SIZE + \
|
||
|
GLOB_REG_BASE)];
|
||
|
.endm /* SAVE_GREG_UNEXT */
|
||
|
|
||
|
.macro SAVE_GREGS_PAIR_UNEXT greg1, greg2, kreg1, kreg2, rbase
|
||
|
{
|
||
|
SAVE_GREG_UNEXT \greg1, kreg1, rbase
|
||
|
SAVE_GREG_UNEXT \greg2, kreg2, rbase
|
||
|
}
|
||
|
.endm /* SAVE_GREGS_PAIR_UNEXT */
|
||
|
|
||
|
.macro ASM_SET_KERNEL_GREGS_PAIR gpair_lo, gpair_hi, rval_lo, rval_hi
|
||
|
{
|
||
|
addd \rval_lo, 0, %dg\gpair_lo;
|
||
|
addd \rval_hi, 0, %dg\gpair_hi;
|
||
|
}
|
||
|
.endm /* ASM_SET_CURRENTS_GREGS_PAIR */
|
||
|
|
||
|
.macro DO_ASM_SET_KERNEL_GREGS_PAIR gpair_lo, gpair_hi, rval_lo, rval_hi
|
||
|
ASM_SET_KERNEL_GREGS_PAIR \gpair_lo, \gpair_hi, \
|
||
|
\rval_lo, \rval_hi
|
||
|
.endm /* DO_ASM_SET_KERNEL_GREGS_PAIR */
|
||
|
|
||
|
.macro SET_KERNEL_GREGS runused, rtask, rpercpu_off, rcpu
|
||
|
DO_ASM_SET_KERNEL_GREGS_PAIR \
|
||
|
GUEST_VCPU_STATE_GREG, CURRENT_TASK_GREG, \
|
||
|
\runused, \rtask
|
||
|
DO_ASM_SET_KERNEL_GREGS_PAIR \
|
||
|
MY_CPU_OFFSET_GREG, SMP_CPU_ID_GREG, \
|
||
|
\rpercpu_off, \rcpu
|
||
|
.endm /* SET_KERNEL_GREGS */
|
||
|
|
||
|
.macro ONLY_SET_KERNEL_GREGS runused, rtask, rpercpu_off, rcpu
|
||
|
SET_KERNEL_GREGS \runused, \rtask, \rpercpu_off, \rcpu
|
||
|
.endm /* ONLY_SET_KERNEL_GREGS */
|
||
|
|
||
|
#ifdef CONFIG_KVM_HOST_MODE
|
||
|
/* it is host kernel with virtualization support */
|
||
|
/* or paravirtualized host and guest kernel */
|
||
|
.macro NEED_SAVE_CUR_AND_VCPU_STATE_GREGS drti, predV5, \
|
||
|
drtmp0, drtmp1, predtmp, \
|
||
|
predCUR, predVCPU, predEXTk
|
||
|
/*
|
||
|
* drti - pointer to thread_info
|
||
|
* predV5 - ISET is V5
|
||
|
* predCUR - is now set to true (trap from user) and can be updated
|
||
|
* to does not save kernel global regs and set current
|
||
|
* Trap at host mode and host kernel currents and other global registers
|
||
|
* (GCURTI & GCURTASK & CPU_ID & CPU_OFF)
|
||
|
* should not be saved to not invalidate guest kernel or user state of
|
||
|
* global registers, which were or will be saved at thread info
|
||
|
* %predVCPU - save VCPU state pointer regs
|
||
|
* predEXTk - need save kernel (predCUR) & need save extention (!predV5)
|
||
|
*
|
||
|
* predCUR = test_thread_flag(TIF_HOST_AT_VCPU_MODE) &&
|
||
|
* !test_thread_flag(TIF_LIGHT_HYPERCALL) ||
|
||
|
* !test_thread_flag(TIF_HOST_AT_VCPU_MODE) &&
|
||
|
* (cr0_hi.CR0_hi_IP >= NATIVE_TASK_SIZE)
|
||
|
* predVCPU = predCUR;
|
||
|
* predEXTk = predCUR & !predV5
|
||
|
*/
|
||
|
{
|
||
|
rrd %cr0.hi, \drtmp0; /* %drtmp0: cr0_hi.IP */
|
||
|
ldd [\drti + TI_FLAGS], \drtmp1; /* %drtmp1: ti->flags */
|
||
|
}
|
||
|
{
|
||
|
cmpbdb \drtmp0, NATIVE_TASK_SIZE, \predtmp;
|
||
|
cmpandedb \drtmp1, _TIF_LIGHT_HYPERCALL, \predCUR;
|
||
|
cmpandedb \drtmp1, _TIF_HOST_AT_VCPU_MODE, \predVCPU;
|
||
|
}
|
||
|
{
|
||
|
nop 1;
|
||
|
pass \predtmp, @p2;
|
||
|
pass \predCUR, @p0;
|
||
|
pass \predVCPU, @p1;
|
||
|
landp @p0, ~@p1, @p4;
|
||
|
pass @p4, \predCUR;
|
||
|
}
|
||
|
{
|
||
|
nop 1;
|
||
|
pass \predVCPU, @p0;
|
||
|
pass \predCUR, @p2;
|
||
|
pass \predtmp, @p1;
|
||
|
landp @p0, ~@p1, @p4;
|
||
|
landp ~@p2, ~@p4, @p5;
|
||
|
landp ~@p2, ~@p4, @p6;
|
||
|
pass @p5, \predCUR;
|
||
|
pass @p6, \predVCPU;
|
||
|
}
|
||
|
{
|
||
|
pass \predV5, @p0;
|
||
|
pass \predCUR, @p1;
|
||
|
landp ~@p0, @p1, @p4;
|
||
|
pass @p4, \predEXTk;
|
||
|
}
|
||
|
.endm /* NEED_SAVE_CUR_AND_VCPU_STATE_GREGS */
|
||
|
|
||
|
.macro DO_SAVE_HOST_GREGS_V2 gvcpu_lo, gvcpu_hi, hvcpu_lo, hvcpu_hi \
|
||
|
drti, predSAVE, drtmp, rtmp0, rtmp1
|
||
|
/* drtmp: thread_info->h_gregs.g */
|
||
|
addd \drti, TI_HOST_GREGS_TO_VIRT, \drtmp ? \predSAVE;
|
||
|
SAVE_GREGS_PAIR_COND_V2 \gvcpu_lo, \gvcpu_hi, \hvcpu_lo, \hvcpu_hi, \
|
||
|
\drtmp, /* thread_info->h_gregs.g base address */ \
|
||
|
\predSAVE, \
|
||
|
\rtmp0, \rtmp1
|
||
|
.endm /* DO_SAVE_HOST_GREGS_V2 */
|
||
|
|
||
|
.macro DO_SAVE_HOST_GREGS_V5 gvcpu_lo, gvcpu_hi, hvcpu_lo, hvcpu_hi \
|
||
|
drti, predSAVE, drtmp
|
||
|
/* drtmp: thread_info->h_gregs.g */
|
||
|
addd \drti, TI_HOST_GREGS_TO_VIRT, \drtmp ? \predSAVE;
|
||
|
SAVE_GREGS_PAIR_COND_V5 \gvcpu_lo, \gvcpu_hi, \hvcpu_lo, \hvcpu_hi, \
|
||
|
\drtmp, /* thread_info->h_gregs.g base address */ \
|
||
|
\predSAVE
|
||
|
.endm /* DO_SAVE_HOST_GREGS_V5 */
|
||
|
|
||
|
.macro SAVE_HOST_GREGS_V2 drti, predSAVE, drtmp, rtmp0, rtmp1
|
||
|
DO_SAVE_HOST_GREGS_V2 \
|
||
|
GUEST_VCPU_STATE_GREG, GUEST_VCPU_STATE_UNUSED_GREG, \
|
||
|
VCPU_STATE_GREGS_PAIRS_INDEX, VCPU_STATE_GREGS_PAIRS_HI_INDEX, \
|
||
|
\drti, \predSAVE, \
|
||
|
\drtmp, \rtmp0, \rtmp1
|
||
|
.endm /* SAVE_HOST_GREGS_V2 */
|
||
|
|
||
|
.macro SAVE_HOST_GREGS_V5 drti, predSAVE, drtmp
|
||
|
DO_SAVE_HOST_GREGS_V5 \
|
||
|
GUEST_VCPU_STATE_GREG, GUEST_VCPU_STATE_UNUSED_GREG, \
|
||
|
VCPU_STATE_GREGS_PAIRS_INDEX, VCPU_STATE_GREGS_PAIRS_HI_INDEX, \
|
||
|
\drti, \predSAVE, \
|
||
|
\drtmp,
|
||
|
.endm /* SAVE_HOST_GREGS_V5 */
|
||
|
|
||
|
.macro SAVE_HOST_GREGS_TO_VIRT_V2 drti, predSAVE, drtmp, rtmp0, rtmp1
|
||
|
SAVE_HOST_GREGS_V2 \drti, \predSAVE, \drtmp, \rtmp0, \rtmp1
|
||
|
.endm /* SAVE_HOST_GREGS_TO_VIRT_V2 */
|
||
|
|
||
|
.macro SAVE_HOST_GREGS_TO_VIRT_V5 drti, predSAVE, drtmp
|
||
|
SAVE_HOST_GREGS_V5 \drti, \predSAVE, \drtmp
|
||
|
.endm /* SAVE_HOST_GREGS_TO_VIRT_V5 */
|
||
|
|
||
|
.macro SAVE_HOST_GREGS_TO_VIRT_UNEXT drti, drtmp
|
||
|
/* not used */
|
||
|
.endm /* SAVE_HOST_GREGS_TO_VIRT_UNEXT */
|
||
|
|
||
|
#elif defined(CONFIG_KVM_GUEST_KERNEL)
|
||
|
/* it is pure guest kernel (not paravirtualized based on pv_ops) */
|
||
|
#include <asm/kvm/guest/trap_table.S.h>
|
||
|
#else /* ! CONFIG_KVM_HOST_MODE && ! CONFIG_KVM_GUEST_KERNEL */
|
||
|
/* It is native host kernel without any virtualization */
|
||
|
.macro NEED_SAVE_CUR_AND_VCPU_STATE_GREGS drti, predV5, \
|
||
|
drtmp0, drtmp1, predtmp, \
|
||
|
predCUR, predVCPU, predEXTk
|
||
|
/*
|
||
|
* drti - pointer to thread_info (unused)
|
||
|
* predV5 - ISET is V5
|
||
|
* predCUR - save kernel global regs and set current (already
|
||
|
* calculated, don't update)
|
||
|
* %predVCPU - set to false (none any VCPUs)
|
||
|
* predEXTk - need save kernel (predCUR) & need save extention (!predV5)
|
||
|
*/
|
||
|
{
|
||
|
pass \predV5, @p0;
|
||
|
pass \predCUR, @p1;
|
||
|
landp ~@p0, @p1, @p4;
|
||
|
landp ~@p1, @p1, @p5;
|
||
|
pass @p4, \predEXTk;
|
||
|
pass @p5, \predVCPU;
|
||
|
}
|
||
|
.endm /* NEED_SAVE_CUR_AND_VCPU_STATE_GREGS */
|
||
|
|
||
|
.macro SAVE_HOST_GREGS_TO_VIRT_V2 drti, predSAVE, drtmp, rtmp0, rtmp1
|
||
|
/* not used */
|
||
|
.endm /* SAVE_VCPU_STATE_GREGS */
|
||
|
|
||
|
.macro SAVE_HOST_GREGS_TO_VIRT_V5 drti, predSAVE, drtmp
|
||
|
/* not used */
|
||
|
.endm /* SAVE_GREGS_TO_VIRT */
|
||
|
|
||
|
.macro SAVE_HOST_GREGS_TO_VIRT_UNEXT drti, drtmp
|
||
|
/* not used */
|
||
|
.endm /* SAVE_HOST_GREGS_TO_VIRT_UNEXT */
|
||
|
|
||
|
#endif /* CONFIG_KVM_HOST_MODE */
|
||
|
|
||
|
/*
|
||
|
* same as C function above but as result should be set %pred28
|
||
|
* argument sys_num_reg_no is assembler register number containing # of
|
||
|
* system call (for example %r0)
|
||
|
* %pred28 == 1 if system call is generic and doesn use pt_regs structure
|
||
|
*/
|
||
|
.macro IS_SYS_CALL_GENERIC sys_num_reg_no
|
||
|
cmpesb sys_num_reg_no, __NR_clone, %pred0;
|
||
|
cmpesb sys_num_reg_no, __NR_clone_thread, %pred1;
|
||
|
cmpesb sys_num_reg_no, __NR_fork, %pred2;
|
||
|
cmpesb sys_num_reg_no, __NR_vfork, %pred3;
|
||
|
{
|
||
|
pass %pred0, @p0;
|
||
|
pass %pred1, @p1;
|
||
|
pass %pred2, @p2;
|
||
|
pass %pred3, @p3;
|
||
|
andp ~@p0, ~@p1, @p4;
|
||
|
andp ~@p2, ~@p3, @p5;
|
||
|
andp @p4, @p5, @p6;
|
||
|
pass @p6, %pred27;
|
||
|
}
|
||
|
cmpesb sys_num_reg_no, __NR_execve, %pred4;
|
||
|
cmpesb sys_num_reg_no, __NR_rt_sigreturn, %pred5;
|
||
|
cmpesb sys_num_reg_no, __NR_e2k_sigsetjmp, %pred6;
|
||
|
cmpesb sys_num_reg_no, __NR_e2k_longjmp, %pred7;
|
||
|
{
|
||
|
pass %pred4, @p0;
|
||
|
pass %pred5, @p1;
|
||
|
pass %pred6, @p2;
|
||
|
pass %pred7, @p3;
|
||
|
andp ~@p0, ~@p1, @p4;
|
||
|
andp ~@p2, ~@p3, @p5;
|
||
|
andp @p4, @p5, @p6;
|
||
|
pass @p6, %pred30;
|
||
|
}
|
||
|
cmpesb sys_num_reg_no, __NR_e2k_longjmp2, %pred8;
|
||
|
cmpesb sys_num_reg_no, __NR_sigaltstack, %pred9;
|
||
|
cmpesb sys_num_reg_no, __NR_rt_sigaction, %pred10;
|
||
|
cmpesb sys_num_reg_no, __NR_rt_sigsuspend, %pred11;
|
||
|
{
|
||
|
pass %pred8, @p0;
|
||
|
pass %pred9, @p1;
|
||
|
pass %pred10, @p2;
|
||
|
pass %pred11, @p3;
|
||
|
andp ~@p0, ~@p1, @p4;
|
||
|
andp ~@p2, ~@p3, @p5;
|
||
|
andp @p4, @p5, @p6;
|
||
|
pass @p6, %pred29;
|
||
|
}
|
||
|
{
|
||
|
nop 2;
|
||
|
pass %pred27, @p0;
|
||
|
pass %pred30, @p1;
|
||
|
pass %pred29, @p2;
|
||
|
andp @p0, @p1, @p4;
|
||
|
andp @p2, @p4, @p5;
|
||
|
pass @p5, %pred28;
|
||
|
}
|
||
|
cmpesb sys_num_reg_no, __NR_ioctl, %pred13;
|
||
|
cmpesb sys_num_reg_no, __NR_ipc, %pred14;
|
||
|
{
|
||
|
pass %pred13, @p0;
|
||
|
pass %pred14, @p1;
|
||
|
pass %pred28, @p2;
|
||
|
andp ~@p0, ~@p1, @p4;
|
||
|
andp @p2, @p4, @p5;
|
||
|
pass @p5, %pred28;
|
||
|
}
|
||
|
.endm /* IS_SYS_CALL_GENERIC */
|
||
|
|
||
|
#endif /* __ASSEMBLY__ */
|
||
|
|
||
|
#endif /* _E2K_KVM_TRAP_TABLE_ASM_H */
|