diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2009-08-07 05:49:34 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-09-10 01:33:24 -0400 |
commit | aad42c641cfcda4f87abc4f6588329b9b3cc3364 (patch) | |
tree | 110c2cfd3cc18dff27f4fb01bb5ffab61661ada0 | |
parent | e6aa9abd7381557c67be6a9e7240eb132ca00d66 (diff) |
KVM: SVM: cache nested intercepts
When the nested intercepts are cached we don't need to call
get_user_pages and/or map the nested vmcb on every nested #vmexit to
check who will handle the intercept.
Further this patch aligns the emulated svm behavior better to real
hardware.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/x86/kvm/svm.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index fbadaa7cb27a..4426c631057b 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -80,6 +80,15 @@ struct nested_state { | |||
80 | 80 | ||
81 | /* gpa pointers to the real vectors */ | 81 | /* gpa pointers to the real vectors */ |
82 | u64 vmcb_msrpm; | 82 | u64 vmcb_msrpm; |
83 | |||
84 | /* cache for intercepts of the guest */ | ||
85 | u16 intercept_cr_read; | ||
86 | u16 intercept_cr_write; | ||
87 | u16 intercept_dr_read; | ||
88 | u16 intercept_dr_write; | ||
89 | u32 intercept_exceptions; | ||
90 | u64 intercept; | ||
91 | |||
83 | }; | 92 | }; |
84 | 93 | ||
85 | struct vcpu_svm { | 94 | struct vcpu_svm { |
@@ -1452,7 +1461,6 @@ static int nested_svm_exit_handled_real(struct vcpu_svm *svm, | |||
1452 | void *arg2, | 1461 | void *arg2, |
1453 | void *opaque) | 1462 | void *opaque) |
1454 | { | 1463 | { |
1455 | struct vmcb *nested_vmcb = (struct vmcb *)arg1; | ||
1456 | bool kvm_overrides = *(bool *)opaque; | 1464 | bool kvm_overrides = *(bool *)opaque; |
1457 | u32 exit_code = svm->vmcb->control.exit_code; | 1465 | u32 exit_code = svm->vmcb->control.exit_code; |
1458 | 1466 | ||
@@ -1479,38 +1487,38 @@ static int nested_svm_exit_handled_real(struct vcpu_svm *svm, | |||
1479 | switch (exit_code) { | 1487 | switch (exit_code) { |
1480 | case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: { | 1488 | case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: { |
1481 | u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0); | 1489 | u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0); |
1482 | if (nested_vmcb->control.intercept_cr_read & cr_bits) | 1490 | if (svm->nested.intercept_cr_read & cr_bits) |
1483 | return 1; | 1491 | return 1; |
1484 | break; | 1492 | break; |
1485 | } | 1493 | } |
1486 | case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR8: { | 1494 | case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR8: { |
1487 | u32 cr_bits = 1 << (exit_code - SVM_EXIT_WRITE_CR0); | 1495 | u32 cr_bits = 1 << (exit_code - SVM_EXIT_WRITE_CR0); |
1488 | if (nested_vmcb->control.intercept_cr_write & cr_bits) | 1496 | if (svm->nested.intercept_cr_write & cr_bits) |
1489 | return 1; | 1497 | return 1; |
1490 | break; | 1498 | break; |
1491 | } | 1499 | } |
1492 | case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: { | 1500 | case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: { |
1493 | u32 dr_bits = 1 << (exit_code - SVM_EXIT_READ_DR0); | 1501 | u32 dr_bits = 1 << (exit_code - SVM_EXIT_READ_DR0); |
1494 | if (nested_vmcb->control.intercept_dr_read & dr_bits) | 1502 | if (svm->nested.intercept_dr_read & dr_bits) |
1495 | return 1; | 1503 | return 1; |
1496 | break; | 1504 | break; |
1497 | } | 1505 | } |
1498 | case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: { | 1506 | case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: { |
1499 | u32 dr_bits = 1 << (exit_code - SVM_EXIT_WRITE_DR0); | 1507 | u32 dr_bits = 1 << (exit_code - SVM_EXIT_WRITE_DR0); |
1500 | if (nested_vmcb->control.intercept_dr_write & dr_bits) | 1508 | if (svm->nested.intercept_dr_write & dr_bits) |
1501 | return 1; | 1509 | return 1; |
1502 | break; | 1510 | break; |
1503 | } | 1511 | } |
1504 | case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: { | 1512 | case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: { |
1505 | u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE); | 1513 | u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE); |
1506 | if (nested_vmcb->control.intercept_exceptions & excp_bits) | 1514 | if (svm->nested.intercept_exceptions & excp_bits) |
1507 | return 1; | 1515 | return 1; |
1508 | break; | 1516 | break; |
1509 | } | 1517 | } |
1510 | default: { | 1518 | default: { |
1511 | u64 exit_bits = 1ULL << (exit_code - SVM_EXIT_INTR); | 1519 | u64 exit_bits = 1ULL << (exit_code - SVM_EXIT_INTR); |
1512 | nsvm_printk("exit code: 0x%x\n", exit_code); | 1520 | nsvm_printk("exit code: 0x%x\n", exit_code); |
1513 | if (nested_vmcb->control.intercept & exit_bits) | 1521 | if (svm->nested.intercept & exit_bits) |
1514 | return 1; | 1522 | return 1; |
1515 | } | 1523 | } |
1516 | } | 1524 | } |
@@ -1801,6 +1809,14 @@ static int nested_svm_vmrun(struct vcpu_svm *svm, void *arg1, | |||
1801 | 1809 | ||
1802 | svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa; | 1810 | svm->nested.vmcb_msrpm = nested_vmcb->control.msrpm_base_pa; |
1803 | 1811 | ||
1812 | /* cache intercepts */ | ||
1813 | svm->nested.intercept_cr_read = nested_vmcb->control.intercept_cr_read; | ||
1814 | svm->nested.intercept_cr_write = nested_vmcb->control.intercept_cr_write; | ||
1815 | svm->nested.intercept_dr_read = nested_vmcb->control.intercept_dr_read; | ||
1816 | svm->nested.intercept_dr_write = nested_vmcb->control.intercept_dr_write; | ||
1817 | svm->nested.intercept_exceptions = nested_vmcb->control.intercept_exceptions; | ||
1818 | svm->nested.intercept = nested_vmcb->control.intercept; | ||
1819 | |||
1804 | force_new_asid(&svm->vcpu); | 1820 | force_new_asid(&svm->vcpu); |
1805 | svm->vmcb->control.exit_int_info = nested_vmcb->control.exit_int_info; | 1821 | svm->vmcb->control.exit_int_info = nested_vmcb->control.exit_int_info; |
1806 | svm->vmcb->control.exit_int_info_err = nested_vmcb->control.exit_int_info_err; | 1822 | svm->vmcb->control.exit_int_info_err = nested_vmcb->control.exit_int_info_err; |