aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaurent Vivier <Laurent.Vivier@bull.net>2007-09-18 05:27:37 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:47 -0500
commit3427318fd2244737a466a06a93c5fe579852f871 (patch)
tree7c6760dbbdd067498c470e6e4f711e5baeef491c /drivers
parent1be3aa47182e94944e57b176a5c4ee4e74f1ce33 (diff)
KVM: Call x86_decode_insn() only when needed
Move emulate_ctxt to kvm_vcpu to keep emulate context when we exit from kvm module. Call x86_decode_insn() only when needed. Modify x86_emulate_insn() to not modify the context if it must be re-entered. Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/kvm/kvm.h8
-rw-r--r--drivers/kvm/kvm_main.c77
-rw-r--r--drivers/kvm/svm.c9
-rw-r--r--drivers/kvm/vmx.c9
-rw-r--r--drivers/kvm/x86_emulate.c24
5 files changed, 82 insertions, 45 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index da9c3aa1c08c..e885b190b798 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -207,6 +207,8 @@ enum {
207 VCPU_SREG_LDTR, 207 VCPU_SREG_LDTR,
208}; 208};
209 209
210#include "x86_emulate.h"
211
210struct kvm_pio_request { 212struct kvm_pio_request {
211 unsigned long count; 213 unsigned long count;
212 int cur_count; 214 int cur_count;
@@ -380,6 +382,10 @@ struct kvm_vcpu {
380 382
381 int cpuid_nent; 383 int cpuid_nent;
382 struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES]; 384 struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];
385
386 /* emulate context */
387
388 struct x86_emulate_ctxt emulate_ctxt;
383}; 389};
384 390
385struct kvm_mem_alias { 391struct kvm_mem_alias {
@@ -555,7 +561,7 @@ enum emulation_result {
555}; 561};
556 562
557int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run, 563int emulate_instruction(struct kvm_vcpu *vcpu, struct kvm_run *run,
558 unsigned long cr2, u16 error_code); 564 unsigned long cr2, u16 error_code, int no_decode);
559void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context); 565void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context);
560void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); 566void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
561void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address); 567void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 800ab5028ed3..710483669f34 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -1251,45 +1251,56 @@ struct x86_emulate_ops emulate_ops = {
1251int emulate_instruction(struct kvm_vcpu *vcpu, 1251int emulate_instruction(struct kvm_vcpu *vcpu,
1252 struct kvm_run *run, 1252 struct kvm_run *run,
1253 unsigned long cr2, 1253 unsigned long cr2,
1254 u16 error_code) 1254 u16 error_code,
1255 int no_decode)
1255{ 1256{
1256 struct x86_emulate_ctxt emulate_ctxt; 1257 int r = 0;
1257 int r;
1258 int cs_db, cs_l;
1259 1258
1260 vcpu->mmio_fault_cr2 = cr2; 1259 vcpu->mmio_fault_cr2 = cr2;
1261 kvm_x86_ops->cache_regs(vcpu); 1260 kvm_x86_ops->cache_regs(vcpu);
1262 1261
1263 kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
1264
1265 emulate_ctxt.vcpu = vcpu;
1266 emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
1267 emulate_ctxt.cr2 = cr2;
1268 emulate_ctxt.mode = (emulate_ctxt.eflags & X86_EFLAGS_VM)
1269 ? X86EMUL_MODE_REAL : cs_l
1270 ? X86EMUL_MODE_PROT64 : cs_db
1271 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
1272
1273 if (emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
1274 emulate_ctxt.cs_base = 0;
1275 emulate_ctxt.ds_base = 0;
1276 emulate_ctxt.es_base = 0;
1277 emulate_ctxt.ss_base = 0;
1278 } else {
1279 emulate_ctxt.cs_base = get_segment_base(vcpu, VCPU_SREG_CS);
1280 emulate_ctxt.ds_base = get_segment_base(vcpu, VCPU_SREG_DS);
1281 emulate_ctxt.es_base = get_segment_base(vcpu, VCPU_SREG_ES);
1282 emulate_ctxt.ss_base = get_segment_base(vcpu, VCPU_SREG_SS);
1283 }
1284
1285 emulate_ctxt.gs_base = get_segment_base(vcpu, VCPU_SREG_GS);
1286 emulate_ctxt.fs_base = get_segment_base(vcpu, VCPU_SREG_FS);
1287
1288 vcpu->mmio_is_write = 0; 1262 vcpu->mmio_is_write = 0;
1289 vcpu->pio.string = 0; 1263 vcpu->pio.string = 0;
1290 r = x86_decode_insn(&emulate_ctxt, &emulate_ops); 1264
1265 if (!no_decode) {
1266 int cs_db, cs_l;
1267 kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
1268
1269 vcpu->emulate_ctxt.vcpu = vcpu;
1270 vcpu->emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
1271 vcpu->emulate_ctxt.cr2 = cr2;
1272 vcpu->emulate_ctxt.mode =
1273 (vcpu->emulate_ctxt.eflags & X86_EFLAGS_VM)
1274 ? X86EMUL_MODE_REAL : cs_l
1275 ? X86EMUL_MODE_PROT64 : cs_db
1276 ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
1277
1278 if (vcpu->emulate_ctxt.mode == X86EMUL_MODE_PROT64) {
1279 vcpu->emulate_ctxt.cs_base = 0;
1280 vcpu->emulate_ctxt.ds_base = 0;
1281 vcpu->emulate_ctxt.es_base = 0;
1282 vcpu->emulate_ctxt.ss_base = 0;
1283 } else {
1284 vcpu->emulate_ctxt.cs_base =
1285 get_segment_base(vcpu, VCPU_SREG_CS);
1286 vcpu->emulate_ctxt.ds_base =
1287 get_segment_base(vcpu, VCPU_SREG_DS);
1288 vcpu->emulate_ctxt.es_base =
1289 get_segment_base(vcpu, VCPU_SREG_ES);
1290 vcpu->emulate_ctxt.ss_base =
1291 get_segment_base(vcpu, VCPU_SREG_SS);
1292 }
1293
1294 vcpu->emulate_ctxt.gs_base =
1295 get_segment_base(vcpu, VCPU_SREG_GS);
1296 vcpu->emulate_ctxt.fs_base =
1297 get_segment_base(vcpu, VCPU_SREG_FS);
1298
1299 r = x86_decode_insn(&vcpu->emulate_ctxt, &emulate_ops);
1300 }
1301
1291 if (r == 0) 1302 if (r == 0)
1292 r = x86_emulate_insn(&emulate_ctxt, &emulate_ops); 1303 r = x86_emulate_insn(&vcpu->emulate_ctxt, &emulate_ops);
1293 1304
1294 if (vcpu->pio.string) 1305 if (vcpu->pio.string)
1295 return EMULATE_DO_MMIO; 1306 return EMULATE_DO_MMIO;
@@ -1313,7 +1324,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
1313 } 1324 }
1314 1325
1315 kvm_x86_ops->decache_regs(vcpu); 1326 kvm_x86_ops->decache_regs(vcpu);
1316 kvm_x86_ops->set_rflags(vcpu, emulate_ctxt.eflags); 1327 kvm_x86_ops->set_rflags(vcpu, vcpu->emulate_ctxt.eflags);
1317 1328
1318 if (vcpu->mmio_is_write) { 1329 if (vcpu->mmio_is_write) {
1319 vcpu->mmio_needed = 0; 1330 vcpu->mmio_needed = 0;
@@ -2055,7 +2066,7 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2055 vcpu->mmio_read_completed = 1; 2066 vcpu->mmio_read_completed = 1;
2056 vcpu->mmio_needed = 0; 2067 vcpu->mmio_needed = 0;
2057 r = emulate_instruction(vcpu, kvm_run, 2068 r = emulate_instruction(vcpu, kvm_run,
2058 vcpu->mmio_fault_cr2, 0); 2069 vcpu->mmio_fault_cr2, 0, 1);
2059 if (r == EMULATE_DO_MMIO) { 2070 if (r == EMULATE_DO_MMIO) {
2060 /* 2071 /*
2061 * Read-modify-write. Back to userspace. 2072 * Read-modify-write. Back to userspace.
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 794d95416f7b..f268bd51f337 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -960,7 +960,7 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
960 return 1; 960 return 1;
961 } 961 }
962 er = emulate_instruction(&svm->vcpu, kvm_run, fault_address, 962 er = emulate_instruction(&svm->vcpu, kvm_run, fault_address,
963 error_code); 963 error_code, 0);
964 mutex_unlock(&kvm->lock); 964 mutex_unlock(&kvm->lock);
965 965
966 switch (er) { 966 switch (er) {
@@ -984,7 +984,7 @@ static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
984{ 984{
985 int er; 985 int er;
986 986
987 er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0); 987 er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0);
988 if (er != EMULATE_DONE) 988 if (er != EMULATE_DONE)
989 inject_ud(&svm->vcpu); 989 inject_ud(&svm->vcpu);
990 990
@@ -1027,7 +1027,8 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1027 string = (io_info & SVM_IOIO_STR_MASK) != 0; 1027 string = (io_info & SVM_IOIO_STR_MASK) != 0;
1028 1028
1029 if (string) { 1029 if (string) {
1030 if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO) 1030 if (emulate_instruction(&svm->vcpu,
1031 kvm_run, 0, 0, 0) == EMULATE_DO_MMIO)
1031 return 0; 1032 return 0;
1032 return 1; 1033 return 1;
1033 } 1034 }
@@ -1086,7 +1087,7 @@ static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1086static int emulate_on_interception(struct vcpu_svm *svm, 1087static int emulate_on_interception(struct vcpu_svm *svm,
1087 struct kvm_run *kvm_run) 1088 struct kvm_run *kvm_run)
1088{ 1089{
1089 if (emulate_instruction(&svm->vcpu, NULL, 0, 0) != EMULATE_DONE) 1090 if (emulate_instruction(&svm->vcpu, NULL, 0, 0, 0) != EMULATE_DONE)
1090 pr_unimpl(&svm->vcpu, "%s: failed\n", __FUNCTION__); 1091 pr_unimpl(&svm->vcpu, "%s: failed\n", __FUNCTION__);
1091 return 1; 1092 return 1;
1092} 1093}
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 47c827d3007c..91768d5dbfb9 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1750,7 +1750,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
1750 * Cause the #SS fault with 0 error code in VM86 mode. 1750 * Cause the #SS fault with 0 error code in VM86 mode.
1751 */ 1751 */
1752 if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0) 1752 if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
1753 if (emulate_instruction(vcpu, NULL, 0, 0) == EMULATE_DONE) 1753 if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE)
1754 return 1; 1754 return 1;
1755 return 0; 1755 return 0;
1756} 1756}
@@ -1787,7 +1787,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1787 } 1787 }
1788 1788
1789 if (is_invalid_opcode(intr_info)) { 1789 if (is_invalid_opcode(intr_info)) {
1790 er = emulate_instruction(vcpu, kvm_run, 0, 0); 1790 er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
1791 if (er != EMULATE_DONE) 1791 if (er != EMULATE_DONE)
1792 vmx_inject_ud(vcpu); 1792 vmx_inject_ud(vcpu);
1793 1793
@@ -1812,7 +1812,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1812 return 1; 1812 return 1;
1813 } 1813 }
1814 1814
1815 er = emulate_instruction(vcpu, kvm_run, cr2, error_code); 1815 er = emulate_instruction(vcpu, kvm_run, cr2, error_code, 0);
1816 mutex_unlock(&vcpu->kvm->lock); 1816 mutex_unlock(&vcpu->kvm->lock);
1817 1817
1818 switch (er) { 1818 switch (er) {
@@ -1873,7 +1873,8 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1873 string = (exit_qualification & 16) != 0; 1873 string = (exit_qualification & 16) != 0;
1874 1874
1875 if (string) { 1875 if (string) {
1876 if (emulate_instruction(vcpu, kvm_run, 0, 0) == EMULATE_DO_MMIO) 1876 if (emulate_instruction(vcpu,
1877 kvm_run, 0, 0, 0) == EMULATE_DO_MMIO)
1877 return 0; 1878 return 0;
1878 return 1; 1879 return 1;
1879 } 1880 }
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index c191093982d8..dc9d2a870fbc 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -913,10 +913,19 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
913 unsigned long cr2 = ctxt->cr2; 913 unsigned long cr2 = ctxt->cr2;
914 int no_wb = 0; 914 int no_wb = 0;
915 u64 msr_data; 915 u64 msr_data;
916 unsigned long saved_eip = 0;
916 unsigned long _eflags = ctxt->eflags; 917 unsigned long _eflags = ctxt->eflags;
917 struct decode_cache *c = &ctxt->decode; 918 struct decode_cache *c = &ctxt->decode;
918 int rc = 0; 919 int rc = 0;
919 920
921 /* Shadow copy of register state. Committed on successful emulation.
922 * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
923 * modify them.
924 */
925
926 memcpy(c->regs, ctxt->vcpu->regs, sizeof c->regs);
927 saved_eip = c->eip;
928
920 if ((c->d & ModRM) && (c->modrm_mod != 3)) 929 if ((c->d & ModRM) && (c->modrm_mod != 3))
921 cr2 = c->modrm_ea; 930 cr2 = c->modrm_ea;
922 931
@@ -1250,7 +1259,11 @@ writeback:
1250 ctxt->vcpu->rip = c->eip; 1259 ctxt->vcpu->rip = c->eip;
1251 1260
1252done: 1261done:
1253 return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; 1262 if (rc == X86EMUL_UNHANDLEABLE) {
1263 c->eip = saved_eip;
1264 return -1;
1265 }
1266 return 0;
1254 1267
1255special_insn: 1268special_insn:
1256 if (c->twobyte) 1269 if (c->twobyte)
@@ -1305,8 +1318,10 @@ push:
1305 register_address(ctxt->es_base, 1318 register_address(ctxt->es_base,
1306 c->regs[VCPU_REGS_RDI]), 1319 c->regs[VCPU_REGS_RDI]),
1307 c->rep_prefix, 1320 c->rep_prefix,
1308 c->regs[VCPU_REGS_RDX]) == 0) 1321 c->regs[VCPU_REGS_RDX]) == 0) {
1322 c->eip = saved_eip;
1309 return -1; 1323 return -1;
1324 }
1310 return 0; 1325 return 0;
1311 case 0x6e: /* outsb */ 1326 case 0x6e: /* outsb */
1312 case 0x6f: /* outsw/outsd */ 1327 case 0x6f: /* outsw/outsd */
@@ -1321,8 +1336,10 @@ push:
1321 ctxt->ds_base, 1336 ctxt->ds_base,
1322 c->regs[VCPU_REGS_RSI]), 1337 c->regs[VCPU_REGS_RSI]),
1323 c->rep_prefix, 1338 c->rep_prefix,
1324 c->regs[VCPU_REGS_RDX]) == 0) 1339 c->regs[VCPU_REGS_RDX]) == 0) {
1340 c->eip = saved_eip;
1325 return -1; 1341 return -1;
1342 }
1326 return 0; 1343 return 0;
1327 case 0x70 ... 0x7f: /* jcc (short) */ { 1344 case 0x70 ... 0x7f: /* jcc (short) */ {
1328 int rel = insn_fetch(s8, 1, c->eip); 1345 int rel = insn_fetch(s8, 1, c->eip);
@@ -1711,5 +1728,6 @@ twobyte_special_insn:
1711 1728
1712cannot_emulate: 1729cannot_emulate:
1713 DPRINTF("Cannot emulate %02x\n", c->b); 1730 DPRINTF("Cannot emulate %02x\n", c->b);
1731 c->eip = saved_eip;
1714 return -1; 1732 return -1;
1715} 1733}