diff options
Diffstat (limited to 'arch/x86/kvm/mmu_audit.c')
| -rw-r--r-- | arch/x86/kvm/mmu_audit.c | 96 | 
1 files changed, 48 insertions, 48 deletions
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c index ba2bcdde622..1185fe7a7f4 100644 --- a/arch/x86/kvm/mmu_audit.c +++ b/arch/x86/kvm/mmu_audit.c @@ -19,11 +19,18 @@  #include <linux/ratelimit.h> -static int audit_point; +char const *audit_point_name[] = { +	"pre page fault", +	"post page fault", +	"pre pte write", +	"post pte write", +	"pre sync", +	"post sync" +}; -#define audit_printk(fmt, args...)		\ +#define audit_printk(kvm, fmt, args...)		\  	printk(KERN_ERR "audit: (%s) error: "	\ -		fmt, audit_point_name[audit_point], ##args) +		fmt, audit_point_name[kvm->arch.audit_point], ##args)  typedef void (*inspect_spte_fn) (struct kvm_vcpu *vcpu, u64 *sptep, int level); @@ -97,53 +104,43 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)  	if (sp->unsync) {  		if (level != PT_PAGE_TABLE_LEVEL) { -			audit_printk("unsync sp: %p level = %d\n", sp, level); -			return; -		} - -		if (*sptep == shadow_notrap_nonpresent_pte) { -			audit_printk("notrap spte in unsync sp: %p\n", sp); +			audit_printk(vcpu->kvm, "unsync sp: %p " +				     "level = %d\n", sp, level);  			return;  		}  	} -	if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) { -		audit_printk("notrap spte in direct sp: %p\n", sp); -		return; -	} -  	if (!is_shadow_present_pte(*sptep) || !is_last_spte(*sptep, level))  		return;  	gfn = kvm_mmu_page_get_gfn(sp, sptep - sp->spt);  	pfn = gfn_to_pfn_atomic(vcpu->kvm, gfn); -	if (is_error_pfn(pfn)) { -		kvm_release_pfn_clean(pfn); +	if (is_error_pfn(pfn))  		return; -	}  	hpa =  pfn << PAGE_SHIFT;  	if ((*sptep & PT64_BASE_ADDR_MASK) != hpa) -		audit_printk("levels %d pfn %llx hpa %llx ent %llxn", -				   vcpu->arch.mmu.root_level, pfn, hpa, *sptep); +		audit_printk(vcpu->kvm, "levels %d pfn %llx hpa %llx " +			     "ent %llxn", vcpu->arch.mmu.root_level, pfn, +			     hpa, *sptep);  }  static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)  { +	static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);  	unsigned long *rmapp;  	struct kvm_mmu_page *rev_sp;  	gfn_t gfn; -  	rev_sp = page_header(__pa(sptep));  	gfn = kvm_mmu_page_get_gfn(rev_sp, sptep - rev_sp->spt);  	if (!gfn_to_memslot(kvm, gfn)) { -		if (!printk_ratelimit()) +		if (!__ratelimit(&ratelimit_state))  			return; -		audit_printk("no memslot for gfn %llx\n", gfn); -		audit_printk("index %ld of sp (gfn=%llx)\n", +		audit_printk(kvm, "no memslot for gfn %llx\n", gfn); +		audit_printk(kvm, "index %ld of sp (gfn=%llx)\n",  		       (long int)(sptep - rev_sp->spt), rev_sp->gfn);  		dump_stack();  		return; @@ -151,9 +148,10 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)  	rmapp = gfn_to_rmap(kvm, gfn, rev_sp->role.level);  	if (!*rmapp) { -		if (!printk_ratelimit()) +		if (!__ratelimit(&ratelimit_state))  			return; -		audit_printk("no rmap for writable spte %llx\n", *sptep); +		audit_printk(kvm, "no rmap for writable spte %llx\n", +			     *sptep);  		dump_stack();  	}  } @@ -168,8 +166,9 @@ static void audit_spte_after_sync(struct kvm_vcpu *vcpu, u64 *sptep, int level)  {  	struct kvm_mmu_page *sp = page_header(__pa(sptep)); -	if (audit_point == AUDIT_POST_SYNC && sp->unsync) -		audit_printk("meet unsync sp(%p) after sync root.\n", sp); +	if (vcpu->kvm->arch.audit_point == AUDIT_POST_SYNC && sp->unsync) +		audit_printk(vcpu->kvm, "meet unsync sp(%p) after sync " +			     "root.\n", sp);  }  static void check_mappings_rmap(struct kvm *kvm, struct kvm_mmu_page *sp) @@ -189,22 +188,21 @@ static void check_mappings_rmap(struct kvm *kvm, struct kvm_mmu_page *sp)  static void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp)  { -	struct kvm_memory_slot *slot;  	unsigned long *rmapp; -	u64 *spte; +	u64 *sptep; +	struct rmap_iterator iter;  	if (sp->role.direct || sp->unsync || sp->role.invalid)  		return; -	slot = gfn_to_memslot(kvm, sp->gfn); -	rmapp = &slot->rmap[sp->gfn - slot->base_gfn]; +	rmapp = gfn_to_rmap(kvm, sp->gfn, PT_PAGE_TABLE_LEVEL); -	spte = rmap_next(kvm, rmapp, NULL); -	while (spte) { -		if (is_writable_pte(*spte)) -			audit_printk("shadow page has writable mappings: gfn " -				     "%llx role %x\n", sp->gfn, sp->role.word); -		spte = rmap_next(kvm, rmapp, spte); +	for (sptep = rmap_get_first(*rmapp, &iter); sptep; +	     sptep = rmap_get_next(&iter)) { +		if (is_writable_pte(*sptep)) +			audit_printk(kvm, "shadow page has writable " +				     "mappings: gfn %llx role %x\n", +				     sp->gfn, sp->role.word);  	}  } @@ -231,30 +229,33 @@ static void audit_vcpu_spte(struct kvm_vcpu *vcpu)  	mmu_spte_walk(vcpu, audit_spte);  } -static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int point) +static bool mmu_audit; +static struct static_key mmu_audit_key; + +static void __kvm_mmu_audit(struct kvm_vcpu *vcpu, int point)  {  	static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);  	if (!__ratelimit(&ratelimit_state))  		return; -	audit_point = point; +	vcpu->kvm->arch.audit_point = point;  	audit_all_active_sps(vcpu->kvm);  	audit_vcpu_spte(vcpu);  } -static bool mmu_audit; +static inline void kvm_mmu_audit(struct kvm_vcpu *vcpu, int point) +{ +	if (static_key_false((&mmu_audit_key))) +		__kvm_mmu_audit(vcpu, point); +}  static void mmu_audit_enable(void)  { -	int ret; -  	if (mmu_audit)  		return; -	ret = register_trace_kvm_mmu_audit(kvm_mmu_audit, NULL); -	WARN_ON(ret); - +	static_key_slow_inc(&mmu_audit_key);  	mmu_audit = true;  } @@ -263,8 +264,7 @@ static void mmu_audit_disable(void)  	if (!mmu_audit)  		return; -	unregister_trace_kvm_mmu_audit(kvm_mmu_audit, NULL); -	tracepoint_synchronize_unregister(); +	static_key_slow_dec(&mmu_audit_key);  	mmu_audit = false;  } @@ -296,4 +296,4 @@ static struct kernel_param_ops audit_param_ops = {  	.get = param_get_bool,  }; -module_param_cb(mmu_audit, &audit_param_ops, &mmu_audit, 0644); +arch_param_cb(mmu_audit, &audit_param_ops, &mmu_audit, 0644);  | 
