diff options
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/kvm_svm.h | 8 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 157 |
2 files changed, 163 insertions, 2 deletions
diff --git a/arch/x86/kvm/kvm_svm.h b/arch/x86/kvm/kvm_svm.h index a0877cac7b9c..91673413d8f7 100644 --- a/arch/x86/kvm/kvm_svm.h +++ b/arch/x86/kvm/kvm_svm.h | |||
@@ -43,6 +43,14 @@ struct vcpu_svm { | |||
43 | u32 *msrpm; | 43 | u32 *msrpm; |
44 | struct vmcb *hsave; | 44 | struct vmcb *hsave; |
45 | u64 hsave_msr; | 45 | u64 hsave_msr; |
46 | |||
47 | u64 nested_vmcb; | ||
48 | |||
49 | /* These are the merged vectors */ | ||
50 | u32 *nested_msrpm; | ||
51 | |||
52 | /* gpa pointers to the real vectors */ | ||
53 | u64 nested_vmcb_msrpm; | ||
46 | }; | 54 | }; |
47 | 55 | ||
48 | #endif | 56 | #endif |
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index a83c94eb5771..fad187cbfabe 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -77,6 +77,11 @@ static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) | |||
77 | return container_of(vcpu, struct vcpu_svm, vcpu); | 77 | return container_of(vcpu, struct vcpu_svm, vcpu); |
78 | } | 78 | } |
79 | 79 | ||
80 | static inline bool is_nested(struct vcpu_svm *svm) | ||
81 | { | ||
82 | return svm->nested_vmcb; | ||
83 | } | ||
84 | |||
80 | static unsigned long iopm_base; | 85 | static unsigned long iopm_base; |
81 | 86 | ||
82 | struct kvm_ldttss_desc { | 87 | struct kvm_ldttss_desc { |
@@ -601,6 +606,7 @@ static void init_vmcb(struct vcpu_svm *svm) | |||
601 | } | 606 | } |
602 | force_new_asid(&svm->vcpu); | 607 | force_new_asid(&svm->vcpu); |
603 | 608 | ||
609 | svm->nested_vmcb = 0; | ||
604 | svm->vcpu.arch.hflags = HF_GIF_MASK; | 610 | svm->vcpu.arch.hflags = HF_GIF_MASK; |
605 | } | 611 | } |
606 | 612 | ||
@@ -627,6 +633,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) | |||
627 | struct page *page; | 633 | struct page *page; |
628 | struct page *msrpm_pages; | 634 | struct page *msrpm_pages; |
629 | struct page *hsave_page; | 635 | struct page *hsave_page; |
636 | struct page *nested_msrpm_pages; | ||
630 | int err; | 637 | int err; |
631 | 638 | ||
632 | svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); | 639 | svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); |
@@ -649,6 +656,11 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) | |||
649 | msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER); | 656 | msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER); |
650 | if (!msrpm_pages) | 657 | if (!msrpm_pages) |
651 | goto uninit; | 658 | goto uninit; |
659 | |||
660 | nested_msrpm_pages = alloc_pages(GFP_KERNEL, MSRPM_ALLOC_ORDER); | ||
661 | if (!nested_msrpm_pages) | ||
662 | goto uninit; | ||
663 | |||
652 | svm->msrpm = page_address(msrpm_pages); | 664 | svm->msrpm = page_address(msrpm_pages); |
653 | svm_vcpu_init_msrpm(svm->msrpm); | 665 | svm_vcpu_init_msrpm(svm->msrpm); |
654 | 666 | ||
@@ -657,6 +669,8 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) | |||
657 | goto uninit; | 669 | goto uninit; |
658 | svm->hsave = page_address(hsave_page); | 670 | svm->hsave = page_address(hsave_page); |
659 | 671 | ||
672 | svm->nested_msrpm = page_address(nested_msrpm_pages); | ||
673 | |||
660 | svm->vmcb = page_address(page); | 674 | svm->vmcb = page_address(page); |
661 | clear_page(svm->vmcb); | 675 | clear_page(svm->vmcb); |
662 | svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; | 676 | svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; |
@@ -687,6 +701,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu) | |||
687 | __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT)); | 701 | __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT)); |
688 | __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER); | 702 | __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER); |
689 | __free_page(virt_to_page(svm->hsave)); | 703 | __free_page(virt_to_page(svm->hsave)); |
704 | __free_pages(virt_to_page(svm->nested_msrpm), MSRPM_ALLOC_ORDER); | ||
690 | kvm_vcpu_uninit(vcpu); | 705 | kvm_vcpu_uninit(vcpu); |
691 | kmem_cache_free(kvm_vcpu_cache, svm); | 706 | kmem_cache_free(kvm_vcpu_cache, svm); |
692 | } | 707 | } |
@@ -1243,6 +1258,123 @@ static int nested_svm_do(struct vcpu_svm *svm, | |||
1243 | return retval; | 1258 | return retval; |
1244 | } | 1259 | } |
1245 | 1260 | ||
1261 | |||
1262 | static int nested_svm_vmrun_msrpm(struct vcpu_svm *svm, void *arg1, | ||
1263 | void *arg2, void *opaque) | ||
1264 | { | ||
1265 | int i; | ||
1266 | u32 *nested_msrpm = (u32*)arg1; | ||
1267 | for (i=0; i< PAGE_SIZE * (1 << MSRPM_ALLOC_ORDER) / 4; i++) | ||
1268 | svm->nested_msrpm[i] = svm->msrpm[i] | nested_msrpm[i]; | ||
1269 | svm->vmcb->control.msrpm_base_pa = __pa(svm->nested_msrpm); | ||
1270 | |||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | static int nested_svm_vmrun(struct vcpu_svm *svm, void *arg1, | ||
1275 | void *arg2, void *opaque) | ||
1276 | { | ||
1277 | struct vmcb *nested_vmcb = (struct vmcb *)arg1; | ||
1278 | struct vmcb *hsave = svm->hsave; | ||
1279 | |||
1280 | /* nested_vmcb is our indicator if nested SVM is activated */ | ||
1281 | svm->nested_vmcb = svm->vmcb->save.rax; | ||
1282 | |||
1283 | /* Clear internal status */ | ||
1284 | svm->vcpu.arch.exception.pending = false; | ||
1285 | |||
1286 | /* Save the old vmcb, so we don't need to pick what we save, but | ||
1287 | can restore everything when a VMEXIT occurs */ | ||
1288 | memcpy(hsave, svm->vmcb, sizeof(struct vmcb)); | ||
1289 | /* We need to remember the original CR3 in the SPT case */ | ||
1290 | if (!npt_enabled) | ||
1291 | hsave->save.cr3 = svm->vcpu.arch.cr3; | ||
1292 | hsave->save.cr4 = svm->vcpu.arch.cr4; | ||
1293 | hsave->save.rip = svm->next_rip; | ||
1294 | |||
1295 | if (svm->vmcb->save.rflags & X86_EFLAGS_IF) | ||
1296 | svm->vcpu.arch.hflags |= HF_HIF_MASK; | ||
1297 | else | ||
1298 | svm->vcpu.arch.hflags &= ~HF_HIF_MASK; | ||
1299 | |||
1300 | /* Load the nested guest state */ | ||
1301 | svm->vmcb->save.es = nested_vmcb->save.es; | ||
1302 | svm->vmcb->save.cs = nested_vmcb->save.cs; | ||
1303 | svm->vmcb->save.ss = nested_vmcb->save.ss; | ||
1304 | svm->vmcb->save.ds = nested_vmcb->save.ds; | ||
1305 | svm->vmcb->save.gdtr = nested_vmcb->save.gdtr; | ||
1306 | svm->vmcb->save.idtr = nested_vmcb->save.idtr; | ||
1307 | svm->vmcb->save.rflags = nested_vmcb->save.rflags; | ||
1308 | svm_set_efer(&svm->vcpu, nested_vmcb->save.efer); | ||
1309 | svm_set_cr0(&svm->vcpu, nested_vmcb->save.cr0); | ||
1310 | svm_set_cr4(&svm->vcpu, nested_vmcb->save.cr4); | ||
1311 | if (npt_enabled) { | ||
1312 | svm->vmcb->save.cr3 = nested_vmcb->save.cr3; | ||
1313 | svm->vcpu.arch.cr3 = nested_vmcb->save.cr3; | ||
1314 | } else { | ||
1315 | kvm_set_cr3(&svm->vcpu, nested_vmcb->save.cr3); | ||
1316 | kvm_mmu_reset_context(&svm->vcpu); | ||
1317 | } | ||
1318 | svm->vmcb->save.cr2 = nested_vmcb->save.cr2; | ||
1319 | kvm_register_write(&svm->vcpu, VCPU_REGS_RAX, nested_vmcb->save.rax); | ||
1320 | kvm_register_write(&svm->vcpu, VCPU_REGS_RSP, nested_vmcb->save.rsp); | ||
1321 | kvm_register_write(&svm->vcpu, VCPU_REGS_RIP, nested_vmcb->save.rip); | ||
1322 | /* In case we don't even reach vcpu_run, the fields are not updated */ | ||
1323 | svm->vmcb->save.rax = nested_vmcb->save.rax; | ||
1324 | svm->vmcb->save.rsp = nested_vmcb->save.rsp; | ||
1325 | svm->vmcb->save.rip = nested_vmcb->save.rip; | ||
1326 | svm->vmcb->save.dr7 = nested_vmcb->save.dr7; | ||
1327 | svm->vmcb->save.dr6 = nested_vmcb->save.dr6; | ||
1328 | svm->vmcb->save.cpl = nested_vmcb->save.cpl; | ||
1329 | |||
1330 | /* We don't want a nested guest to be more powerful than the guest, | ||
1331 | so all intercepts are ORed */ | ||
1332 | svm->vmcb->control.intercept_cr_read |= | ||
1333 | nested_vmcb->control.intercept_cr_read; | ||
1334 | svm->vmcb->control.intercept_cr_write |= | ||
1335 | nested_vmcb->control.intercept_cr_write; | ||
1336 | svm->vmcb->control.intercept_dr_read |= | ||
1337 | nested_vmcb->control.intercept_dr_read; | ||
1338 | svm->vmcb->control.intercept_dr_write |= | ||
1339 | nested_vmcb->control.intercept_dr_write; | ||
1340 | svm->vmcb->control.intercept_exceptions |= | ||
1341 | nested_vmcb->control.intercept_exceptions; | ||
1342 | |||
1343 | svm->vmcb->control.intercept |= nested_vmcb->control.intercept; | ||
1344 | |||
1345 | svm->nested_vmcb_msrpm = nested_vmcb->control.msrpm_base_pa; | ||
1346 | |||
1347 | force_new_asid(&svm->vcpu); | ||
1348 | svm->vmcb->control.exit_int_info = nested_vmcb->control.exit_int_info; | ||
1349 | svm->vmcb->control.exit_int_info_err = nested_vmcb->control.exit_int_info_err; | ||
1350 | svm->vmcb->control.int_ctl = nested_vmcb->control.int_ctl | V_INTR_MASKING_MASK; | ||
1351 | if (nested_vmcb->control.int_ctl & V_IRQ_MASK) { | ||
1352 | nsvm_printk("nSVM Injecting Interrupt: 0x%x\n", | ||
1353 | nested_vmcb->control.int_ctl); | ||
1354 | } | ||
1355 | if (nested_vmcb->control.int_ctl & V_INTR_MASKING_MASK) | ||
1356 | svm->vcpu.arch.hflags |= HF_VINTR_MASK; | ||
1357 | else | ||
1358 | svm->vcpu.arch.hflags &= ~HF_VINTR_MASK; | ||
1359 | |||
1360 | nsvm_printk("nSVM exit_int_info: 0x%x | int_state: 0x%x\n", | ||
1361 | nested_vmcb->control.exit_int_info, | ||
1362 | nested_vmcb->control.int_state); | ||
1363 | |||
1364 | svm->vmcb->control.int_vector = nested_vmcb->control.int_vector; | ||
1365 | svm->vmcb->control.int_state = nested_vmcb->control.int_state; | ||
1366 | svm->vmcb->control.tsc_offset += nested_vmcb->control.tsc_offset; | ||
1367 | if (nested_vmcb->control.event_inj & SVM_EVTINJ_VALID) | ||
1368 | nsvm_printk("Injecting Event: 0x%x\n", | ||
1369 | nested_vmcb->control.event_inj); | ||
1370 | svm->vmcb->control.event_inj = nested_vmcb->control.event_inj; | ||
1371 | svm->vmcb->control.event_inj_err = nested_vmcb->control.event_inj_err; | ||
1372 | |||
1373 | svm->vcpu.arch.hflags |= HF_GIF_MASK; | ||
1374 | |||
1375 | return 0; | ||
1376 | } | ||
1377 | |||
1246 | static int nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb) | 1378 | static int nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb) |
1247 | { | 1379 | { |
1248 | to_vmcb->save.fs = from_vmcb->save.fs; | 1380 | to_vmcb->save.fs = from_vmcb->save.fs; |
@@ -1299,6 +1431,26 @@ static int vmsave_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | |||
1299 | return 1; | 1431 | return 1; |
1300 | } | 1432 | } |
1301 | 1433 | ||
1434 | static int vmrun_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | ||
1435 | { | ||
1436 | nsvm_printk("VMrun\n"); | ||
1437 | if (nested_svm_check_permissions(svm)) | ||
1438 | return 1; | ||
1439 | |||
1440 | svm->next_rip = kvm_rip_read(&svm->vcpu) + 3; | ||
1441 | skip_emulated_instruction(&svm->vcpu); | ||
1442 | |||
1443 | if (nested_svm_do(svm, svm->vmcb->save.rax, 0, | ||
1444 | NULL, nested_svm_vmrun)) | ||
1445 | return 1; | ||
1446 | |||
1447 | if (nested_svm_do(svm, svm->nested_vmcb_msrpm, 0, | ||
1448 | NULL, nested_svm_vmrun_msrpm)) | ||
1449 | return 1; | ||
1450 | |||
1451 | return 1; | ||
1452 | } | ||
1453 | |||
1302 | static int stgi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) | 1454 | static int stgi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) |
1303 | { | 1455 | { |
1304 | if (nested_svm_check_permissions(svm)) | 1456 | if (nested_svm_check_permissions(svm)) |
@@ -1632,7 +1784,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, | |||
1632 | [SVM_EXIT_MSR] = msr_interception, | 1784 | [SVM_EXIT_MSR] = msr_interception, |
1633 | [SVM_EXIT_TASK_SWITCH] = task_switch_interception, | 1785 | [SVM_EXIT_TASK_SWITCH] = task_switch_interception, |
1634 | [SVM_EXIT_SHUTDOWN] = shutdown_interception, | 1786 | [SVM_EXIT_SHUTDOWN] = shutdown_interception, |
1635 | [SVM_EXIT_VMRUN] = invalid_op_interception, | 1787 | [SVM_EXIT_VMRUN] = vmrun_interception, |
1636 | [SVM_EXIT_VMMCALL] = vmmcall_interception, | 1788 | [SVM_EXIT_VMMCALL] = vmmcall_interception, |
1637 | [SVM_EXIT_VMLOAD] = vmload_interception, | 1789 | [SVM_EXIT_VMLOAD] = vmload_interception, |
1638 | [SVM_EXIT_VMSAVE] = vmsave_interception, | 1790 | [SVM_EXIT_VMSAVE] = vmsave_interception, |
@@ -1939,7 +2091,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1939 | svm->host_cr2 = kvm_read_cr2(); | 2091 | svm->host_cr2 = kvm_read_cr2(); |
1940 | svm->host_dr6 = read_dr6(); | 2092 | svm->host_dr6 = read_dr6(); |
1941 | svm->host_dr7 = read_dr7(); | 2093 | svm->host_dr7 = read_dr7(); |
1942 | svm->vmcb->save.cr2 = vcpu->arch.cr2; | 2094 | if (!is_nested(svm)) |
2095 | svm->vmcb->save.cr2 = vcpu->arch.cr2; | ||
1943 | /* required for live migration with NPT */ | 2096 | /* required for live migration with NPT */ |
1944 | if (npt_enabled) | 2097 | if (npt_enabled) |
1945 | svm->vmcb->save.cr3 = vcpu->arch.cr3; | 2098 | svm->vmcb->save.cr3 = vcpu->arch.cr3; |