diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-12 14:13:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-12 14:13:54 -0500 |
commit | e6a5c27f3b0fef72e528fc35e343af4b2db790ff (patch) | |
tree | c34374b96071fe4c5579643da2c10fb630d23b10 /drivers | |
parent | 05f3f415894d061f7d3e77e3d46caeb4c184b005 (diff) | |
parent | cf5a94d1331b411b84414c13e43f578260942d6b (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm:
KVM: SVM: Intercept the 'invd' and 'wbinvd' instructions
KVM: x86 emulator: invd instruction
KVM: SVM: Defer nmi processing until switch to host state is complete
KVM: SVM: Fix SMP with kernel apic
KVM: x86 emulator: fix 'push imm8' emulation
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/kvm/svm.c | 18 | ||||
-rw-r--r-- | drivers/kvm/x86_emulate.c | 26 |
2 files changed, 28 insertions, 16 deletions
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 729f1cd93606..7a6eead63a6b 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -494,6 +494,7 @@ static void init_vmcb(struct vmcb *vmcb) | |||
494 | */ | 494 | */ |
495 | /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */ | 495 | /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */ |
496 | (1ULL << INTERCEPT_CPUID) | | 496 | (1ULL << INTERCEPT_CPUID) | |
497 | (1ULL << INTERCEPT_INVD) | | ||
497 | (1ULL << INTERCEPT_HLT) | | 498 | (1ULL << INTERCEPT_HLT) | |
498 | (1ULL << INTERCEPT_INVLPGA) | | 499 | (1ULL << INTERCEPT_INVLPGA) | |
499 | (1ULL << INTERCEPT_IOIO_PROT) | | 500 | (1ULL << INTERCEPT_IOIO_PROT) | |
@@ -507,6 +508,7 @@ static void init_vmcb(struct vmcb *vmcb) | |||
507 | (1ULL << INTERCEPT_STGI) | | 508 | (1ULL << INTERCEPT_STGI) | |
508 | (1ULL << INTERCEPT_CLGI) | | 509 | (1ULL << INTERCEPT_CLGI) | |
509 | (1ULL << INTERCEPT_SKINIT) | | 510 | (1ULL << INTERCEPT_SKINIT) | |
511 | (1ULL << INTERCEPT_WBINVD) | | ||
510 | (1ULL << INTERCEPT_MONITOR) | | 512 | (1ULL << INTERCEPT_MONITOR) | |
511 | (1ULL << INTERCEPT_MWAIT); | 513 | (1ULL << INTERCEPT_MWAIT); |
512 | 514 | ||
@@ -561,6 +563,12 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu) | |||
561 | struct vcpu_svm *svm = to_svm(vcpu); | 563 | struct vcpu_svm *svm = to_svm(vcpu); |
562 | 564 | ||
563 | init_vmcb(svm->vmcb); | 565 | init_vmcb(svm->vmcb); |
566 | |||
567 | if (vcpu->vcpu_id != 0) { | ||
568 | svm->vmcb->save.rip = 0; | ||
569 | svm->vmcb->save.cs.base = svm->vcpu.sipi_vector << 12; | ||
570 | svm->vmcb->save.cs.selector = svm->vcpu.sipi_vector << 8; | ||
571 | } | ||
564 | } | 572 | } |
565 | 573 | ||
566 | static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) | 574 | static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) |
@@ -1241,6 +1249,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, | |||
1241 | [SVM_EXIT_VINTR] = interrupt_window_interception, | 1249 | [SVM_EXIT_VINTR] = interrupt_window_interception, |
1242 | /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */ | 1250 | /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */ |
1243 | [SVM_EXIT_CPUID] = cpuid_interception, | 1251 | [SVM_EXIT_CPUID] = cpuid_interception, |
1252 | [SVM_EXIT_INVD] = emulate_on_interception, | ||
1244 | [SVM_EXIT_HLT] = halt_interception, | 1253 | [SVM_EXIT_HLT] = halt_interception, |
1245 | [SVM_EXIT_INVLPG] = emulate_on_interception, | 1254 | [SVM_EXIT_INVLPG] = emulate_on_interception, |
1246 | [SVM_EXIT_INVLPGA] = invalid_op_interception, | 1255 | [SVM_EXIT_INVLPGA] = invalid_op_interception, |
@@ -1255,6 +1264,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, | |||
1255 | [SVM_EXIT_STGI] = invalid_op_interception, | 1264 | [SVM_EXIT_STGI] = invalid_op_interception, |
1256 | [SVM_EXIT_CLGI] = invalid_op_interception, | 1265 | [SVM_EXIT_CLGI] = invalid_op_interception, |
1257 | [SVM_EXIT_SKINIT] = invalid_op_interception, | 1266 | [SVM_EXIT_SKINIT] = invalid_op_interception, |
1267 | [SVM_EXIT_WBINVD] = emulate_on_interception, | ||
1258 | [SVM_EXIT_MONITOR] = invalid_op_interception, | 1268 | [SVM_EXIT_MONITOR] = invalid_op_interception, |
1259 | [SVM_EXIT_MWAIT] = invalid_op_interception, | 1269 | [SVM_EXIT_MWAIT] = invalid_op_interception, |
1260 | }; | 1270 | }; |
@@ -1579,10 +1589,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1579 | #endif | 1589 | #endif |
1580 | : "cc", "memory" ); | 1590 | : "cc", "memory" ); |
1581 | 1591 | ||
1582 | local_irq_disable(); | ||
1583 | |||
1584 | stgi(); | ||
1585 | |||
1586 | if ((svm->vmcb->save.dr7 & 0xff)) | 1592 | if ((svm->vmcb->save.dr7 & 0xff)) |
1587 | load_db_regs(svm->host_db_regs); | 1593 | load_db_regs(svm->host_db_regs); |
1588 | 1594 | ||
@@ -1599,6 +1605,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1599 | 1605 | ||
1600 | reload_tss(vcpu); | 1606 | reload_tss(vcpu); |
1601 | 1607 | ||
1608 | local_irq_disable(); | ||
1609 | |||
1610 | stgi(); | ||
1611 | |||
1602 | svm->next_rip = 0; | 1612 | svm->next_rip = 0; |
1603 | } | 1613 | } |
1604 | 1614 | ||
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index a6ace302e0cd..33b181451557 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -167,7 +167,7 @@ static u8 opcode_table[256] = { | |||
167 | static u16 twobyte_table[256] = { | 167 | static u16 twobyte_table[256] = { |
168 | /* 0x00 - 0x0F */ | 168 | /* 0x00 - 0x0F */ |
169 | 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, | 169 | 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, |
170 | 0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0, | 170 | ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0, |
171 | /* 0x10 - 0x1F */ | 171 | /* 0x10 - 0x1F */ |
172 | 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, | 172 | 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, |
173 | /* 0x20 - 0x2F */ | 173 | /* 0x20 - 0x2F */ |
@@ -980,17 +980,6 @@ done_prefixes: | |||
980 | goto cannot_emulate; | 980 | goto cannot_emulate; |
981 | dst.val = (s32) src.val; | 981 | dst.val = (s32) src.val; |
982 | break; | 982 | break; |
983 | case 0x6a: /* push imm8 */ | ||
984 | src.val = 0L; | ||
985 | src.val = insn_fetch(s8, 1, _eip); | ||
986 | push: | ||
987 | dst.type = OP_MEM; | ||
988 | dst.bytes = op_bytes; | ||
989 | dst.val = src.val; | ||
990 | register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes); | ||
991 | dst.ptr = (void *) register_address(ctxt->ss_base, | ||
992 | _regs[VCPU_REGS_RSP]); | ||
993 | break; | ||
994 | case 0x80 ... 0x83: /* Grp1 */ | 983 | case 0x80 ... 0x83: /* Grp1 */ |
995 | switch (modrm_reg) { | 984 | switch (modrm_reg) { |
996 | case 0: | 985 | case 0: |
@@ -1243,6 +1232,17 @@ special_insn: | |||
1243 | register_address_increment(_regs[VCPU_REGS_RSP], op_bytes); | 1232 | register_address_increment(_regs[VCPU_REGS_RSP], op_bytes); |
1244 | no_wb = 1; /* Disable writeback. */ | 1233 | no_wb = 1; /* Disable writeback. */ |
1245 | break; | 1234 | break; |
1235 | case 0x6a: /* push imm8 */ | ||
1236 | src.val = 0L; | ||
1237 | src.val = insn_fetch(s8, 1, _eip); | ||
1238 | push: | ||
1239 | dst.type = OP_MEM; | ||
1240 | dst.bytes = op_bytes; | ||
1241 | dst.val = src.val; | ||
1242 | register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes); | ||
1243 | dst.ptr = (void *) register_address(ctxt->ss_base, | ||
1244 | _regs[VCPU_REGS_RSP]); | ||
1245 | break; | ||
1246 | case 0x6c: /* insb */ | 1246 | case 0x6c: /* insb */ |
1247 | case 0x6d: /* insw/insd */ | 1247 | case 0x6d: /* insw/insd */ |
1248 | if (kvm_emulate_pio_string(ctxt->vcpu, NULL, | 1248 | if (kvm_emulate_pio_string(ctxt->vcpu, NULL, |
@@ -1532,6 +1532,8 @@ twobyte_special_insn: | |||
1532 | case 0x06: | 1532 | case 0x06: |
1533 | emulate_clts(ctxt->vcpu); | 1533 | emulate_clts(ctxt->vcpu); |
1534 | break; | 1534 | break; |
1535 | case 0x08: /* invd */ | ||
1536 | break; | ||
1535 | case 0x09: /* wbinvd */ | 1537 | case 0x09: /* wbinvd */ |
1536 | break; | 1538 | break; |
1537 | case 0x0d: /* GrpP (prefetch) */ | 1539 | case 0x0d: /* GrpP (prefetch) */ |