aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r--arch/x86/kvm/svm.c80
1 files changed, 50 insertions, 30 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 53376f144d70..be28a38db918 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -47,6 +47,10 @@ MODULE_LICENSE("GPL");
47#define SVM_FEATURE_LBRV (1 << 1) 47#define SVM_FEATURE_LBRV (1 << 1)
48#define SVM_FEATURE_SVML (1 << 2) 48#define SVM_FEATURE_SVML (1 << 2)
49 49
50#define NESTED_EXIT_HOST 0 /* Exit handled on host level */
51#define NESTED_EXIT_DONE 1 /* Exit caused nested vmexit */
52#define NESTED_EXIT_CONTINUE 2 /* Further checks needed */
53
50#define DEBUGCTL_RESERVED_BITS (~(0x3fULL)) 54#define DEBUGCTL_RESERVED_BITS (~(0x3fULL))
51 55
52/* Turn on to get debugging output*/ 56/* Turn on to get debugging output*/
@@ -126,7 +130,7 @@ module_param(nested, int, S_IRUGO);
126static void svm_flush_tlb(struct kvm_vcpu *vcpu); 130static void svm_flush_tlb(struct kvm_vcpu *vcpu);
127static void svm_complete_interrupts(struct vcpu_svm *svm); 131static void svm_complete_interrupts(struct vcpu_svm *svm);
128 132
129static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override); 133static int nested_svm_exit_handled(struct vcpu_svm *svm);
130static int nested_svm_vmexit(struct vcpu_svm *svm); 134static int nested_svm_vmexit(struct vcpu_svm *svm);
131static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, 135static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
132 bool has_error_code, u32 error_code); 136 bool has_error_code, u32 error_code);
@@ -1365,7 +1369,7 @@ static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
1365 svm->vmcb->control.exit_info_1 = error_code; 1369 svm->vmcb->control.exit_info_1 = error_code;
1366 svm->vmcb->control.exit_info_2 = svm->vcpu.arch.cr2; 1370 svm->vmcb->control.exit_info_2 = svm->vcpu.arch.cr2;
1367 1371
1368 return nested_svm_exit_handled(svm, false); 1372 return nested_svm_exit_handled(svm);
1369} 1373}
1370 1374
1371static inline int nested_svm_intr(struct vcpu_svm *svm) 1375static inline int nested_svm_intr(struct vcpu_svm *svm)
@@ -1379,7 +1383,7 @@ static inline int nested_svm_intr(struct vcpu_svm *svm)
1379 1383
1380 svm->vmcb->control.exit_code = SVM_EXIT_INTR; 1384 svm->vmcb->control.exit_code = SVM_EXIT_INTR;
1381 1385
1382 if (nested_svm_exit_handled(svm, false)) { 1386 if (nested_svm_exit_handled(svm)) {
1383 nsvm_printk("VMexit -> INTR\n"); 1387 nsvm_printk("VMexit -> INTR\n");
1384 return 1; 1388 return 1;
1385 } 1389 }
@@ -1465,31 +1469,39 @@ out:
1465 return ret; 1469 return ret;
1466} 1470}
1467 1471
1468static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override) 1472static int nested_svm_exit_special(struct vcpu_svm *svm)
1469{ 1473{
1470 u32 exit_code = svm->vmcb->control.exit_code; 1474 u32 exit_code = svm->vmcb->control.exit_code;
1471 bool vmexit = false;
1472 1475
1473 if (kvm_override) { 1476 switch (exit_code) {
1474 switch (exit_code) { 1477 case SVM_EXIT_INTR:
1475 case SVM_EXIT_INTR: 1478 case SVM_EXIT_NMI:
1476 case SVM_EXIT_NMI: 1479 return NESTED_EXIT_HOST;
1477 return 0;
1478 /* For now we are always handling NPFs when using them */ 1480 /* For now we are always handling NPFs when using them */
1479 case SVM_EXIT_NPF: 1481 case SVM_EXIT_NPF:
1480 if (npt_enabled) 1482 if (npt_enabled)
1481 return 0; 1483 return NESTED_EXIT_HOST;
1482 break; 1484 break;
1483 /* When we're shadowing, trap PFs */ 1485 /* When we're shadowing, trap PFs */
1484 case SVM_EXIT_EXCP_BASE + PF_VECTOR: 1486 case SVM_EXIT_EXCP_BASE + PF_VECTOR:
1485 if (!npt_enabled) 1487 if (!npt_enabled)
1486 return 0; 1488 return NESTED_EXIT_HOST;
1487 break; 1489 break;
1488 default: 1490 default:
1489 break; 1491 break;
1490 }
1491 } 1492 }
1492 1493
1494 return NESTED_EXIT_CONTINUE;
1495}
1496
1497/*
1498 * If this function returns true, this #vmexit was already handled
1499 */
1500static int nested_svm_exit_handled(struct vcpu_svm *svm)
1501{
1502 u32 exit_code = svm->vmcb->control.exit_code;
1503 int vmexit = NESTED_EXIT_HOST;
1504
1493 switch (exit_code) { 1505 switch (exit_code) {
1494 case SVM_EXIT_MSR: 1506 case SVM_EXIT_MSR:
1495 vmexit = nested_svm_exit_handled_msr(svm); 1507 vmexit = nested_svm_exit_handled_msr(svm);
@@ -1497,42 +1509,42 @@ static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override)
1497 case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: { 1509 case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR8: {
1498 u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0); 1510 u32 cr_bits = 1 << (exit_code - SVM_EXIT_READ_CR0);
1499 if (svm->nested.intercept_cr_read & cr_bits) 1511 if (svm->nested.intercept_cr_read & cr_bits)
1500 vmexit = true; 1512 vmexit = NESTED_EXIT_DONE;
1501 break; 1513 break;
1502 } 1514 }
1503 case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR8: { 1515 case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR8: {
1504 u32 cr_bits = 1 << (exit_code - SVM_EXIT_WRITE_CR0); 1516 u32 cr_bits = 1 << (exit_code - SVM_EXIT_WRITE_CR0);
1505 if (svm->nested.intercept_cr_write & cr_bits) 1517 if (svm->nested.intercept_cr_write & cr_bits)
1506 vmexit = true; 1518 vmexit = NESTED_EXIT_DONE;
1507 break; 1519 break;
1508 } 1520 }
1509 case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: { 1521 case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR7: {
1510 u32 dr_bits = 1 << (exit_code - SVM_EXIT_READ_DR0); 1522 u32 dr_bits = 1 << (exit_code - SVM_EXIT_READ_DR0);
1511 if (svm->nested.intercept_dr_read & dr_bits) 1523 if (svm->nested.intercept_dr_read & dr_bits)
1512 vmexit = true; 1524 vmexit = NESTED_EXIT_DONE;
1513 break; 1525 break;
1514 } 1526 }
1515 case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: { 1527 case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR7: {
1516 u32 dr_bits = 1 << (exit_code - SVM_EXIT_WRITE_DR0); 1528 u32 dr_bits = 1 << (exit_code - SVM_EXIT_WRITE_DR0);
1517 if (svm->nested.intercept_dr_write & dr_bits) 1529 if (svm->nested.intercept_dr_write & dr_bits)
1518 vmexit = true; 1530 vmexit = NESTED_EXIT_DONE;
1519 break; 1531 break;
1520 } 1532 }
1521 case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: { 1533 case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: {
1522 u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE); 1534 u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE);
1523 if (svm->nested.intercept_exceptions & excp_bits) 1535 if (svm->nested.intercept_exceptions & excp_bits)
1524 vmexit = true; 1536 vmexit = NESTED_EXIT_DONE;
1525 break; 1537 break;
1526 } 1538 }
1527 default: { 1539 default: {
1528 u64 exit_bits = 1ULL << (exit_code - SVM_EXIT_INTR); 1540 u64 exit_bits = 1ULL << (exit_code - SVM_EXIT_INTR);
1529 nsvm_printk("exit code: 0x%x\n", exit_code); 1541 nsvm_printk("exit code: 0x%x\n", exit_code);
1530 if (svm->nested.intercept & exit_bits) 1542 if (svm->nested.intercept & exit_bits)
1531 vmexit = true; 1543 vmexit = NESTED_EXIT_DONE;
1532 } 1544 }
1533 } 1545 }
1534 1546
1535 if (vmexit) { 1547 if (vmexit == NESTED_EXIT_DONE) {
1536 nsvm_printk("#VMEXIT reason=%04x\n", exit_code); 1548 nsvm_printk("#VMEXIT reason=%04x\n", exit_code);
1537 nested_svm_vmexit(svm); 1549 nested_svm_vmexit(svm);
1538 } 1550 }
@@ -2312,10 +2324,18 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
2312 trace_kvm_exit(exit_code, svm->vmcb->save.rip); 2324 trace_kvm_exit(exit_code, svm->vmcb->save.rip);
2313 2325
2314 if (is_nested(svm)) { 2326 if (is_nested(svm)) {
2327 int vmexit;
2328
2315 nsvm_printk("nested handle_exit: 0x%x | 0x%lx | 0x%lx | 0x%lx\n", 2329 nsvm_printk("nested handle_exit: 0x%x | 0x%lx | 0x%lx | 0x%lx\n",
2316 exit_code, svm->vmcb->control.exit_info_1, 2330 exit_code, svm->vmcb->control.exit_info_1,
2317 svm->vmcb->control.exit_info_2, svm->vmcb->save.rip); 2331 svm->vmcb->control.exit_info_2, svm->vmcb->save.rip);
2318 if (nested_svm_exit_handled(svm, true)) 2332
2333 vmexit = nested_svm_exit_special(svm);
2334
2335 if (vmexit == NESTED_EXIT_CONTINUE)
2336 vmexit = nested_svm_exit_handled(svm);
2337
2338 if (vmexit == NESTED_EXIT_DONE)
2319 return 1; 2339 return 1;
2320 } 2340 }
2321 2341