diff options
Diffstat (limited to 'arch/x86/kvm/emulate.c')
| -rw-r--r-- | arch/x86/kvm/emulate.c | 103 | 
1 files changed, 61 insertions, 42 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 28b1a4e57827..50ca1db7247c 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -175,6 +175,7 @@  #define No16	    ((u64)1 << 53)  /* No 16 bit operand */  #define IncSP       ((u64)1 << 54)  /* SP is incremented before ModRM calc */  #define TwoMemOp    ((u64)1 << 55)  /* Instruction has two memory operand */ +#define IsBranch    ((u64)1 << 56)  /* Instruction is considered a branch. */  #define DstXacc     (DstAccLo | SrcAccHi | SrcWrite) @@ -191,8 +192,9 @@  #define FASTOP_SIZE 8  struct opcode { -	u64 flags : 56; -	u64 intercept : 8; +	u64 flags; +	u8 intercept; +	u8 pad[7];  	union {  		int (*execute)(struct x86_emulate_ctxt *ctxt);  		const struct opcode *group; @@ -315,7 +317,7 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);  	__FOP_FUNC(#name)  #define __FOP_RET(name) \ -	"ret \n\t" \ +	"11: " ASM_RET \  	".size " name ", .-" name "\n\t"  #define FOP_RET(name) \ @@ -344,7 +346,7 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);  	__FOP_RET(#op "_" #dst)  #define FOP1EEX(op,  dst) \ -	FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception) +	FOP1E(op, dst) _ASM_EXTABLE_TYPE_REG(10b, 11b, EX_TYPE_ZERO_REG, %%esi)  #define FASTOP1(op) \  	FOP_START(op) \ @@ -427,17 +429,28 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);  	FOP_END  /* Special case for SETcc - 1 instruction per cc */ + +/* + * Depending on .config the SETcc functions look like: + * + * SETcc %al   [3 bytes] + * RET         [1 byte] + * INT3        [1 byte; CONFIG_SLS] + * + * Which gives possible sizes 4 or 5.  When rounded up to the + * next power-of-two alignment they become 4 or 8. + */ +#define SETCC_LENGTH	(4 + IS_ENABLED(CONFIG_SLS)) +#define SETCC_ALIGN	(4 << IS_ENABLED(CONFIG_SLS)) +static_assert(SETCC_LENGTH <= SETCC_ALIGN); +  #define FOP_SETCC(op) \ -	".align 4 \n\t" \ +	".align " __stringify(SETCC_ALIGN) " \n\t" \  	".type " #op ", @function \n\t" \  	#op ": \n\t" \  	#op " %al \n\t" \  	__FOP_RET(#op) -asm(".pushsection .fixup, \"ax\"\n" -    "kvm_fastop_exception: xor %esi, %esi; ret\n" -    ".popsection"); -  FOP_START(setcc)  FOP_SETCC(seto)  FOP_SETCC(setno) @@ -473,12 +486,8 @@ FOP_END;   \  	asm volatile("1:" insn "\n" \  	             "2:\n" \ -	             ".pushsection .fixup, \"ax\"\n" \ -	             "3: movl $1, %[_fault]\n" \ -	             "   jmp  2b\n" \ -	             ".popsection\n" \ -	             _ASM_EXTABLE(1b, 3b) \ -	             : [_fault] "+qm"(_fault) inoutclob ); \ +		     _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_ONE_REG, %[_fault]) \ +	             : [_fault] "+r"(_fault) inoutclob ); \   \  	_fault ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; \  }) @@ -671,7 +680,7 @@ static inline u8 ctxt_virt_addr_bits(struct x86_emulate_ctxt *ctxt)  static inline bool emul_is_noncanonical_address(u64 la,  						struct x86_emulate_ctxt *ctxt)  { -	return get_canonical(la, ctxt_virt_addr_bits(ctxt)) != la; +	return !__is_canonical_address(la, ctxt_virt_addr_bits(ctxt));  }  /* @@ -721,7 +730,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,  	case X86EMUL_MODE_PROT64:  		*linear = la;  		va_bits = ctxt_virt_addr_bits(ctxt); -		if (get_canonical(la, va_bits) != la) +		if (!__is_canonical_address(la, va_bits))  			goto bad;  		*max_size = min_t(u64, ~0u, (1ull << va_bits) - la); @@ -1053,7 +1062,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)  static __always_inline u8 test_cc(unsigned int condition, unsigned long flags)  {  	u8 rc; -	void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf); +	void (*fop)(void) = (void *)em_setcc + SETCC_ALIGN * (condition & 0xf);  	flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF;  	asm("push %[flags]; popf; " CALL_NOSPEC @@ -4364,10 +4373,10 @@ static const struct opcode group4[] = {  static const struct opcode group5[] = {  	F(DstMem | SrcNone | Lock,		em_inc),  	F(DstMem | SrcNone | Lock,		em_dec), -	I(SrcMem | NearBranch,			em_call_near_abs), -	I(SrcMemFAddr | ImplicitOps,		em_call_far), -	I(SrcMem | NearBranch,			em_jmp_abs), -	I(SrcMemFAddr | ImplicitOps,		em_jmp_far), +	I(SrcMem | NearBranch | IsBranch,       em_call_near_abs), +	I(SrcMemFAddr | ImplicitOps | IsBranch, em_call_far), +	I(SrcMem | NearBranch | IsBranch,       em_jmp_abs), +	I(SrcMemFAddr | ImplicitOps | IsBranch, em_jmp_far),  	I(SrcMem | Stack | TwoMemOp,		em_push), D(Undefined),  }; @@ -4577,7 +4586,7 @@ static const struct opcode opcode_table[256] = {  	I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_in), /* insb, insw/insd */  	I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, outsw/outsd */  	/* 0x70 - 0x7F */ -	X16(D(SrcImmByte | NearBranch)), +	X16(D(SrcImmByte | NearBranch | IsBranch)),  	/* 0x80 - 0x87 */  	G(ByteOp | DstMem | SrcImm, group1),  	G(DstMem | SrcImm, group1), @@ -4596,7 +4605,7 @@ static const struct opcode opcode_table[256] = {  	DI(SrcAcc | DstReg, pause), X7(D(SrcAcc | DstReg)),  	/* 0x98 - 0x9F */  	D(DstAcc | SrcNone), I(ImplicitOps | SrcAcc, em_cwd), -	I(SrcImmFAddr | No64, em_call_far), N, +	I(SrcImmFAddr | No64 | IsBranch, em_call_far), N,  	II(ImplicitOps | Stack, em_pushf, pushf),  	II(ImplicitOps | Stack, em_popf, popf),  	I(ImplicitOps, em_sahf), I(ImplicitOps, em_lahf), @@ -4616,17 +4625,19 @@ static const struct opcode opcode_table[256] = {  	X8(I(DstReg | SrcImm64 | Mov, em_mov)),  	/* 0xC0 - 0xC7 */  	G(ByteOp | Src2ImmByte, group2), G(Src2ImmByte, group2), -	I(ImplicitOps | NearBranch | SrcImmU16, em_ret_near_imm), -	I(ImplicitOps | NearBranch, em_ret), +	I(ImplicitOps | NearBranch | SrcImmU16 | IsBranch, em_ret_near_imm), +	I(ImplicitOps | NearBranch | IsBranch, em_ret),  	I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg),  	I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),  	G(ByteOp, group11), G(0, group11),  	/* 0xC8 - 0xCF */ -	I(Stack | SrcImmU16 | Src2ImmByte, em_enter), I(Stack, em_leave), -	I(ImplicitOps | SrcImmU16, em_ret_far_imm), -	I(ImplicitOps, em_ret_far), -	D(ImplicitOps), DI(SrcImmByte, intn), -	D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret), +	I(Stack | SrcImmU16 | Src2ImmByte | IsBranch, em_enter), +	I(Stack | IsBranch, em_leave), +	I(ImplicitOps | SrcImmU16 | IsBranch, em_ret_far_imm), +	I(ImplicitOps | IsBranch, em_ret_far), +	D(ImplicitOps | IsBranch), DI(SrcImmByte | IsBranch, intn), +	D(ImplicitOps | No64 | IsBranch), +	II(ImplicitOps | IsBranch, em_iret, iret),  	/* 0xD0 - 0xD7 */  	G(Src2One | ByteOp, group2), G(Src2One, group2),  	G(Src2CL | ByteOp, group2), G(Src2CL, group2), @@ -4637,14 +4648,15 @@ static const struct opcode opcode_table[256] = {  	/* 0xD8 - 0xDF */  	N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N,  	/* 0xE0 - 0xE7 */ -	X3(I(SrcImmByte | NearBranch, em_loop)), -	I(SrcImmByte | NearBranch, em_jcxz), +	X3(I(SrcImmByte | NearBranch | IsBranch, em_loop)), +	I(SrcImmByte | NearBranch | IsBranch, em_jcxz),  	I2bvIP(SrcImmUByte | DstAcc, em_in,  in,  check_perm_in),  	I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out),  	/* 0xE8 - 0xEF */ -	I(SrcImm | NearBranch, em_call), D(SrcImm | ImplicitOps | NearBranch), -	I(SrcImmFAddr | No64, em_jmp_far), -	D(SrcImmByte | ImplicitOps | NearBranch), +	I(SrcImm | NearBranch | IsBranch, em_call), +	D(SrcImm | ImplicitOps | NearBranch | IsBranch), +	I(SrcImmFAddr | No64 | IsBranch, em_jmp_far), +	D(SrcImmByte | ImplicitOps | NearBranch | IsBranch),  	I2bvIP(SrcDX | DstAcc, em_in,  in,  check_perm_in),  	I2bvIP(SrcAcc | DstDX, em_out, out, check_perm_out),  	/* 0xF0 - 0xF7 */ @@ -4660,7 +4672,7 @@ static const struct opcode opcode_table[256] = {  static const struct opcode twobyte_table[256] = {  	/* 0x00 - 0x0F */  	G(0, group6), GD(0, &group7), N, N, -	N, I(ImplicitOps | EmulateOnUD, em_syscall), +	N, I(ImplicitOps | EmulateOnUD | IsBranch, em_syscall),  	II(ImplicitOps | Priv, em_clts, clts), N,  	DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,  	N, D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N, @@ -4691,8 +4703,8 @@ static const struct opcode twobyte_table[256] = {  	IIP(ImplicitOps, em_rdtsc, rdtsc, check_rdtsc),  	II(ImplicitOps | Priv, em_rdmsr, rdmsr),  	IIP(ImplicitOps, em_rdpmc, rdpmc, check_rdpmc), -	I(ImplicitOps | EmulateOnUD, em_sysenter), -	I(ImplicitOps | Priv | EmulateOnUD, em_sysexit), +	I(ImplicitOps | EmulateOnUD | IsBranch, em_sysenter), +	I(ImplicitOps | Priv | EmulateOnUD | IsBranch, em_sysexit),  	N, N,  	N, N, N, N, N, N, N, N,  	/* 0x40 - 0x4F */ @@ -4710,7 +4722,7 @@ static const struct opcode twobyte_table[256] = {  	N, N, N, N,  	N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_6f_0f_7f),  	/* 0x80 - 0x8F */ -	X16(D(SrcImm | NearBranch)), +	X16(D(SrcImm | NearBranch | IsBranch)),  	/* 0x90 - 0x9F */  	X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),  	/* 0xA0 - 0xA7 */ @@ -5224,6 +5236,8 @@ done_prefixes:  		ctxt->d |= opcode.flags;  	} +	ctxt->is_branch = opcode.flags & IsBranch; +  	/* Unrecognised? */  	if (ctxt->d == 0)  		return EMULATION_FAILED; @@ -5381,8 +5395,13 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop)  void init_decode_cache(struct x86_emulate_ctxt *ctxt)  { -	memset(&ctxt->rip_relative, 0, -	       (void *)&ctxt->modrm - (void *)&ctxt->rip_relative); +	/* Clear fields that are set conditionally but read without a guard. */ +	ctxt->rip_relative = false; +	ctxt->rex_prefix = 0; +	ctxt->lock_prefix = 0; +	ctxt->rep_prefix = 0; +	ctxt->regs_valid = 0; +	ctxt->regs_dirty = 0;  	ctxt->io_read.pos = 0;  	ctxt->io_read.end = 0;  |