diff options
-rw-r--r-- | arch/x86/kvm/mmu.c | 17 | ||||
-rw-r--r-- | arch/x86/kvm/mmu.h | 3 | ||||
-rw-r--r-- | include/asm-x86/kvm_host.h | 1 |
3 files changed, 19 insertions, 2 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 8e449dbcc596..53f1ed852ca2 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -1122,8 +1122,10 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, | |||
1122 | else | 1122 | else |
1123 | kvm_release_pfn_clean(pfn); | 1123 | kvm_release_pfn_clean(pfn); |
1124 | } | 1124 | } |
1125 | if (!ptwrite || !*ptwrite) | 1125 | if (speculative) { |
1126 | vcpu->arch.last_pte_updated = shadow_pte; | 1126 | vcpu->arch.last_pte_updated = shadow_pte; |
1127 | vcpu->arch.last_pte_gfn = gfn; | ||
1128 | } | ||
1127 | } | 1129 | } |
1128 | 1130 | ||
1129 | static void nonpaging_new_cr3(struct kvm_vcpu *vcpu) | 1131 | static void nonpaging_new_cr3(struct kvm_vcpu *vcpu) |
@@ -1671,6 +1673,18 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
1671 | vcpu->arch.update_pte.pfn = pfn; | 1673 | vcpu->arch.update_pte.pfn = pfn; |
1672 | } | 1674 | } |
1673 | 1675 | ||
1676 | static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn) | ||
1677 | { | ||
1678 | u64 *spte = vcpu->arch.last_pte_updated; | ||
1679 | |||
1680 | if (spte | ||
1681 | && vcpu->arch.last_pte_gfn == gfn | ||
1682 | && shadow_accessed_mask | ||
1683 | && !(*spte & shadow_accessed_mask) | ||
1684 | && is_shadow_present_pte(*spte)) | ||
1685 | set_bit(PT_ACCESSED_SHIFT, (unsigned long *)spte); | ||
1686 | } | ||
1687 | |||
1674 | void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | 1688 | void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, |
1675 | const u8 *new, int bytes) | 1689 | const u8 *new, int bytes) |
1676 | { | 1690 | { |
@@ -1694,6 +1708,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
1694 | pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes); | 1708 | pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes); |
1695 | mmu_guess_page_from_pte_write(vcpu, gpa, new, bytes); | 1709 | mmu_guess_page_from_pte_write(vcpu, gpa, new, bytes); |
1696 | spin_lock(&vcpu->kvm->mmu_lock); | 1710 | spin_lock(&vcpu->kvm->mmu_lock); |
1711 | kvm_mmu_access_page(vcpu, gfn); | ||
1697 | kvm_mmu_free_some_pages(vcpu); | 1712 | kvm_mmu_free_some_pages(vcpu); |
1698 | ++vcpu->kvm->stat.mmu_pte_write; | 1713 | ++vcpu->kvm->stat.mmu_pte_write; |
1699 | kvm_mmu_audit(vcpu, "pre pte write"); | 1714 | kvm_mmu_audit(vcpu, "pre pte write"); |
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 1730757bbc7a..258e5d56298e 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h | |||
@@ -15,7 +15,8 @@ | |||
15 | #define PT_USER_MASK (1ULL << 2) | 15 | #define PT_USER_MASK (1ULL << 2) |
16 | #define PT_PWT_MASK (1ULL << 3) | 16 | #define PT_PWT_MASK (1ULL << 3) |
17 | #define PT_PCD_MASK (1ULL << 4) | 17 | #define PT_PCD_MASK (1ULL << 4) |
18 | #define PT_ACCESSED_MASK (1ULL << 5) | 18 | #define PT_ACCESSED_SHIFT 5 |
19 | #define PT_ACCESSED_MASK (1ULL << PT_ACCESSED_SHIFT) | ||
19 | #define PT_DIRTY_MASK (1ULL << 6) | 20 | #define PT_DIRTY_MASK (1ULL << 6) |
20 | #define PT_PAGE_SIZE_MASK (1ULL << 7) | 21 | #define PT_PAGE_SIZE_MASK (1ULL << 7) |
21 | #define PT_PAT_MASK (1ULL << 7) | 22 | #define PT_PAT_MASK (1ULL << 7) |
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 844f2a89afbc..c2d066e185f4 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h | |||
@@ -243,6 +243,7 @@ struct kvm_vcpu_arch { | |||
243 | gfn_t last_pt_write_gfn; | 243 | gfn_t last_pt_write_gfn; |
244 | int last_pt_write_count; | 244 | int last_pt_write_count; |
245 | u64 *last_pte_updated; | 245 | u64 *last_pte_updated; |
246 | gfn_t last_pte_gfn; | ||
246 | 247 | ||
247 | struct { | 248 | struct { |
248 | gfn_t gfn; /* presumed gfn during guest pte update */ | 249 | gfn_t gfn; /* presumed gfn during guest pte update */ |