aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-03-27 06:58:02 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-07-11 03:13:58 -0400
commitd40a6898e50c2589ca3d345ef5ca6671e2b35b1a (patch)
tree774afe302d8a79ce59bdc17f8d213e5d4564b9ed /arch/x86/kvm
parente24186e097b80c5995ff75e1bbcd541d09c9e42b (diff)
KVM: emulate: protect checks on ctxt->d by a common "if (unlikely())"
There are several checks for "peculiar" aspects of instructions in both x86_decode_insn and x86_emulate_insn. Group them together, and guard them with a single "if" that lets the processor quickly skip them all. Make this more effective by adding two more flag bits that say whether the .intercept and .check_perm fields are valid. We will reuse these flags later to avoid initializing fields of the emulate_ctxt struct. This skims about 30 cycles for each emulated instructions, which is approximately a 3% improvement. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/emulate.c175
1 files changed, 94 insertions, 81 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index d79677c6056d..ea56dae3e67c 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -162,6 +162,8 @@
162#define NoWrite ((u64)1 << 45) /* No writeback */ 162#define NoWrite ((u64)1 << 45) /* No writeback */
163#define SrcWrite ((u64)1 << 46) /* Write back src operand */ 163#define SrcWrite ((u64)1 << 46) /* Write back src operand */
164#define NoMod ((u64)1 << 47) /* Mod field is ignored */ 164#define NoMod ((u64)1 << 47) /* Mod field is ignored */
165#define Intercept ((u64)1 << 48) /* Has valid intercept field */
166#define CheckPerm ((u64)1 << 49) /* Has valid check_perm field */
165 167
166#define DstXacc (DstAccLo | SrcAccHi | SrcWrite) 168#define DstXacc (DstAccLo | SrcAccHi | SrcWrite)
167 169
@@ -3546,9 +3548,9 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
3546} 3548}
3547 3549
3548#define D(_y) { .flags = (_y) } 3550#define D(_y) { .flags = (_y) }
3549#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } 3551#define DI(_y, _i) { .flags = (_y)|Intercept, .intercept = x86_intercept_##_i }
3550#define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \ 3552#define DIP(_y, _i, _p) { .flags = (_y)|Intercept|CheckPerm, \
3551 .check_perm = (_p) } 3553 .intercept = x86_intercept_##_i, .check_perm = (_p) }
3552#define N D(NotImpl) 3554#define N D(NotImpl)
3553#define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) } 3555#define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) }
3554#define G(_f, _g) { .flags = ((_f) | Group | ModRM), .u.group = (_g) } 3556#define G(_f, _g) { .flags = ((_f) | Group | ModRM), .u.group = (_g) }
@@ -3557,10 +3559,10 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
3557#define I(_f, _e) { .flags = (_f), .u.execute = (_e) } 3559#define I(_f, _e) { .flags = (_f), .u.execute = (_e) }
3558#define F(_f, _e) { .flags = (_f) | Fastop, .u.fastop = (_e) } 3560#define F(_f, _e) { .flags = (_f) | Fastop, .u.fastop = (_e) }
3559#define II(_f, _e, _i) \ 3561#define II(_f, _e, _i) \
3560 { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i } 3562 { .flags = (_f)|Intercept, .u.execute = (_e), .intercept = x86_intercept_##_i }
3561#define IIP(_f, _e, _i, _p) \ 3563#define IIP(_f, _e, _i, _p) \
3562 { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i, \ 3564 { .flags = (_f)|Intercept|CheckPerm, .u.execute = (_e), \
3563 .check_perm = (_p) } 3565 .intercept = x86_intercept_##_i, .check_perm = (_p) }
3564#define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) } 3566#define GP(_f, _g) { .flags = ((_f) | Prefix), .u.gprefix = (_g) }
3565 3567
3566#define D2bv(_f) D((_f) | ByteOp), D(_f) 3568#define D2bv(_f) D((_f) | ByteOp), D(_f)
@@ -4393,29 +4395,37 @@ done_prefixes:
4393 return EMULATION_FAILED; 4395 return EMULATION_FAILED;
4394 4396
4395 ctxt->execute = opcode.u.execute; 4397 ctxt->execute = opcode.u.execute;
4396 ctxt->check_perm = opcode.check_perm;
4397 ctxt->intercept = opcode.intercept;
4398 4398
4399 if (ctxt->d & NotImpl) 4399 if (unlikely(ctxt->d &
4400 return EMULATION_FAILED; 4400 (NotImpl|EmulateOnUD|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm))) {
4401 /*
4402 * These are copied unconditionally here, and checked unconditionally
4403 * in x86_emulate_insn.
4404 */
4405 ctxt->check_perm = opcode.check_perm;
4406 ctxt->intercept = opcode.intercept;
4401 4407
4402 if (!(ctxt->d & EmulateOnUD) && ctxt->ud) 4408 if (ctxt->d & NotImpl)
4403 return EMULATION_FAILED; 4409 return EMULATION_FAILED;
4404 4410
4405 if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack)) 4411 if (!(ctxt->d & EmulateOnUD) && ctxt->ud)
4406 ctxt->op_bytes = 8; 4412 return EMULATION_FAILED;
4407 4413
4408 if (ctxt->d & Op3264) { 4414 if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack))
4409 if (mode == X86EMUL_MODE_PROT64)
4410 ctxt->op_bytes = 8; 4415 ctxt->op_bytes = 8;
4411 else
4412 ctxt->op_bytes = 4;
4413 }
4414 4416
4415 if (ctxt->d & Sse) 4417 if (ctxt->d & Op3264) {
4416 ctxt->op_bytes = 16; 4418 if (mode == X86EMUL_MODE_PROT64)
4417 else if (ctxt->d & Mmx) 4419 ctxt->op_bytes = 8;
4418 ctxt->op_bytes = 8; 4420 else
4421 ctxt->op_bytes = 4;
4422 }
4423
4424 if (ctxt->d & Sse)
4425 ctxt->op_bytes = 16;
4426 else if (ctxt->d & Mmx)
4427 ctxt->op_bytes = 8;
4428 }
4419 4429
4420 /* ModRM and SIB bytes. */ 4430 /* ModRM and SIB bytes. */
4421 if (ctxt->d & ModRM) { 4431 if (ctxt->d & ModRM) {
@@ -4549,75 +4559,78 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
4549 goto done; 4559 goto done;
4550 } 4560 }
4551 4561
4552 if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) || 4562 if (unlikely(ctxt->d &
4553 (ctxt->d & Undefined)) { 4563 (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
4554 rc = emulate_ud(ctxt); 4564 if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
4555 goto done; 4565 (ctxt->d & Undefined)) {
4556 } 4566 rc = emulate_ud(ctxt);
4557 4567 goto done;
4558 if (((ctxt->d & (Sse|Mmx)) && ((ops->get_cr(ctxt, 0) & X86_CR0_EM))) 4568 }
4559 || ((ctxt->d & Sse) && !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
4560 rc = emulate_ud(ctxt);
4561 goto done;
4562 }
4563
4564 if ((ctxt->d & (Sse|Mmx)) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
4565 rc = emulate_nm(ctxt);
4566 goto done;
4567 }
4568 4569
4569 if (ctxt->d & Mmx) { 4570 if (((ctxt->d & (Sse|Mmx)) && ((ops->get_cr(ctxt, 0) & X86_CR0_EM)))
4570 rc = flush_pending_x87_faults(ctxt); 4571 || ((ctxt->d & Sse) && !(ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))) {
4571 if (rc != X86EMUL_CONTINUE) 4572 rc = emulate_ud(ctxt);
4572 goto done; 4573 goto done;
4573 /* 4574 }
4574 * Now that we know the fpu is exception safe, we can fetch
4575 * operands from it.
4576 */
4577 fetch_possible_mmx_operand(ctxt, &ctxt->src);
4578 fetch_possible_mmx_operand(ctxt, &ctxt->src2);
4579 if (!(ctxt->d & Mov))
4580 fetch_possible_mmx_operand(ctxt, &ctxt->dst);
4581 }
4582 4575
4583 if (unlikely(ctxt->guest_mode) && ctxt->intercept) { 4576 if ((ctxt->d & (Sse|Mmx)) && (ops->get_cr(ctxt, 0) & X86_CR0_TS)) {
4584 rc = emulator_check_intercept(ctxt, ctxt->intercept, 4577 rc = emulate_nm(ctxt);
4585 X86_ICPT_PRE_EXCEPT);
4586 if (rc != X86EMUL_CONTINUE)
4587 goto done; 4578 goto done;
4588 } 4579 }
4589 4580
4590 /* Privileged instruction can be executed only in CPL=0 */ 4581 if (ctxt->d & Mmx) {
4591 if ((ctxt->d & Priv) && ops->cpl(ctxt)) { 4582 rc = flush_pending_x87_faults(ctxt);
4592 rc = emulate_gp(ctxt, 0); 4583 if (rc != X86EMUL_CONTINUE)
4593 goto done; 4584 goto done;
4594 } 4585 /*
4586 * Now that we know the fpu is exception safe, we can fetch
4587 * operands from it.
4588 */
4589 fetch_possible_mmx_operand(ctxt, &ctxt->src);
4590 fetch_possible_mmx_operand(ctxt, &ctxt->src2);
4591 if (!(ctxt->d & Mov))
4592 fetch_possible_mmx_operand(ctxt, &ctxt->dst);
4593 }
4595 4594
4596 /* Instruction can only be executed in protected mode */ 4595 if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
4597 if ((ctxt->d & Prot) && ctxt->mode < X86EMUL_MODE_PROT16) { 4596 rc = emulator_check_intercept(ctxt, ctxt->intercept,
4598 rc = emulate_ud(ctxt); 4597 X86_ICPT_PRE_EXCEPT);
4599 goto done; 4598 if (rc != X86EMUL_CONTINUE)
4600 } 4599 goto done;
4600 }
4601 4601
4602 /* Do instruction specific permission checks */ 4602 /* Privileged instruction can be executed only in CPL=0 */
4603 if (ctxt->check_perm) { 4603 if ((ctxt->d & Priv) && ops->cpl(ctxt)) {
4604 rc = ctxt->check_perm(ctxt); 4604 rc = emulate_gp(ctxt, 0);
4605 if (rc != X86EMUL_CONTINUE)
4606 goto done; 4605 goto done;
4607 } 4606 }
4608 4607
4609 if (unlikely(ctxt->guest_mode) && ctxt->intercept) { 4608 /* Instruction can only be executed in protected mode */
4610 rc = emulator_check_intercept(ctxt, ctxt->intercept, 4609 if ((ctxt->d & Prot) && ctxt->mode < X86EMUL_MODE_PROT16) {
4611 X86_ICPT_POST_EXCEPT); 4610 rc = emulate_ud(ctxt);
4612 if (rc != X86EMUL_CONTINUE)
4613 goto done; 4611 goto done;
4614 } 4612 }
4615 4613
4616 if (ctxt->rep_prefix && (ctxt->d & String)) { 4614 /* Do instruction specific permission checks */
4617 /* All REP prefixes have the same first termination condition */ 4615 if (ctxt->check_perm) {
4618 if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) { 4616 rc = ctxt->check_perm(ctxt);
4619 ctxt->eip = ctxt->_eip; 4617 if (rc != X86EMUL_CONTINUE)
4620 goto done; 4618 goto done;
4619 }
4620
4621 if (unlikely(ctxt->guest_mode) && ctxt->intercept) {
4622 rc = emulator_check_intercept(ctxt, ctxt->intercept,
4623 X86_ICPT_POST_EXCEPT);
4624 if (rc != X86EMUL_CONTINUE)
4625 goto done;
4626 }
4627
4628 if (ctxt->rep_prefix && (ctxt->d & String)) {
4629 /* All REP prefixes have the same first termination condition */
4630 if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) {
4631 ctxt->eip = ctxt->_eip;
4632 goto done;
4633 }
4621 } 4634 }
4622 } 4635 }
4623 4636