diff options
Diffstat (limited to 'arch/x86/kvm/svm.c')
| -rw-r--r-- | arch/x86/kvm/svm.c | 138 |
1 files changed, 121 insertions, 17 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index ce438e0fdd2..56c9b6bd765 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | * AMD SVM support | 4 | * AMD SVM support |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2006 Qumranet, Inc. | 6 | * Copyright (C) 2006 Qumranet, Inc. |
| 7 | * Copyright 2010 Red Hat, Inc. and/or its affilates. | ||
| 7 | * | 8 | * |
| 8 | * Authors: | 9 | * Authors: |
| 9 | * Yaniv Kamay <yaniv@qumranet.com> | 10 | * Yaniv Kamay <yaniv@qumranet.com> |
| @@ -285,11 +286,11 @@ static inline void flush_guest_tlb(struct kvm_vcpu *vcpu) | |||
| 285 | 286 | ||
| 286 | static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) | 287 | static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) |
| 287 | { | 288 | { |
| 289 | vcpu->arch.efer = efer; | ||
| 288 | if (!npt_enabled && !(efer & EFER_LMA)) | 290 | if (!npt_enabled && !(efer & EFER_LMA)) |
| 289 | efer &= ~EFER_LME; | 291 | efer &= ~EFER_LME; |
| 290 | 292 | ||
| 291 | to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME; | 293 | to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME; |
| 292 | vcpu->arch.efer = efer; | ||
| 293 | } | 294 | } |
| 294 | 295 | ||
| 295 | static int is_external_interrupt(u32 info) | 296 | static int is_external_interrupt(u32 info) |
| @@ -640,7 +641,7 @@ static __init int svm_hardware_setup(void) | |||
| 640 | 641 | ||
| 641 | if (nested) { | 642 | if (nested) { |
| 642 | printk(KERN_INFO "kvm: Nested Virtualization enabled\n"); | 643 | printk(KERN_INFO "kvm: Nested Virtualization enabled\n"); |
| 643 | kvm_enable_efer_bits(EFER_SVME); | 644 | kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE); |
| 644 | } | 645 | } |
| 645 | 646 | ||
| 646 | for_each_possible_cpu(cpu) { | 647 | for_each_possible_cpu(cpu) { |
| @@ -806,7 +807,7 @@ static void init_vmcb(struct vcpu_svm *svm) | |||
| 806 | * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0. | 807 | * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0. |
| 807 | */ | 808 | */ |
| 808 | svm->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET; | 809 | svm->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET; |
| 809 | kvm_set_cr0(&svm->vcpu, svm->vcpu.arch.cr0); | 810 | (void)kvm_set_cr0(&svm->vcpu, svm->vcpu.arch.cr0); |
| 810 | 811 | ||
| 811 | save->cr4 = X86_CR4_PAE; | 812 | save->cr4 = X86_CR4_PAE; |
| 812 | /* rdx = ?? */ | 813 | /* rdx = ?? */ |
| @@ -903,13 +904,18 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) | |||
| 903 | svm->asid_generation = 0; | 904 | svm->asid_generation = 0; |
| 904 | init_vmcb(svm); | 905 | init_vmcb(svm); |
| 905 | 906 | ||
| 906 | fx_init(&svm->vcpu); | 907 | err = fx_init(&svm->vcpu); |
| 908 | if (err) | ||
| 909 | goto free_page4; | ||
| 910 | |||
| 907 | svm->vcpu.arch.apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; | 911 | svm->vcpu.arch.apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; |
| 908 | if (kvm_vcpu_is_bsp(&svm->vcpu)) | 912 | if (kvm_vcpu_is_bsp(&svm->vcpu)) |
| 909 | svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP; | 913 | svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP; |
| 910 | 914 | ||
| 911 | return &svm->vcpu; | 915 | return &svm->vcpu; |
| 912 | 916 | ||
| 917 | free_page4: | ||
| 918 | __free_page(hsave_page); | ||
| 913 | free_page3: | 919 | free_page3: |
| 914 | __free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER); | 920 | __free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER); |
| 915 | free_page2: | 921 | free_page2: |
| @@ -1488,7 +1494,7 @@ static void svm_handle_mce(struct vcpu_svm *svm) | |||
| 1488 | */ | 1494 | */ |
| 1489 | pr_err("KVM: Guest triggered AMD Erratum 383\n"); | 1495 | pr_err("KVM: Guest triggered AMD Erratum 383\n"); |
| 1490 | 1496 | ||
| 1491 | set_bit(KVM_REQ_TRIPLE_FAULT, &svm->vcpu.requests); | 1497 | kvm_make_request(KVM_REQ_TRIPLE_FAULT, &svm->vcpu); |
| 1492 | 1498 | ||
| 1493 | return; | 1499 | return; |
| 1494 | } | 1500 | } |
| @@ -1535,7 +1541,7 @@ static int io_interception(struct vcpu_svm *svm) | |||
| 1535 | string = (io_info & SVM_IOIO_STR_MASK) != 0; | 1541 | string = (io_info & SVM_IOIO_STR_MASK) != 0; |
| 1536 | in = (io_info & SVM_IOIO_TYPE_MASK) != 0; | 1542 | in = (io_info & SVM_IOIO_TYPE_MASK) != 0; |
| 1537 | if (string || in) | 1543 | if (string || in) |
| 1538 | return !(emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DO_MMIO); | 1544 | return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE; |
| 1539 | 1545 | ||
| 1540 | port = io_info >> 16; | 1546 | port = io_info >> 16; |
| 1541 | size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT; | 1547 | size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT; |
| @@ -1957,7 +1963,7 @@ static int nested_svm_vmexit(struct vcpu_svm *svm) | |||
| 1957 | svm->vmcb->save.cr3 = hsave->save.cr3; | 1963 | svm->vmcb->save.cr3 = hsave->save.cr3; |
| 1958 | svm->vcpu.arch.cr3 = hsave->save.cr3; | 1964 | svm->vcpu.arch.cr3 = hsave->save.cr3; |
| 1959 | } else { | 1965 | } else { |
| 1960 | kvm_set_cr3(&svm->vcpu, hsave->save.cr3); | 1966 | (void)kvm_set_cr3(&svm->vcpu, hsave->save.cr3); |
| 1961 | } | 1967 | } |
| 1962 | kvm_register_write(&svm->vcpu, VCPU_REGS_RAX, hsave->save.rax); | 1968 | kvm_register_write(&svm->vcpu, VCPU_REGS_RAX, hsave->save.rax); |
| 1963 | kvm_register_write(&svm->vcpu, VCPU_REGS_RSP, hsave->save.rsp); | 1969 | kvm_register_write(&svm->vcpu, VCPU_REGS_RSP, hsave->save.rsp); |
| @@ -2080,7 +2086,7 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm) | |||
| 2080 | svm->vmcb->save.cr3 = nested_vmcb->save.cr3; | 2086 | svm->vmcb->save.cr3 = nested_vmcb->save.cr3; |
| 2081 | svm->vcpu.arch.cr3 = nested_vmcb->save.cr3; | 2087 | svm->vcpu.arch.cr3 = nested_vmcb->save.cr3; |
| 2082 | } else | 2088 | } else |
| 2083 | kvm_set_cr3(&svm->vcpu, nested_vmcb->save.cr3); | 2089 | (void)kvm_set_cr3(&svm->vcpu, nested_vmcb->save.cr3); |
| 2084 | 2090 | ||
| 2085 | /* Guest paging mode is active - reset mmu */ | 2091 | /* Guest paging mode is active - reset mmu */ |
| 2086 | kvm_mmu_reset_context(&svm->vcpu); | 2092 | kvm_mmu_reset_context(&svm->vcpu); |
| @@ -2386,16 +2392,12 @@ static int iret_interception(struct vcpu_svm *svm) | |||
| 2386 | 2392 | ||
| 2387 | static int invlpg_interception(struct vcpu_svm *svm) | 2393 | static int invlpg_interception(struct vcpu_svm *svm) |
| 2388 | { | 2394 | { |
| 2389 | if (emulate_instruction(&svm->vcpu, 0, 0, 0) != EMULATE_DONE) | 2395 | return emulate_instruction(&svm->vcpu, 0, 0, 0) == EMULATE_DONE; |
| 2390 | pr_unimpl(&svm->vcpu, "%s: failed\n", __func__); | ||
| 2391 | return 1; | ||
| 2392 | } | 2396 | } |
| 2393 | 2397 | ||
| 2394 | static int emulate_on_interception(struct vcpu_svm *svm) | 2398 | static int emulate_on_interception(struct vcpu_svm *svm) |
| 2395 | { | 2399 | { |
| 2396 | if (emulate_instruction(&svm->vcpu, 0, 0, 0) != EMULATE_DONE) | 2400 | return emulate_instruction(&svm->vcpu, 0, 0, 0) == EMULATE_DONE; |
| 2397 | pr_unimpl(&svm->vcpu, "%s: failed\n", __func__); | ||
| 2398 | return 1; | ||
| 2399 | } | 2401 | } |
| 2400 | 2402 | ||
| 2401 | static int cr8_write_interception(struct vcpu_svm *svm) | 2403 | static int cr8_write_interception(struct vcpu_svm *svm) |
| @@ -2726,6 +2728,99 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = { | |||
| 2726 | [SVM_EXIT_NPF] = pf_interception, | 2728 | [SVM_EXIT_NPF] = pf_interception, |
| 2727 | }; | 2729 | }; |
| 2728 | 2730 | ||
| 2731 | void dump_vmcb(struct kvm_vcpu *vcpu) | ||
| 2732 | { | ||
| 2733 | struct vcpu_svm *svm = to_svm(vcpu); | ||
| 2734 | struct vmcb_control_area *control = &svm->vmcb->control; | ||
| 2735 | struct vmcb_save_area *save = &svm->vmcb->save; | ||
| 2736 | |||
| 2737 | pr_err("VMCB Control Area:\n"); | ||
| 2738 | pr_err("cr_read: %04x\n", control->intercept_cr_read); | ||
| 2739 | pr_err("cr_write: %04x\n", control->intercept_cr_write); | ||
| 2740 | pr_err("dr_read: %04x\n", control->intercept_dr_read); | ||
| 2741 | pr_err("dr_write: %04x\n", control->intercept_dr_write); | ||
| 2742 | pr_err("exceptions: %08x\n", control->intercept_exceptions); | ||
| 2743 | pr_err("intercepts: %016llx\n", control->intercept); | ||
| 2744 | pr_err("pause filter count: %d\n", control->pause_filter_count); | ||
| 2745 | pr_err("iopm_base_pa: %016llx\n", control->iopm_base_pa); | ||
| 2746 | pr_err("msrpm_base_pa: %016llx\n", control->msrpm_base_pa); | ||
| 2747 | pr_err("tsc_offset: %016llx\n", control->tsc_offset); | ||
| 2748 | pr_err("asid: %d\n", control->asid); | ||
| 2749 | pr_err("tlb_ctl: %d\n", control->tlb_ctl); | ||
| 2750 | pr_err("int_ctl: %08x\n", control->int_ctl); | ||
| 2751 | pr_err("int_vector: %08x\n", control->int_vector); | ||
| 2752 | pr_err("int_state: %08x\n", control->int_state); | ||
| 2753 | pr_err("exit_code: %08x\n", control->exit_code); | ||
| 2754 | pr_err("exit_info1: %016llx\n", control->exit_info_1); | ||
| 2755 | pr_err("exit_info2: %016llx\n", control->exit_info_2); | ||
| 2756 | pr_err("exit_int_info: %08x\n", control->exit_int_info); | ||
| 2757 | pr_err("exit_int_info_err: %08x\n", control->exit_int_info_err); | ||
| 2758 | pr_err("nested_ctl: %lld\n", control->nested_ctl); | ||
| 2759 | pr_err("nested_cr3: %016llx\n", control->nested_cr3); | ||
| 2760 | pr_err("event_inj: %08x\n", control->event_inj); | ||
| 2761 | pr_err("event_inj_err: %08x\n", control->event_inj_err); | ||
| 2762 | pr_err("lbr_ctl: %lld\n", control->lbr_ctl); | ||
| 2763 | pr_err("next_rip: %016llx\n", control->next_rip); | ||
| 2764 | pr_err("VMCB State Save Area:\n"); | ||
| 2765 | pr_err("es: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2766 | save->es.selector, save->es.attrib, | ||
| 2767 | save->es.limit, save->es.base); | ||
| 2768 | pr_err("cs: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2769 | save->cs.selector, save->cs.attrib, | ||
| 2770 | save->cs.limit, save->cs.base); | ||
| 2771 | pr_err("ss: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2772 | save->ss.selector, save->ss.attrib, | ||
| 2773 | save->ss.limit, save->ss.base); | ||
| 2774 | pr_err("ds: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2775 | save->ds.selector, save->ds.attrib, | ||
| 2776 | save->ds.limit, save->ds.base); | ||
| 2777 | pr_err("fs: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2778 | save->fs.selector, save->fs.attrib, | ||
| 2779 | save->fs.limit, save->fs.base); | ||
| 2780 | pr_err("gs: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2781 | save->gs.selector, save->gs.attrib, | ||
| 2782 | save->gs.limit, save->gs.base); | ||
| 2783 | pr_err("gdtr: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2784 | save->gdtr.selector, save->gdtr.attrib, | ||
| 2785 | save->gdtr.limit, save->gdtr.base); | ||
| 2786 | pr_err("ldtr: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2787 | save->ldtr.selector, save->ldtr.attrib, | ||
| 2788 | save->ldtr.limit, save->ldtr.base); | ||
| 2789 | pr_err("idtr: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2790 | save->idtr.selector, save->idtr.attrib, | ||
| 2791 | save->idtr.limit, save->idtr.base); | ||
| 2792 | pr_err("tr: s: %04x a: %04x l: %08x b: %016llx\n", | ||
| 2793 | save->tr.selector, save->tr.attrib, | ||
| 2794 | save->tr.limit, save->tr.base); | ||
| 2795 | pr_err("cpl: %d efer: %016llx\n", | ||
| 2796 | save->cpl, save->efer); | ||
| 2797 | pr_err("cr0: %016llx cr2: %016llx\n", | ||
| 2798 | save->cr0, save->cr2); | ||
| 2799 | pr_err("cr3: %016llx cr4: %016llx\n", | ||
| 2800 | save->cr3, save->cr4); | ||
| 2801 | pr_err("dr6: %016llx dr7: %016llx\n", | ||
| 2802 | save->dr6, save->dr7); | ||
| 2803 | pr_err("rip: %016llx rflags: %016llx\n", | ||
| 2804 | save->rip, save->rflags); | ||
| 2805 | pr_err("rsp: %016llx rax: %016llx\n", | ||
| 2806 | save->rsp, save->rax); | ||
| 2807 | pr_err("star: %016llx lstar: %016llx\n", | ||
| 2808 | save->star, save->lstar); | ||
| 2809 | pr_err("cstar: %016llx sfmask: %016llx\n", | ||
| 2810 | save->cstar, save->sfmask); | ||
| 2811 | pr_err("kernel_gs_base: %016llx sysenter_cs: %016llx\n", | ||
| 2812 | save->kernel_gs_base, save->sysenter_cs); | ||
| 2813 | pr_err("sysenter_esp: %016llx sysenter_eip: %016llx\n", | ||
| 2814 | save->sysenter_esp, save->sysenter_eip); | ||
| 2815 | pr_err("gpat: %016llx dbgctl: %016llx\n", | ||
| 2816 | save->g_pat, save->dbgctl); | ||
| 2817 | pr_err("br_from: %016llx br_to: %016llx\n", | ||
| 2818 | save->br_from, save->br_to); | ||
| 2819 | pr_err("excp_from: %016llx excp_to: %016llx\n", | ||
| 2820 | save->last_excp_from, save->last_excp_to); | ||
| 2821 | |||
| 2822 | } | ||
| 2823 | |||
| 2729 | static int handle_exit(struct kvm_vcpu *vcpu) | 2824 | static int handle_exit(struct kvm_vcpu *vcpu) |
| 2730 | { | 2825 | { |
| 2731 | struct vcpu_svm *svm = to_svm(vcpu); | 2826 | struct vcpu_svm *svm = to_svm(vcpu); |
| @@ -2770,6 +2865,8 @@ static int handle_exit(struct kvm_vcpu *vcpu) | |||
| 2770 | kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY; | 2865 | kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY; |
| 2771 | kvm_run->fail_entry.hardware_entry_failure_reason | 2866 | kvm_run->fail_entry.hardware_entry_failure_reason |
| 2772 | = svm->vmcb->control.exit_code; | 2867 | = svm->vmcb->control.exit_code; |
| 2868 | pr_err("KVM: FAILED VMRUN WITH VMCB:\n"); | ||
| 2869 | dump_vmcb(vcpu); | ||
| 2773 | return 0; | 2870 | return 0; |
| 2774 | } | 2871 | } |
| 2775 | 2872 | ||
| @@ -2826,9 +2923,6 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq) | |||
| 2826 | { | 2923 | { |
| 2827 | struct vmcb_control_area *control; | 2924 | struct vmcb_control_area *control; |
| 2828 | 2925 | ||
| 2829 | trace_kvm_inj_virq(irq); | ||
| 2830 | |||
| 2831 | ++svm->vcpu.stat.irq_injections; | ||
| 2832 | control = &svm->vmcb->control; | 2926 | control = &svm->vmcb->control; |
| 2833 | control->int_vector = irq; | 2927 | control->int_vector = irq; |
| 2834 | control->int_ctl &= ~V_INTR_PRIO_MASK; | 2928 | control->int_ctl &= ~V_INTR_PRIO_MASK; |
| @@ -2842,6 +2936,9 @@ static void svm_set_irq(struct kvm_vcpu *vcpu) | |||
| 2842 | 2936 | ||
| 2843 | BUG_ON(!(gif_set(svm))); | 2937 | BUG_ON(!(gif_set(svm))); |
| 2844 | 2938 | ||
| 2939 | trace_kvm_inj_virq(vcpu->arch.interrupt.nr); | ||
| 2940 | ++vcpu->stat.irq_injections; | ||
| 2941 | |||
| 2845 | svm->vmcb->control.event_inj = vcpu->arch.interrupt.nr | | 2942 | svm->vmcb->control.event_inj = vcpu->arch.interrupt.nr | |
| 2846 | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR; | 2943 | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR; |
| 2847 | } | 2944 | } |
| @@ -3327,6 +3424,11 @@ static bool svm_rdtscp_supported(void) | |||
| 3327 | return false; | 3424 | return false; |
| 3328 | } | 3425 | } |
| 3329 | 3426 | ||
| 3427 | static bool svm_has_wbinvd_exit(void) | ||
| 3428 | { | ||
| 3429 | return true; | ||
| 3430 | } | ||
| 3431 | |||
| 3330 | static void svm_fpu_deactivate(struct kvm_vcpu *vcpu) | 3432 | static void svm_fpu_deactivate(struct kvm_vcpu *vcpu) |
| 3331 | { | 3433 | { |
| 3332 | struct vcpu_svm *svm = to_svm(vcpu); | 3434 | struct vcpu_svm *svm = to_svm(vcpu); |
| @@ -3411,6 +3513,8 @@ static struct kvm_x86_ops svm_x86_ops = { | |||
| 3411 | .rdtscp_supported = svm_rdtscp_supported, | 3513 | .rdtscp_supported = svm_rdtscp_supported, |
| 3412 | 3514 | ||
| 3413 | .set_supported_cpuid = svm_set_supported_cpuid, | 3515 | .set_supported_cpuid = svm_set_supported_cpuid, |
| 3516 | |||
| 3517 | .has_wbinvd_exit = svm_has_wbinvd_exit, | ||
| 3414 | }; | 3518 | }; |
| 3415 | 3519 | ||
| 3416 | static int __init svm_init(void) | 3520 | static int __init svm_init(void) |
