KVM: MMU: audit: allow audit more guests at the same time
PATCH RESEND 1/2 KVM: MMU: audit: allow audit more guests at the same time
It only allows to audit one guest in the system since:
- 'audit_point' is a glob variable
- mmu_audit_disable() is called in kvm_mmu_destroy(), so audit is disabled after a guest exited
this patch fix those issues then allow to audit more guests at the same time
--- arch/x86/include/asm/kvm_host.h | 4 ++++ arch/x86/kvm/mmu.c | 26 +++++++++++++------------- arch/x86/kvm/mmu_audit.c | 39 ++++++++++++++++++++++----------------- 3 files changed, 39 insertions(+), 30 deletions(-)
arch/x86/include/asm/kvm_host.h +4 -0
@@ -460,6 +460,10 @@ struct kvm_arch {/* fields used by HYPER-V emulation */ u64 hv_guest_os_id;u64 hv_hypercall; + +#ifdef CONFIG_KVM_MMU_AUDIT +int audit_point; +#endif };struct kvm_vm_stat {
arch/x86/kvm/mmu.c +13 -13
@@ -3528,13 +3528,6 @@ static void mmu_destroy_caches(void)kmem_cache_destroy (mmu_page_header_cache); } -void kvm_mmu_module_exit (void ) -{ -mmu_destroy_caches (); -percpu_counter_destroy (&kvm_total_used_mmu_pages); -unregister_shrinker (&mmu_shrinker); -} -int kvm_mmu_module_init (void ) { pte_chain_cache = kmem_cache_create("kvm_pte_chain",
@@ -3727,12 +3720,6 @@ int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]) }EXPORT_SYMBOL_GPL (kvm_mmu_get_spte_hierarchy); -#ifdef CONFIG_KVM_MMU_AUDIT -#include "mmu_audit.c" -#else -static void mmu_audit_disable (void ) { } -#endif -void kvm_mmu_destroy (struct kvm_vcpu *vcpu) {ASSERT (vcpu);
@@ -3740,5 +3727,18 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu)destroy_kvm_mmu (vcpu);free_mmu_pages (vcpu);mmu_free_memory_caches (vcpu); +} + +#ifdef CONFIG_KVM_MMU_AUDIT +#include "mmu_audit.c" +#else +static void mmu_audit_disable (void ) { } +#endif + +void kvm_mmu_module_exit (void ) +{ +mmu_destroy_caches (); +percpu_counter_destroy (&kvm_total_used_mmu_pages); +unregister_shrinker (&mmu_shrinker);mmu_audit_disable (); }
arch/x86/kvm/mmu_audit.c +22 -17
@@ -19,11 +19,9 @@#include <linux/ratelimit.h> -static int audit_point; - -#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,18 +95,21 @@ 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); +audit_printk (vcpu->kvm,"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,"notrap spte in unsync " +"sp: %p\n" , sp);return ; } }if (sp->role.direct && *sptep == shadow_notrap_nonpresent_pte) { -audit_printk ("notrap spte in direct sp: %p\n" , sp); +audit_printk (vcpu->kvm,"notrap spte in direct sp: %p\n" , + sp);return ; }
@@ -125,8 +126,9 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level) 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)
@@ -142,8 +144,8 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)if (!gfn_to_memslot (kvm, gfn)) {if (!printk_ratelimit ())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 ;
@@ -153,7 +155,8 @@ static void inspect_spte_has_rmap(struct kvm *kvm, u64 *sptep)if (!*rmapp) {if (!printk_ratelimit ())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 +171,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)
@@ -202,8 +206,9 @@ static void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp) 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); +audit_printk (kvm,"shadow page has writable " +"mappings: gfn %llx role %x\n" , + sp->gfn, sp->role.word); spte =rmap_next (kvm, rmapp, spte); } }
@@ -238,7 +243,7 @@ static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int point)if (!__ratelimit (&ratelimit_state))return ; - audit_point = point; + vcpu->kvm->arch.audit_point = point;audit_all_active_sps (vcpu->kvm);audit_vcpu_spte (vcpu); }
Signature · 1 line
1.7.0.4
PATCH 2/2 KVM: MMU: handle 'map_writable' in set_spte() function
Move the operation of 'writable' to set_spte() to clean up code
--- arch/x86/kvm/mmu.c | 4 ++-- arch/x86/kvm/paging_tmpl.h | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-)
arch/x86/kvm/mmu.c +2 -2
@@ -1983,6 +1983,8 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,if (host_writable) spte |=SPTE_HOST_WRITEABLE ; +else + pte_access &= ~ACC_WRITE_MASK ; spte |= (u64 )pfn <<PAGE_SHIFT ;
@@ -2222,8 +2224,6 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,if (iterator.level == level) {unsigned pte_access =ACC_ALL ; -if (!map_writable) - pte_access &= ~ACC_WRITE_MASK ;mmu_set_spte (vcpu, iterator.sptep,ACC_ALL , pte_access,0 , write,1 , &pt_write, level, gfn, pfn, prefault, map_writable);
arch/x86/kvm/paging_tmpl.h +2 -9
@@ -511,9 +511,6 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,link_shadow_page (it.sptep, sp); } -if (!map_writable) - access &= ~ACC_WRITE_MASK ; -mmu_set_spte (vcpu, it.sptep, access, gw->pte_access & access, user_fault, write_fault, dirty, ptwrite, it.level, gw->gfn, pfn, prefault, map_writable);
@@ -809,12 +806,8 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) nr_present++; pte_access = sp->role.access &FNAME (gpte_access)(vcpu, gpte); -if (!(sp->spt[i] &SPTE_HOST_WRITEABLE )) { - pte_access &= ~ACC_WRITE_MASK ; - host_writable =0 ; - }else { - host_writable =1 ; - } + host_writable = !!(sp->spt[i] &SPTE_HOST_WRITEABLE ); + set_spte(vcpu, &sp->spt[i], pte_access, 0, 0, is_dirty_gpte(gpte), PT_PAGE_TABLE_LEVEL, gfn, spte_to_pfn(sp->spt[i]), true, false,
Signature · 1 line
1.7.0.4
Avi Kivity
AppliedRe: [PATCH 2/2] KVM: MMU: handle 'map_writable' in set_spte() function
Quoted 2 lines · Xiao Guangrong
Move the operation of 'writable' to
set_spte()to clean up code
Thanks, applied.
arch/x86/kvm/paging_tmpl.h static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) · line 810
Quoted 12 lines
arch/x86/kvm/paging_tmpl.h +2
-6@@ -809,12 +806,8 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) nr_present++; pte_access = sp->role.access&FNAME (gpte_access)(vcpu, gpte); -if (!(sp->spt[i]&SPTE_HOST_WRITEABLE )) { - pte_access&= ~ACC_WRITE_MASK ; - host_writable =0 ; - }else { - host_writable =1 ; - } + host_writable = !!(sp->spt[i]&SPTE_HOST_WRITEABLE ); +
Note, !! is unneeded when assigning to a boolean variable. I removed it.
Signature · 1 line
error compiling committee.c: too many arguments to function