aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/svm.c2
-rw-r--r--arch/x86/kvm/vmx.c2
-rw-r--r--arch/x86/kvm/x86.c18
-rw-r--r--include/asm-x86/kvm_host.h4
4 files changed, 20 insertions, 6 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 33f77b044c52..de755cb1431d 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -942,7 +942,7 @@ static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
942{ 942{
943 int er; 943 int er;
944 944
945 er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0); 945 er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0, EMULTYPE_TRAP_UD);
946 if (er != EMULATE_DONE) 946 if (er != EMULATE_DONE)
947 kvm_queue_exception(&svm->vcpu, UD_VECTOR); 947 kvm_queue_exception(&svm->vcpu, UD_VECTOR);
948 return 1; 948 return 1;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 3d251f894a8d..ad36447e696e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1863,7 +1863,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1863 } 1863 }
1864 1864
1865 if (is_invalid_opcode(intr_info)) { 1865 if (is_invalid_opcode(intr_info)) {
1866 er = emulate_instruction(vcpu, kvm_run, 0, 0, 0); 1866 er = emulate_instruction(vcpu, kvm_run, 0, 0, EMULTYPE_TRAP_UD);
1867 if (er != EMULATE_DONE) 1867 if (er != EMULATE_DONE)
1868 kvm_queue_exception(vcpu, UD_VECTOR); 1868 kvm_queue_exception(vcpu, UD_VECTOR);
1869 return 1; 1869 return 1;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e3b3141db13c..8a90403272e2 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1840,9 +1840,10 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
1840 struct kvm_run *run, 1840 struct kvm_run *run,
1841 unsigned long cr2, 1841 unsigned long cr2,
1842 u16 error_code, 1842 u16 error_code,
1843 int no_decode) 1843 int emulation_type)
1844{ 1844{
1845 int r; 1845 int r;
1846 struct decode_cache *c;
1846 1847
1847 vcpu->arch.mmio_fault_cr2 = cr2; 1848 vcpu->arch.mmio_fault_cr2 = cr2;
1848 kvm_x86_ops->cache_regs(vcpu); 1849 kvm_x86_ops->cache_regs(vcpu);
@@ -1850,7 +1851,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
1850 vcpu->mmio_is_write = 0; 1851 vcpu->mmio_is_write = 0;
1851 vcpu->arch.pio.string = 0; 1852 vcpu->arch.pio.string = 0;
1852 1853
1853 if (!no_decode) { 1854 if (!(emulation_type & EMULTYPE_NO_DECODE)) {
1854 int cs_db, cs_l; 1855 int cs_db, cs_l;
1855 kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); 1856 kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
1856 1857
@@ -1884,6 +1885,16 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
1884 get_segment_base(vcpu, VCPU_SREG_FS); 1885 get_segment_base(vcpu, VCPU_SREG_FS);
1885 1886
1886 r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops); 1887 r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
1888
1889 /* Reject the instructions other than VMCALL/VMMCALL when
1890 * try to emulate invalid opcode */
1891 c = &vcpu->arch.emulate_ctxt.decode;
1892 if ((emulation_type & EMULTYPE_TRAP_UD) &&
1893 (!(c->twobyte && c->b == 0x01 &&
1894 (c->modrm_reg == 0 || c->modrm_reg == 3) &&
1895 c->modrm_mod == 3 && c->modrm_rm == 1)))
1896 return EMULATE_FAIL;
1897
1887 ++vcpu->stat.insn_emulation; 1898 ++vcpu->stat.insn_emulation;
1888 if (r) { 1899 if (r) {
1889 ++vcpu->stat.insn_emulation_fail; 1900 ++vcpu->stat.insn_emulation_fail;
@@ -2640,7 +2651,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2640 vcpu->mmio_read_completed = 1; 2651 vcpu->mmio_read_completed = 1;
2641 vcpu->mmio_needed = 0; 2652 vcpu->mmio_needed = 0;
2642 r = emulate_instruction(vcpu, kvm_run, 2653 r = emulate_instruction(vcpu, kvm_run,
2643 vcpu->arch.mmio_fault_cr2, 0, 1); 2654 vcpu->arch.mmio_fault_cr2, 0,
2655 EMULTYPE_NO_DECODE);
2644 if (r == EMULATE_DO_MMIO) { 2656 if (r == EMULATE_DO_MMIO) {
2645 /* 2657 /*
2646 * Read-modify-write. Back to userspace. 2658 * Read-modify-write. Back to userspace.
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
index 20597bc16744..4702b04b979a 100644
--- a/include/asm-x86/kvm_host.h
+++ b/include/asm-x86/kvm_host.h
@@ -415,8 +415,10 @@ enum emulation_result {
415 EMULATE_FAIL, /* can't emulate this instruction */ 415 EMULATE_FAIL, /* can't emulate this instruction */
416}; 416};
417 417
418#define EMULTYPE_NO_DECODE (1 << 0)
419#define EMULTYPE_TRAP_UD (1 << 1)
418int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run, 420int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run,
419 unsigned long cr2, u16 error_code, int no_decode); 421 unsigned long cr2, u16 error_code, int emulation_type);
420void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context); 422void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context);
421void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); 423void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
422void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); 424void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);