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 */ |
