diff options
Diffstat (limited to 'drivers/kvm/svm.c')
-rw-r--r-- | drivers/kvm/svm.c | 113 |
1 files changed, 102 insertions, 11 deletions
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index fa0428735717..ccc06b1b91b5 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -235,6 +235,8 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) | |||
235 | 235 | ||
236 | vcpu->rip = vcpu->svm->vmcb->save.rip = vcpu->svm->next_rip; | 236 | vcpu->rip = vcpu->svm->vmcb->save.rip = vcpu->svm->next_rip; |
237 | vcpu->svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK; | 237 | vcpu->svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK; |
238 | |||
239 | vcpu->interrupt_window_open = 1; | ||
238 | } | 240 | } |
239 | 241 | ||
240 | static int has_svm(void) | 242 | static int has_svm(void) |
@@ -495,7 +497,6 @@ static void init_vmcb(struct vmcb *vmcb) | |||
495 | /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */ | 497 | /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */ |
496 | (1ULL << INTERCEPT_CPUID) | | 498 | (1ULL << INTERCEPT_CPUID) | |
497 | (1ULL << INTERCEPT_HLT) | | 499 | (1ULL << INTERCEPT_HLT) | |
498 | (1ULL << INTERCEPT_INVLPG) | | ||
499 | (1ULL << INTERCEPT_INVLPGA) | | 500 | (1ULL << INTERCEPT_INVLPGA) | |
500 | (1ULL << INTERCEPT_IOIO_PROT) | | 501 | (1ULL << INTERCEPT_IOIO_PROT) | |
501 | (1ULL << INTERCEPT_MSR_PROT) | | 502 | (1ULL << INTERCEPT_MSR_PROT) | |
@@ -700,6 +701,10 @@ static void svm_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | |||
700 | vcpu->svm->vmcb->save.gdtr.base = dt->base ; | 701 | vcpu->svm->vmcb->save.gdtr.base = dt->base ; |
701 | } | 702 | } |
702 | 703 | ||
704 | static void svm_decache_cr0_cr4_guest_bits(struct kvm_vcpu *vcpu) | ||
705 | { | ||
706 | } | ||
707 | |||
703 | static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | 708 | static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) |
704 | { | 709 | { |
705 | #ifdef CONFIG_X86_64 | 710 | #ifdef CONFIG_X86_64 |
@@ -847,6 +852,7 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
847 | u64 fault_address; | 852 | u64 fault_address; |
848 | u32 error_code; | 853 | u32 error_code; |
849 | enum emulation_result er; | 854 | enum emulation_result er; |
855 | int r; | ||
850 | 856 | ||
851 | if (is_external_interrupt(exit_int_info)) | 857 | if (is_external_interrupt(exit_int_info)) |
852 | push_irq(vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); | 858 | push_irq(vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK); |
@@ -855,7 +861,12 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
855 | 861 | ||
856 | fault_address = vcpu->svm->vmcb->control.exit_info_2; | 862 | fault_address = vcpu->svm->vmcb->control.exit_info_2; |
857 | error_code = vcpu->svm->vmcb->control.exit_info_1; | 863 | error_code = vcpu->svm->vmcb->control.exit_info_1; |
858 | if (!vcpu->mmu.page_fault(vcpu, fault_address, error_code)) { | 864 | r = kvm_mmu_page_fault(vcpu, fault_address, error_code); |
865 | if (r < 0) { | ||
866 | spin_unlock(&vcpu->kvm->lock); | ||
867 | return r; | ||
868 | } | ||
869 | if (!r) { | ||
859 | spin_unlock(&vcpu->kvm->lock); | 870 | spin_unlock(&vcpu->kvm->lock); |
860 | return 1; | 871 | return 1; |
861 | } | 872 | } |
@@ -1031,10 +1042,11 @@ static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1031 | { | 1042 | { |
1032 | vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1; | 1043 | vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1; |
1033 | skip_emulated_instruction(vcpu); | 1044 | skip_emulated_instruction(vcpu); |
1034 | if (vcpu->irq_summary && (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF)) | 1045 | if (vcpu->irq_summary) |
1035 | return 1; | 1046 | return 1; |
1036 | 1047 | ||
1037 | kvm_run->exit_reason = KVM_EXIT_HLT; | 1048 | kvm_run->exit_reason = KVM_EXIT_HLT; |
1049 | ++kvm_stat.halt_exits; | ||
1038 | return 0; | 1050 | return 0; |
1039 | } | 1051 | } |
1040 | 1052 | ||
@@ -1186,6 +1198,23 @@ static int msr_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1186 | return rdmsr_interception(vcpu, kvm_run); | 1198 | return rdmsr_interception(vcpu, kvm_run); |
1187 | } | 1199 | } |
1188 | 1200 | ||
1201 | static int interrupt_window_interception(struct kvm_vcpu *vcpu, | ||
1202 | struct kvm_run *kvm_run) | ||
1203 | { | ||
1204 | /* | ||
1205 | * If the user space waits to inject interrupts, exit as soon as | ||
1206 | * possible | ||
1207 | */ | ||
1208 | if (kvm_run->request_interrupt_window && | ||
1209 | !vcpu->irq_summary) { | ||
1210 | ++kvm_stat.irq_window_exits; | ||
1211 | kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; | ||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1215 | return 1; | ||
1216 | } | ||
1217 | |||
1189 | static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, | 1218 | static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, |
1190 | struct kvm_run *kvm_run) = { | 1219 | struct kvm_run *kvm_run) = { |
1191 | [SVM_EXIT_READ_CR0] = emulate_on_interception, | 1220 | [SVM_EXIT_READ_CR0] = emulate_on_interception, |
@@ -1210,6 +1239,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, | |||
1210 | [SVM_EXIT_NMI] = nop_on_interception, | 1239 | [SVM_EXIT_NMI] = nop_on_interception, |
1211 | [SVM_EXIT_SMI] = nop_on_interception, | 1240 | [SVM_EXIT_SMI] = nop_on_interception, |
1212 | [SVM_EXIT_INIT] = nop_on_interception, | 1241 | [SVM_EXIT_INIT] = nop_on_interception, |
1242 | [SVM_EXIT_VINTR] = interrupt_window_interception, | ||
1213 | /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */ | 1243 | /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */ |
1214 | [SVM_EXIT_CPUID] = cpuid_interception, | 1244 | [SVM_EXIT_CPUID] = cpuid_interception, |
1215 | [SVM_EXIT_HLT] = halt_interception, | 1245 | [SVM_EXIT_HLT] = halt_interception, |
@@ -1278,15 +1308,11 @@ static void pre_svm_run(struct kvm_vcpu *vcpu) | |||
1278 | } | 1308 | } |
1279 | 1309 | ||
1280 | 1310 | ||
1281 | static inline void kvm_try_inject_irq(struct kvm_vcpu *vcpu) | 1311 | static inline void kvm_do_inject_irq(struct kvm_vcpu *vcpu) |
1282 | { | 1312 | { |
1283 | struct vmcb_control_area *control; | 1313 | struct vmcb_control_area *control; |
1284 | 1314 | ||
1285 | if (!vcpu->irq_summary) | ||
1286 | return; | ||
1287 | |||
1288 | control = &vcpu->svm->vmcb->control; | 1315 | control = &vcpu->svm->vmcb->control; |
1289 | |||
1290 | control->int_vector = pop_irq(vcpu); | 1316 | control->int_vector = pop_irq(vcpu); |
1291 | control->int_ctl &= ~V_INTR_PRIO_MASK; | 1317 | control->int_ctl &= ~V_INTR_PRIO_MASK; |
1292 | control->int_ctl |= V_IRQ_MASK | | 1318 | control->int_ctl |= V_IRQ_MASK | |
@@ -1301,6 +1327,59 @@ static void kvm_reput_irq(struct kvm_vcpu *vcpu) | |||
1301 | control->int_ctl &= ~V_IRQ_MASK; | 1327 | control->int_ctl &= ~V_IRQ_MASK; |
1302 | push_irq(vcpu, control->int_vector); | 1328 | push_irq(vcpu, control->int_vector); |
1303 | } | 1329 | } |
1330 | |||
1331 | vcpu->interrupt_window_open = | ||
1332 | !(control->int_state & SVM_INTERRUPT_SHADOW_MASK); | ||
1333 | } | ||
1334 | |||
1335 | static void do_interrupt_requests(struct kvm_vcpu *vcpu, | ||
1336 | struct kvm_run *kvm_run) | ||
1337 | { | ||
1338 | struct vmcb_control_area *control = &vcpu->svm->vmcb->control; | ||
1339 | |||
1340 | vcpu->interrupt_window_open = | ||
1341 | (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) && | ||
1342 | (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF)); | ||
1343 | |||
1344 | if (vcpu->interrupt_window_open && vcpu->irq_summary) | ||
1345 | /* | ||
1346 | * If interrupts enabled, and not blocked by sti or mov ss. Good. | ||
1347 | */ | ||
1348 | kvm_do_inject_irq(vcpu); | ||
1349 | |||
1350 | /* | ||
1351 | * Interrupts blocked. Wait for unblock. | ||
1352 | */ | ||
1353 | if (!vcpu->interrupt_window_open && | ||
1354 | (vcpu->irq_summary || kvm_run->request_interrupt_window)) { | ||
1355 | control->intercept |= 1ULL << INTERCEPT_VINTR; | ||
1356 | } else | ||
1357 | control->intercept &= ~(1ULL << INTERCEPT_VINTR); | ||
1358 | } | ||
1359 | |||
1360 | static void post_kvm_run_save(struct kvm_vcpu *vcpu, | ||
1361 | struct kvm_run *kvm_run) | ||
1362 | { | ||
1363 | kvm_run->ready_for_interrupt_injection = (vcpu->interrupt_window_open && | ||
1364 | vcpu->irq_summary == 0); | ||
1365 | kvm_run->if_flag = (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF) != 0; | ||
1366 | kvm_run->cr8 = vcpu->cr8; | ||
1367 | kvm_run->apic_base = vcpu->apic_base; | ||
1368 | } | ||
1369 | |||
1370 | /* | ||
1371 | * Check if userspace requested an interrupt window, and that the | ||
1372 | * interrupt window is open. | ||
1373 | * | ||
1374 | * No need to exit to userspace if we already have an interrupt queued. | ||
1375 | */ | ||
1376 | static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu, | ||
1377 | struct kvm_run *kvm_run) | ||
1378 | { | ||
1379 | return (!vcpu->irq_summary && | ||
1380 | kvm_run->request_interrupt_window && | ||
1381 | vcpu->interrupt_window_open && | ||
1382 | (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_IF)); | ||
1304 | } | 1383 | } |
1305 | 1384 | ||
1306 | static void save_db_regs(unsigned long *db_regs) | 1385 | static void save_db_regs(unsigned long *db_regs) |
@@ -1324,9 +1403,10 @@ static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1324 | u16 fs_selector; | 1403 | u16 fs_selector; |
1325 | u16 gs_selector; | 1404 | u16 gs_selector; |
1326 | u16 ldt_selector; | 1405 | u16 ldt_selector; |
1406 | int r; | ||
1327 | 1407 | ||
1328 | again: | 1408 | again: |
1329 | kvm_try_inject_irq(vcpu); | 1409 | do_interrupt_requests(vcpu, kvm_run); |
1330 | 1410 | ||
1331 | clgi(); | 1411 | clgi(); |
1332 | 1412 | ||
@@ -1487,18 +1567,28 @@ again: | |||
1487 | if (vcpu->svm->vmcb->control.exit_code == SVM_EXIT_ERR) { | 1567 | if (vcpu->svm->vmcb->control.exit_code == SVM_EXIT_ERR) { |
1488 | kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY; | 1568 | kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY; |
1489 | kvm_run->exit_reason = vcpu->svm->vmcb->control.exit_code; | 1569 | kvm_run->exit_reason = vcpu->svm->vmcb->control.exit_code; |
1570 | post_kvm_run_save(vcpu, kvm_run); | ||
1490 | return 0; | 1571 | return 0; |
1491 | } | 1572 | } |
1492 | 1573 | ||
1493 | if (handle_exit(vcpu, kvm_run)) { | 1574 | r = handle_exit(vcpu, kvm_run); |
1575 | if (r > 0) { | ||
1494 | if (signal_pending(current)) { | 1576 | if (signal_pending(current)) { |
1495 | ++kvm_stat.signal_exits; | 1577 | ++kvm_stat.signal_exits; |
1578 | post_kvm_run_save(vcpu, kvm_run); | ||
1579 | return -EINTR; | ||
1580 | } | ||
1581 | |||
1582 | if (dm_request_for_irq_injection(vcpu, kvm_run)) { | ||
1583 | ++kvm_stat.request_irq_exits; | ||
1584 | post_kvm_run_save(vcpu, kvm_run); | ||
1496 | return -EINTR; | 1585 | return -EINTR; |
1497 | } | 1586 | } |
1498 | kvm_resched(vcpu); | 1587 | kvm_resched(vcpu); |
1499 | goto again; | 1588 | goto again; |
1500 | } | 1589 | } |
1501 | return 0; | 1590 | post_kvm_run_save(vcpu, kvm_run); |
1591 | return r; | ||
1502 | } | 1592 | } |
1503 | 1593 | ||
1504 | static void svm_flush_tlb(struct kvm_vcpu *vcpu) | 1594 | static void svm_flush_tlb(struct kvm_vcpu *vcpu) |
@@ -1565,6 +1655,7 @@ static struct kvm_arch_ops svm_arch_ops = { | |||
1565 | .get_segment = svm_get_segment, | 1655 | .get_segment = svm_get_segment, |
1566 | .set_segment = svm_set_segment, | 1656 | .set_segment = svm_set_segment, |
1567 | .get_cs_db_l_bits = svm_get_cs_db_l_bits, | 1657 | .get_cs_db_l_bits = svm_get_cs_db_l_bits, |
1658 | .decache_cr0_cr4_guest_bits = svm_decache_cr0_cr4_guest_bits, | ||
1568 | .set_cr0 = svm_set_cr0, | 1659 | .set_cr0 = svm_set_cr0, |
1569 | .set_cr0_no_modeswitch = svm_set_cr0, | 1660 | .set_cr0_no_modeswitch = svm_set_cr0, |
1570 | .set_cr3 = svm_set_cr3, | 1661 | .set_cr3 = svm_set_cr3, |