diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-10-14 05:22:50 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-01-12 04:23:12 -0500 |
commit | 344d9588a9df06182684168be4f1408b55c7da3e (patch) | |
tree | 16890e3f0f10ac767265e650a1d6d38b78780040 /arch | |
parent | ca3f10172eea9b95bbb66487656f3c3e93855702 (diff) |
KVM: Add PV MSR to enable asynchronous page faults delivery.
Guest enables async PF vcpu functionality using this MSR.
Reviewed-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/kvm_para.h | 4 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 38 |
3 files changed, 42 insertions, 2 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index c3076bcf5ef7..0d7039804b4c 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -419,6 +419,8 @@ struct kvm_vcpu_arch { | |||
419 | struct { | 419 | struct { |
420 | bool halted; | 420 | bool halted; |
421 | gfn_t gfns[roundup_pow_of_two(ASYNC_PF_PER_VCPU)]; | 421 | gfn_t gfns[roundup_pow_of_two(ASYNC_PF_PER_VCPU)]; |
422 | struct gfn_to_hva_cache data; | ||
423 | u64 msr_val; | ||
422 | } apf; | 424 | } apf; |
423 | }; | 425 | }; |
424 | 426 | ||
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h index e3faaaf4301e..8662ae0a035c 100644 --- a/arch/x86/include/asm/kvm_para.h +++ b/arch/x86/include/asm/kvm_para.h | |||
@@ -20,6 +20,7 @@ | |||
20 | * are available. The use of 0x11 and 0x12 is deprecated | 20 | * are available. The use of 0x11 and 0x12 is deprecated |
21 | */ | 21 | */ |
22 | #define KVM_FEATURE_CLOCKSOURCE2 3 | 22 | #define KVM_FEATURE_CLOCKSOURCE2 3 |
23 | #define KVM_FEATURE_ASYNC_PF 4 | ||
23 | 24 | ||
24 | /* The last 8 bits are used to indicate how to interpret the flags field | 25 | /* The last 8 bits are used to indicate how to interpret the flags field |
25 | * in pvclock structure. If no bits are set, all flags are ignored. | 26 | * in pvclock structure. If no bits are set, all flags are ignored. |
@@ -32,9 +33,12 @@ | |||
32 | /* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */ | 33 | /* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */ |
33 | #define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00 | 34 | #define MSR_KVM_WALL_CLOCK_NEW 0x4b564d00 |
34 | #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01 | 35 | #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01 |
36 | #define MSR_KVM_ASYNC_PF_EN 0x4b564d02 | ||
35 | 37 | ||
36 | #define KVM_MAX_MMU_OP_BATCH 32 | 38 | #define KVM_MAX_MMU_OP_BATCH 32 |
37 | 39 | ||
40 | #define KVM_ASYNC_PF_ENABLED (1 << 0) | ||
41 | |||
38 | /* Operations for KVM_HC_MMU_OP */ | 42 | /* Operations for KVM_HC_MMU_OP */ |
39 | #define KVM_MMU_OP_WRITE_PTE 1 | 43 | #define KVM_MMU_OP_WRITE_PTE 1 |
40 | #define KVM_MMU_OP_FLUSH_TLB 2 | 44 | #define KVM_MMU_OP_FLUSH_TLB 2 |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index bd254779d1cc..063c07296764 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -783,12 +783,12 @@ EXPORT_SYMBOL_GPL(kvm_get_dr); | |||
783 | * kvm-specific. Those are put in the beginning of the list. | 783 | * kvm-specific. Those are put in the beginning of the list. |
784 | */ | 784 | */ |
785 | 785 | ||
786 | #define KVM_SAVE_MSRS_BEGIN 7 | 786 | #define KVM_SAVE_MSRS_BEGIN 8 |
787 | static u32 msrs_to_save[] = { | 787 | static u32 msrs_to_save[] = { |
788 | MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, | 788 | MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, |
789 | MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, | 789 | MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW, |
790 | HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, | 790 | HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL, |
791 | HV_X64_MSR_APIC_ASSIST_PAGE, | 791 | HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, |
792 | MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, | 792 | MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP, |
793 | MSR_STAR, | 793 | MSR_STAR, |
794 | #ifdef CONFIG_X86_64 | 794 | #ifdef CONFIG_X86_64 |
@@ -1425,6 +1425,29 @@ static int set_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
1425 | return 0; | 1425 | return 0; |
1426 | } | 1426 | } |
1427 | 1427 | ||
1428 | static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data) | ||
1429 | { | ||
1430 | gpa_t gpa = data & ~0x3f; | ||
1431 | |||
1432 | /* Bits 1:5 are resrved, Should be zero */ | ||
1433 | if (data & 0x3e) | ||
1434 | return 1; | ||
1435 | |||
1436 | vcpu->arch.apf.msr_val = data; | ||
1437 | |||
1438 | if (!(data & KVM_ASYNC_PF_ENABLED)) { | ||
1439 | kvm_clear_async_pf_completion_queue(vcpu); | ||
1440 | kvm_async_pf_hash_reset(vcpu); | ||
1441 | return 0; | ||
1442 | } | ||
1443 | |||
1444 | if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa)) | ||
1445 | return 1; | ||
1446 | |||
1447 | kvm_async_pf_wakeup_all(vcpu); | ||
1448 | return 0; | ||
1449 | } | ||
1450 | |||
1428 | int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | 1451 | int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) |
1429 | { | 1452 | { |
1430 | switch (msr) { | 1453 | switch (msr) { |
@@ -1506,6 +1529,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
1506 | } | 1529 | } |
1507 | break; | 1530 | break; |
1508 | } | 1531 | } |
1532 | case MSR_KVM_ASYNC_PF_EN: | ||
1533 | if (kvm_pv_enable_async_pf(vcpu, data)) | ||
1534 | return 1; | ||
1535 | break; | ||
1509 | case MSR_IA32_MCG_CTL: | 1536 | case MSR_IA32_MCG_CTL: |
1510 | case MSR_IA32_MCG_STATUS: | 1537 | case MSR_IA32_MCG_STATUS: |
1511 | case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1: | 1538 | case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1: |
@@ -1782,6 +1809,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |||
1782 | case MSR_KVM_SYSTEM_TIME_NEW: | 1809 | case MSR_KVM_SYSTEM_TIME_NEW: |
1783 | data = vcpu->arch.time; | 1810 | data = vcpu->arch.time; |
1784 | break; | 1811 | break; |
1812 | case MSR_KVM_ASYNC_PF_EN: | ||
1813 | data = vcpu->arch.apf.msr_val; | ||
1814 | break; | ||
1785 | case MSR_IA32_P5_MC_ADDR: | 1815 | case MSR_IA32_P5_MC_ADDR: |
1786 | case MSR_IA32_P5_MC_TYPE: | 1816 | case MSR_IA32_P5_MC_TYPE: |
1787 | case MSR_IA32_MCG_CAP: | 1817 | case MSR_IA32_MCG_CAP: |
@@ -1929,6 +1959,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
1929 | case KVM_CAP_DEBUGREGS: | 1959 | case KVM_CAP_DEBUGREGS: |
1930 | case KVM_CAP_X86_ROBUST_SINGLESTEP: | 1960 | case KVM_CAP_X86_ROBUST_SINGLESTEP: |
1931 | case KVM_CAP_XSAVE: | 1961 | case KVM_CAP_XSAVE: |
1962 | case KVM_CAP_ASYNC_PF: | ||
1932 | r = 1; | 1963 | r = 1; |
1933 | break; | 1964 | break; |
1934 | case KVM_CAP_COALESCED_MMIO: | 1965 | case KVM_CAP_COALESCED_MMIO: |
@@ -5792,6 +5823,8 @@ free_vcpu: | |||
5792 | 5823 | ||
5793 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) | 5824 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) |
5794 | { | 5825 | { |
5826 | vcpu->arch.apf.msr_val = 0; | ||
5827 | |||
5795 | vcpu_load(vcpu); | 5828 | vcpu_load(vcpu); |
5796 | kvm_mmu_unload(vcpu); | 5829 | kvm_mmu_unload(vcpu); |
5797 | vcpu_put(vcpu); | 5830 | vcpu_put(vcpu); |
@@ -5811,6 +5844,7 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu) | |||
5811 | vcpu->arch.dr7 = DR7_FIXED_1; | 5844 | vcpu->arch.dr7 = DR7_FIXED_1; |
5812 | 5845 | ||
5813 | kvm_make_request(KVM_REQ_EVENT, vcpu); | 5846 | kvm_make_request(KVM_REQ_EVENT, vcpu); |
5847 | vcpu->arch.apf.msr_val = 0; | ||
5814 | 5848 | ||
5815 | kvm_clear_async_pf_completion_queue(vcpu); | 5849 | kvm_clear_async_pf_completion_queue(vcpu); |
5816 | kvm_async_pf_hash_reset(vcpu); | 5850 | kvm_async_pf_hash_reset(vcpu); |