aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/mmu.c
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2009-06-10 11:27:04 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:32:53 -0400
commit08a3732bf2e68048c9166e929ca2115127a412ab (patch)
tree6f741496cf7c0932512e8af2833ca2596b4aebf9 /arch/x86/kvm/mmu.c
parent776e6633363b5616be6fa4493a8b70ef8e2ea04b (diff)
KVM: MMU audit: update count_writable_mappings / count_rmaps
Under testing, count_writable_mappings returns a value that is 2 integers larger than what count_rmaps returns. Suspicion is that either of the two functions is counting a duplicate (either positively or negatively). Modifying check_writable_mappings_rmap to check for rmap existance on all present MMU pages fails to trigger an error, which should keep Avi happy. Also introduce mmu_spte_walk to invoke a callback on all present sptes visible to the current vcpu, might be useful in the future. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r--arch/x86/kvm/mmu.c104
1 files changed, 94 insertions, 10 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index f85d9953a620..fd5579cc8abd 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3045,6 +3045,55 @@ static gva_t canonicalize(gva_t gva)
3045 return gva; 3045 return gva;
3046} 3046}
3047 3047
3048
3049typedef void (*inspect_spte_fn) (struct kvm *kvm, struct kvm_mmu_page *sp,
3050 u64 *sptep);
3051
3052static void __mmu_spte_walk(struct kvm *kvm, struct kvm_mmu_page *sp,
3053 inspect_spte_fn fn)
3054{
3055 int i;
3056
3057 for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
3058 u64 ent = sp->spt[i];
3059
3060 if (is_shadow_present_pte(ent)) {
3061 if (sp->role.level > 1 && !is_large_pte(ent)) {
3062 struct kvm_mmu_page *child;
3063 child = page_header(ent & PT64_BASE_ADDR_MASK);
3064 __mmu_spte_walk(kvm, child, fn);
3065 }
3066 if (sp->role.level == 1)
3067 fn(kvm, sp, &sp->spt[i]);
3068 }
3069 }
3070}
3071
3072static void mmu_spte_walk(struct kvm_vcpu *vcpu, inspect_spte_fn fn)
3073{
3074 int i;
3075 struct kvm_mmu_page *sp;
3076
3077 if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
3078 return;
3079 if (vcpu->arch.mmu.shadow_root_level == PT64_ROOT_LEVEL) {
3080 hpa_t root = vcpu->arch.mmu.root_hpa;
3081 sp = page_header(root);
3082 __mmu_spte_walk(vcpu->kvm, sp, fn);
3083 return;
3084 }
3085 for (i = 0; i < 4; ++i) {
3086 hpa_t root = vcpu->arch.mmu.pae_root[i];
3087
3088 if (root && VALID_PAGE(root)) {
3089 root &= PT64_BASE_ADDR_MASK;
3090 sp = page_header(root);
3091 __mmu_spte_walk(vcpu->kvm, sp, fn);
3092 }
3093 }
3094 return;
3095}
3096
3048static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte, 3097static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
3049 gva_t va, int level) 3098 gva_t va, int level)
3050{ 3099{
@@ -3137,9 +3186,47 @@ static int count_rmaps(struct kvm_vcpu *vcpu)
3137 return nmaps; 3186 return nmaps;
3138} 3187}
3139 3188
3140static int count_writable_mappings(struct kvm_vcpu *vcpu) 3189void inspect_spte_has_rmap(struct kvm *kvm, struct kvm_mmu_page *sp, u64 *sptep)
3190{
3191 unsigned long *rmapp;
3192 struct kvm_mmu_page *rev_sp;
3193 gfn_t gfn;
3194
3195 if (*sptep & PT_WRITABLE_MASK) {
3196 rev_sp = page_header(__pa(sptep));
3197 gfn = rev_sp->gfns[sptep - rev_sp->spt];
3198
3199 if (!gfn_to_memslot(kvm, gfn)) {
3200 if (!printk_ratelimit())
3201 return;
3202 printk(KERN_ERR "%s: no memslot for gfn %ld\n",
3203 audit_msg, gfn);
3204 printk(KERN_ERR "%s: index %ld of sp (gfn=%lx)\n",
3205 audit_msg, sptep - rev_sp->spt,
3206 rev_sp->gfn);
3207 dump_stack();
3208 return;
3209 }
3210
3211 rmapp = gfn_to_rmap(kvm, rev_sp->gfns[sptep - rev_sp->spt], 0);
3212 if (!*rmapp) {
3213 if (!printk_ratelimit())
3214 return;
3215 printk(KERN_ERR "%s: no rmap for writable spte %llx\n",
3216 audit_msg, *sptep);
3217 dump_stack();
3218 }
3219 }
3220
3221}
3222
3223void audit_writable_sptes_have_rmaps(struct kvm_vcpu *vcpu)
3224{
3225 mmu_spte_walk(vcpu, inspect_spte_has_rmap);
3226}
3227
3228static void check_writable_mappings_rmap(struct kvm_vcpu *vcpu)
3141{ 3229{
3142 int nmaps = 0;
3143 struct kvm_mmu_page *sp; 3230 struct kvm_mmu_page *sp;
3144 int i; 3231 int i;
3145 3232
@@ -3156,20 +3243,16 @@ static int count_writable_mappings(struct kvm_vcpu *vcpu)
3156 continue; 3243 continue;
3157 if (!(ent & PT_WRITABLE_MASK)) 3244 if (!(ent & PT_WRITABLE_MASK))
3158 continue; 3245 continue;
3159 ++nmaps; 3246 inspect_spte_has_rmap(vcpu->kvm, sp, &pt[i]);
3160 } 3247 }
3161 } 3248 }
3162 return nmaps; 3249 return;
3163} 3250}
3164 3251
3165static void audit_rmap(struct kvm_vcpu *vcpu) 3252static void audit_rmap(struct kvm_vcpu *vcpu)
3166{ 3253{
3167 int n_rmap = count_rmaps(vcpu); 3254 check_writable_mappings_rmap(vcpu);
3168 int n_actual = count_writable_mappings(vcpu); 3255 count_rmaps(vcpu);
3169
3170 if (n_rmap != n_actual)
3171 printk(KERN_ERR "%s: (%s) rmap %d actual %d\n",
3172 __func__, audit_msg, n_rmap, n_actual);
3173} 3256}
3174 3257
3175static void audit_write_protection(struct kvm_vcpu *vcpu) 3258static void audit_write_protection(struct kvm_vcpu *vcpu)
@@ -3203,6 +3286,7 @@ static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg)
3203 audit_rmap(vcpu); 3286 audit_rmap(vcpu);
3204 audit_write_protection(vcpu); 3287 audit_write_protection(vcpu);
3205 audit_mappings(vcpu); 3288 audit_mappings(vcpu);
3289 audit_writable_sptes_have_rmaps(vcpu);
3206 dbg = olddbg; 3290 dbg = olddbg;
3207} 3291}
3208 3292