aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2009-08-07 05:49:34 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:33:24 -0400
commitaad42c641cfcda4f87abc4f6588329b9b3cc3364 (patch)
tree110c2cfd3cc18dff27f4fb01bb5ffab61661ada0
parente6aa9abd7381557c67be6a9e7240eb132ca00d66 (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.c30
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
85struct vcpu_svm { 94struct 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;