aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2010-08-30 06:22:53 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:51:56 -0400
commit8b1fe17cc7a8b2c62b400dcbfaebd96da6b4f58e (patch)
treed453a7a24163e58fee9830b42c101fd717a0f67c /arch/x86/kvm
parent84e0cefa8ddd5d5018d3b582e1e90585ed551757 (diff)
KVM: MMU: support disable/enable mmu audit dynamicly
Add a r/w module parameter named 'mmu_audit', it can control audit enable/disable: enable: echo 1 > /sys/module/kvm/parameters/mmu_audit disable: echo 0 > /sys/module/kvm/parameters/mmu_audit This patch not change the logic Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/Kconfig7
-rw-r--r--arch/x86/kvm/mmu.c91
-rw-r--r--arch/x86/kvm/mmutrace.h19
-rw-r--r--arch/x86/kvm/paging_tmpl.h4
4 files changed, 101 insertions, 20 deletions
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 970bbd479516..ddc131ff438f 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -64,6 +64,13 @@ config KVM_AMD
64 To compile this as a module, choose M here: the module 64 To compile this as a module, choose M here: the module
65 will be called kvm-amd. 65 will be called kvm-amd.
66 66
67config KVM_MMU_AUDIT
68 bool "Audit KVM MMU"
69 depends on KVM && TRACEPOINTS
70 ---help---
71 This option adds a R/W kVM module parameter 'mmu_audit', which allows
72 audit KVM MMU at runtime.
73
67# OK, it's a little counter-intuitive to do this, but it puts it neatly under 74# OK, it's a little counter-intuitive to do this, but it puts it neatly under
68# the virtualization menu. 75# the virtualization menu.
69source drivers/vhost/Kconfig 76source drivers/vhost/Kconfig
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 0bff4d54817e..8b750ff6911a 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -49,15 +49,21 @@
49 */ 49 */
50bool tdp_enabled = false; 50bool tdp_enabled = false;
51 51
52#undef MMU_DEBUG 52enum {
53 AUDIT_PRE_PAGE_FAULT,
54 AUDIT_POST_PAGE_FAULT,
55 AUDIT_PRE_PTE_WRITE,
56 AUDIT_POST_PTE_WRITE
57};
53 58
54#undef AUDIT 59char *audit_point_name[] = {
60 "pre page fault",
61 "post page fault",
62 "pre pte write",
63 "post pte write"
64};
55 65
56#ifdef AUDIT 66#undef MMU_DEBUG
57static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg);
58#else
59static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg) {}
60#endif
61 67
62#ifdef MMU_DEBUG 68#ifdef MMU_DEBUG
63 69
@@ -71,7 +77,7 @@ static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg) {}
71 77
72#endif 78#endif
73 79
74#if defined(MMU_DEBUG) || defined(AUDIT) 80#ifdef MMU_DEBUG
75static int dbg = 0; 81static int dbg = 0;
76module_param(dbg, bool, 0644); 82module_param(dbg, bool, 0644);
77#endif 83#endif
@@ -2964,7 +2970,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
2964 kvm_mmu_access_page(vcpu, gfn); 2970 kvm_mmu_access_page(vcpu, gfn);
2965 kvm_mmu_free_some_pages(vcpu); 2971 kvm_mmu_free_some_pages(vcpu);
2966 ++vcpu->kvm->stat.mmu_pte_write; 2972 ++vcpu->kvm->stat.mmu_pte_write;
2967 kvm_mmu_audit(vcpu, "pre pte write"); 2973 trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE);
2968 if (guest_initiated) { 2974 if (guest_initiated) {
2969 if (gfn == vcpu->arch.last_pt_write_gfn 2975 if (gfn == vcpu->arch.last_pt_write_gfn
2970 && !last_updated_pte_accessed(vcpu)) { 2976 && !last_updated_pte_accessed(vcpu)) {
@@ -3037,7 +3043,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
3037 } 3043 }
3038 mmu_pte_write_flush_tlb(vcpu, zap_page, remote_flush, local_flush); 3044 mmu_pte_write_flush_tlb(vcpu, zap_page, remote_flush, local_flush);
3039 kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list); 3045 kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
3040 kvm_mmu_audit(vcpu, "post pte write"); 3046 trace_kvm_mmu_audit(vcpu, AUDIT_POST_PTE_WRITE);
3041 spin_unlock(&vcpu->kvm->mmu_lock); 3047 spin_unlock(&vcpu->kvm->mmu_lock);
3042 if (!is_error_pfn(vcpu->arch.update_pte.pfn)) { 3048 if (!is_error_pfn(vcpu->arch.update_pte.pfn)) {
3043 kvm_release_pfn_clean(vcpu->arch.update_pte.pfn); 3049 kvm_release_pfn_clean(vcpu->arch.update_pte.pfn);
@@ -3483,8 +3489,7 @@ int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])
3483} 3489}
3484EXPORT_SYMBOL_GPL(kvm_mmu_get_spte_hierarchy); 3490EXPORT_SYMBOL_GPL(kvm_mmu_get_spte_hierarchy);
3485 3491
3486#ifdef AUDIT 3492#ifdef CONFIG_KVM_MMU_AUDIT
3487
3488static const char *audit_msg; 3493static const char *audit_msg;
3489 3494
3490typedef void (*inspect_spte_fn) (struct kvm *kvm, u64 *sptep); 3495typedef void (*inspect_spte_fn) (struct kvm *kvm, u64 *sptep);
@@ -3699,18 +3704,68 @@ static void audit_write_protection(struct kvm_vcpu *vcpu)
3699 } 3704 }
3700} 3705}
3701 3706
3702static void kvm_mmu_audit(struct kvm_vcpu *vcpu, const char *msg) 3707static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int audit_point)
3703{ 3708{
3704 int olddbg = dbg; 3709 audit_msg = audit_point_name[audit_point];
3705
3706 dbg = 0;
3707 audit_msg = msg;
3708 audit_rmap(vcpu); 3710 audit_rmap(vcpu);
3709 audit_write_protection(vcpu); 3711 audit_write_protection(vcpu);
3710 if (strcmp("pre pte write", audit_msg) != 0) 3712 if (strcmp("pre pte write", audit_msg) != 0)
3711 audit_mappings(vcpu); 3713 audit_mappings(vcpu);
3712 audit_sptes_have_rmaps(vcpu); 3714 audit_sptes_have_rmaps(vcpu);
3713 dbg = olddbg;
3714} 3715}
3715 3716
3717static bool mmu_audit;
3718
3719static void mmu_audit_enable(void)
3720{
3721 int ret;
3722
3723 if (mmu_audit)
3724 return;
3725
3726 ret = register_trace_kvm_mmu_audit(kvm_mmu_audit, NULL);
3727 WARN_ON(ret);
3728
3729 mmu_audit = true;
3730}
3731
3732static void mmu_audit_disable(void)
3733{
3734 if (!mmu_audit)
3735 return;
3736
3737 unregister_trace_kvm_mmu_audit(kvm_mmu_audit, NULL);
3738 tracepoint_synchronize_unregister();
3739 mmu_audit = false;
3740}
3741
3742static int mmu_audit_set(const char *val, const struct kernel_param *kp)
3743{
3744 int ret;
3745 unsigned long enable;
3746
3747 ret = strict_strtoul(val, 10, &enable);
3748 if (ret < 0)
3749 return -EINVAL;
3750
3751 switch (enable) {
3752 case 0:
3753 mmu_audit_disable();
3754 break;
3755 case 1:
3756 mmu_audit_enable();
3757 break;
3758 default:
3759 return -EINVAL;
3760 }
3761
3762 return 0;
3763}
3764
3765static struct kernel_param_ops audit_param_ops = {
3766 .set = mmu_audit_set,
3767 .get = param_get_bool,
3768};
3769
3770module_param_cb(mmu_audit, &audit_param_ops, &mmu_audit, 0644);
3716#endif 3771#endif
diff --git a/arch/x86/kvm/mmutrace.h b/arch/x86/kvm/mmutrace.h
index 3aab0f0930ef..b60b4fdb3eda 100644
--- a/arch/x86/kvm/mmutrace.h
+++ b/arch/x86/kvm/mmutrace.h
@@ -195,6 +195,25 @@ DEFINE_EVENT(kvm_mmu_page_class, kvm_mmu_prepare_zap_page,
195 195
196 TP_ARGS(sp) 196 TP_ARGS(sp)
197); 197);
198
199TRACE_EVENT(
200 kvm_mmu_audit,
201 TP_PROTO(struct kvm_vcpu *vcpu, int audit_point),
202 TP_ARGS(vcpu, audit_point),
203
204 TP_STRUCT__entry(
205 __field(struct kvm_vcpu *, vcpu)
206 __field(int, audit_point)
207 ),
208
209 TP_fast_assign(
210 __entry->vcpu = vcpu;
211 __entry->audit_point = audit_point;
212 ),
213
214 TP_printk("vcpu:%d %s", __entry->vcpu->cpu,
215 audit_point_name[__entry->audit_point])
216);
198#endif /* _TRACE_KVMMMU_H */ 217#endif /* _TRACE_KVMMMU_H */
199 218
200#undef TRACE_INCLUDE_PATH 219#undef TRACE_INCLUDE_PATH
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index a0f2febf5692..debe77035366 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -542,7 +542,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
542 if (mmu_notifier_retry(vcpu, mmu_seq)) 542 if (mmu_notifier_retry(vcpu, mmu_seq))
543 goto out_unlock; 543 goto out_unlock;
544 544
545 kvm_mmu_audit(vcpu, "pre page fault"); 545 trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT);
546 kvm_mmu_free_some_pages(vcpu); 546 kvm_mmu_free_some_pages(vcpu);
547 sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault, 547 sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
548 level, &write_pt, pfn); 548 level, &write_pt, pfn);
@@ -554,7 +554,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
554 vcpu->arch.last_pt_write_count = 0; /* reset fork detector */ 554 vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
555 555
556 ++vcpu->stat.pf_fixed; 556 ++vcpu->stat.pf_fixed;
557 kvm_mmu_audit(vcpu, "post page fault (fixed)"); 557 trace_kvm_mmu_audit(vcpu, AUDIT_POST_PAGE_FAULT);
558 spin_unlock(&vcpu->kvm->mmu_lock); 558 spin_unlock(&vcpu->kvm->mmu_lock);
559 559
560 return write_pt; 560 return write_pt;