aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/kvm_x86_emulate.h3
-rw-r--r--arch/x86/kvm/x86.c6
-rw-r--r--arch/x86/kvm/x86_emulate.c20
3 files changed, 28 insertions, 1 deletions
diff --git a/arch/x86/include/asm/kvm_x86_emulate.h b/arch/x86/include/asm/kvm_x86_emulate.h
index be40d6e2b6bb..b7ed2c423116 100644
--- a/arch/x86/include/asm/kvm_x86_emulate.h
+++ b/arch/x86/include/asm/kvm_x86_emulate.h
@@ -155,6 +155,9 @@ struct x86_emulate_ctxt {
155 int mode; 155 int mode;
156 u32 cs_base; 156 u32 cs_base;
157 157
158 /* interruptibility state, as a result of execution of STI or MOV SS */
159 int interruptibility;
160
158 /* decode cache */ 161 /* decode cache */
159 struct decode_cache decode; 162 struct decode_cache decode;
160}; 163};
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7475b029b2ad..48f744ff0bc1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2379,7 +2379,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
2379 u16 error_code, 2379 u16 error_code,
2380 int emulation_type) 2380 int emulation_type)
2381{ 2381{
2382 int r; 2382 int r, shadow_mask;
2383 struct decode_cache *c; 2383 struct decode_cache *c;
2384 2384
2385 kvm_clear_exception_queue(vcpu); 2385 kvm_clear_exception_queue(vcpu);
@@ -2433,6 +2433,10 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
2433 } 2433 }
2434 2434
2435 r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); 2435 r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
2436 shadow_mask = vcpu->arch.emulate_ctxt.interruptibility;
2437
2438 if (r == 0)
2439 kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask);
2436 2440
2437 if (vcpu->arch.pio.string) 2441 if (vcpu->arch.pio.string)
2438 return EMULATE_DO_MMIO; 2442 return EMULATE_DO_MMIO;
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c
index d2664fcba7fa..c1b6c232e02b 100644
--- a/arch/x86/kvm/x86_emulate.c
+++ b/arch/x86/kvm/x86_emulate.c
@@ -1361,6 +1361,20 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
1361 return 0; 1361 return 0;
1362} 1362}
1363 1363
1364void toggle_interruptibility(struct x86_emulate_ctxt *ctxt, u32 mask)
1365{
1366 u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(ctxt->vcpu, mask);
1367 /*
1368 * an sti; sti; sequence only disable interrupts for the first
1369 * instruction. So, if the last instruction, be it emulated or
1370 * not, left the system with the INT_STI flag enabled, it
1371 * means that the last instruction is an sti. We should not
1372 * leave the flag on in this case. The same goes for mov ss
1373 */
1374 if (!(int_shadow & mask))
1375 ctxt->interruptibility = mask;
1376}
1377
1364int 1378int
1365x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) 1379x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1366{ 1380{
@@ -1372,6 +1386,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1372 int io_dir_in; 1386 int io_dir_in;
1373 int rc = 0; 1387 int rc = 0;
1374 1388
1389 ctxt->interruptibility = 0;
1390
1375 /* Shadow copy of register state. Committed on successful emulation. 1391 /* Shadow copy of register state. Committed on successful emulation.
1376 * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't 1392 * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
1377 * modify them. 1393 * modify them.
@@ -1618,6 +1634,9 @@ special_insn:
1618 int err; 1634 int err;
1619 1635
1620 sel = c->src.val; 1636 sel = c->src.val;
1637 if (c->modrm_reg == VCPU_SREG_SS)
1638 toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS);
1639
1621 if (c->modrm_reg <= 5) { 1640 if (c->modrm_reg <= 5) {
1622 type_bits = (c->modrm_reg == 1) ? 9 : 1; 1641 type_bits = (c->modrm_reg == 1) ? 9 : 1;
1623 err = kvm_load_segment_descriptor(ctxt->vcpu, sel, 1642 err = kvm_load_segment_descriptor(ctxt->vcpu, sel,
@@ -1847,6 +1866,7 @@ special_insn:
1847 c->dst.type = OP_NONE; /* Disable writeback. */ 1866 c->dst.type = OP_NONE; /* Disable writeback. */
1848 break; 1867 break;
1849 case 0xfb: /* sti */ 1868 case 0xfb: /* sti */
1869 toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
1850 ctxt->eflags |= X86_EFLAGS_IF; 1870 ctxt->eflags |= X86_EFLAGS_IF;
1851 c->dst.type = OP_NONE; /* Disable writeback. */ 1871 c->dst.type = OP_NONE; /* Disable writeback. */
1852 break; 1872 break;