diff options
author | Andre Przywara <andre.przywara@amd.com> | 2010-12-21 05:12:07 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-01-12 04:31:07 -0500 |
commit | dc25e89e07d5ef31c476117d2c76b34dbb22196c (patch) | |
tree | 9fef452c4bd0704b9d74512a9a58dc5d5b742d53 /arch/x86/kvm | |
parent | df4f3108562dc6f6ae6648f2698df7f4c9acf52d (diff) |
KVM: SVM: copy instruction bytes from VMCB
In case of a nested page fault or an intercepted #PF newer SVM
implementations provide a copy of the faulting instruction bytes
in the VMCB.
Use these bytes to feed the instruction emulator and avoid the costly
guest instruction fetch in this case.
Signed-off-by: Andre Przywara <andre.przywara@amd.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/emulate.c | 7 | ||||
-rw-r--r-- | arch/x86/kvm/mmu.c | 5 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 4 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 4 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 6 |
5 files changed, 17 insertions, 9 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 36534ecaf596..caf966781d25 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -2610,7 +2610,7 @@ done: | |||
2610 | } | 2610 | } |
2611 | 2611 | ||
2612 | int | 2612 | int |
2613 | x86_decode_insn(struct x86_emulate_ctxt *ctxt) | 2613 | x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) |
2614 | { | 2614 | { |
2615 | struct x86_emulate_ops *ops = ctxt->ops; | 2615 | struct x86_emulate_ops *ops = ctxt->ops; |
2616 | struct decode_cache *c = &ctxt->decode; | 2616 | struct decode_cache *c = &ctxt->decode; |
@@ -2621,7 +2621,10 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt) | |||
2621 | struct operand memop = { .type = OP_NONE }; | 2621 | struct operand memop = { .type = OP_NONE }; |
2622 | 2622 | ||
2623 | c->eip = ctxt->eip; | 2623 | c->eip = ctxt->eip; |
2624 | c->fetch.start = c->fetch.end = c->eip; | 2624 | c->fetch.start = c->eip; |
2625 | c->fetch.end = c->fetch.start + insn_len; | ||
2626 | if (insn_len > 0) | ||
2627 | memcpy(c->fetch.data, insn, insn_len); | ||
2625 | ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS); | 2628 | ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS); |
2626 | 2629 | ||
2627 | switch (mode) { | 2630 | switch (mode) { |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 01c5a104031f..ea6063d9242e 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -3330,7 +3330,8 @@ void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu) | |||
3330 | } | 3330 | } |
3331 | } | 3331 | } |
3332 | 3332 | ||
3333 | int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code) | 3333 | int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code, |
3334 | void *insn, int insn_len) | ||
3334 | { | 3335 | { |
3335 | int r; | 3336 | int r; |
3336 | enum emulation_result er; | 3337 | enum emulation_result er; |
@@ -3348,7 +3349,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code) | |||
3348 | if (r) | 3349 | if (r) |
3349 | goto out; | 3350 | goto out; |
3350 | 3351 | ||
3351 | er = x86_emulate_instruction(vcpu, cr2, 0); | 3352 | er = x86_emulate_instruction(vcpu, cr2, 0, insn, insn_len); |
3352 | 3353 | ||
3353 | switch (er) { | 3354 | switch (er) { |
3354 | case EMULATE_DONE: | 3355 | case EMULATE_DONE: |
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index a04c01e324b4..af4b911a8bed 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -1527,7 +1527,9 @@ static int pf_interception(struct vcpu_svm *svm) | |||
1527 | trace_kvm_page_fault(fault_address, error_code); | 1527 | trace_kvm_page_fault(fault_address, error_code); |
1528 | if (!npt_enabled && kvm_event_needs_reinjection(&svm->vcpu)) | 1528 | if (!npt_enabled && kvm_event_needs_reinjection(&svm->vcpu)) |
1529 | kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address); | 1529 | kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address); |
1530 | r = kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); | 1530 | r = kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code, |
1531 | svm->vmcb->control.insn_bytes, | ||
1532 | svm->vmcb->control.insn_len); | ||
1531 | break; | 1533 | break; |
1532 | case KVM_PV_REASON_PAGE_NOT_PRESENT: | 1534 | case KVM_PV_REASON_PAGE_NOT_PRESENT: |
1533 | svm->apf_reason = 0; | 1535 | svm->apf_reason = 0; |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index f3c60fb8d95e..736f83955ce9 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -3055,7 +3055,7 @@ static int handle_exception(struct kvm_vcpu *vcpu) | |||
3055 | 3055 | ||
3056 | if (kvm_event_needs_reinjection(vcpu)) | 3056 | if (kvm_event_needs_reinjection(vcpu)) |
3057 | kvm_mmu_unprotect_page_virt(vcpu, cr2); | 3057 | kvm_mmu_unprotect_page_virt(vcpu, cr2); |
3058 | return kvm_mmu_page_fault(vcpu, cr2, error_code); | 3058 | return kvm_mmu_page_fault(vcpu, cr2, error_code, NULL, 0); |
3059 | } | 3059 | } |
3060 | 3060 | ||
3061 | if (vmx->rmode.vm86_active && | 3061 | if (vmx->rmode.vm86_active && |
@@ -3502,7 +3502,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) | |||
3502 | 3502 | ||
3503 | gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); | 3503 | gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); |
3504 | trace_kvm_page_fault(gpa, exit_qualification); | 3504 | trace_kvm_page_fault(gpa, exit_qualification); |
3505 | return kvm_mmu_page_fault(vcpu, gpa, exit_qualification & 0x3); | 3505 | return kvm_mmu_page_fault(vcpu, gpa, exit_qualification & 0x3, NULL, 0); |
3506 | } | 3506 | } |
3507 | 3507 | ||
3508 | static u64 ept_rsvd_mask(u64 spte, int level) | 3508 | static u64 ept_rsvd_mask(u64 spte, int level) |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index a6fcb76196b7..7ad9cda8ff36 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4365,7 +4365,9 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva) | |||
4365 | 4365 | ||
4366 | int x86_emulate_instruction(struct kvm_vcpu *vcpu, | 4366 | int x86_emulate_instruction(struct kvm_vcpu *vcpu, |
4367 | unsigned long cr2, | 4367 | unsigned long cr2, |
4368 | int emulation_type) | 4368 | int emulation_type, |
4369 | void *insn, | ||
4370 | int insn_len) | ||
4369 | { | 4371 | { |
4370 | int r; | 4372 | int r; |
4371 | struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode; | 4373 | struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode; |
@@ -4386,7 +4388,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, | |||
4386 | vcpu->arch.emulate_ctxt.have_exception = false; | 4388 | vcpu->arch.emulate_ctxt.have_exception = false; |
4387 | vcpu->arch.emulate_ctxt.perm_ok = false; | 4389 | vcpu->arch.emulate_ctxt.perm_ok = false; |
4388 | 4390 | ||
4389 | r = x86_decode_insn(&vcpu->arch.emulate_ctxt); | 4391 | r = x86_decode_insn(&vcpu->arch.emulate_ctxt, insn, insn_len); |
4390 | if (r == X86EMUL_PROPAGATE_FAULT) | 4392 | if (r == X86EMUL_PROPAGATE_FAULT) |
4391 | goto done; | 4393 | goto done; |
4392 | 4394 | ||