[PATCH 5/7] ARM: KVM: parametrize HYP page table freeing

Christoffer Dall cdall at cs.columbia.edu
Wed Apr 3 19:15:23 EDT 2013


On Tue, Apr 02, 2013 at 02:25:13PM +0100, Marc Zyngier wrote:
> In order to prepare for having to deal with multiple HYP page tables,
> pass the PGD parameter to the function performing the freeing of the
> page tables.
> 
> Also move the freeing of the PGD itself there, and rename the
> free_hyp_pmds to free_hyp_pgds.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
>  arch/arm/include/asm/kvm_mmu.h |  2 +-
>  arch/arm/kvm/arm.c             |  2 +-
>  arch/arm/kvm/mmu.c             | 30 +++++++++++++++++-------------
>  3 files changed, 19 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
> index 3c71a1d..92eb20d 100644
> --- a/arch/arm/include/asm/kvm_mmu.h
> +++ b/arch/arm/include/asm/kvm_mmu.h
> @@ -32,7 +32,7 @@
>  
>  int create_hyp_mappings(void *from, void *to);
>  int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
> -void free_hyp_pmds(void);
> +void free_hyp_pgds(void);
>  
>  int kvm_alloc_stage2_pgd(struct kvm *kvm);
>  void kvm_free_stage2_pgd(struct kvm *kvm);
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 2ce90bb..6eba879 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -936,7 +936,7 @@ static int init_hyp_mode(void)
>  out_free_context:
>  	free_percpu(kvm_host_cpu_state);
>  out_free_mappings:
> -	free_hyp_pmds();
> +	free_hyp_pgds();
>  out_free_stack_pages:
>  	for_each_possible_cpu(cpu)
>  		free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
> diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
> index 7d23480..85b3553 100644
> --- a/arch/arm/kvm/mmu.c
> +++ b/arch/arm/kvm/mmu.c
> @@ -86,42 +86,46 @@ static void free_ptes(pmd_t *pmd, unsigned long addr)
>  	}
>  }
>  
> -static void free_hyp_pgd_entry(unsigned long addr)
> +static void free_hyp_pgd_entry(pgd_t *pgdp, unsigned long addr)
>  {
>  	pgd_t *pgd;
>  	pud_t *pud;
>  	pmd_t *pmd;
> -	unsigned long hyp_addr = KERN_TO_HYP(addr);
>  
> -	pgd = hyp_pgd + pgd_index(hyp_addr);
> -	pud = pud_offset(pgd, hyp_addr);
> +	pgd = pgdp + pgd_index(addr);
> +	pud = pud_offset(pgd, addr);
>  
>  	if (pud_none(*pud))
>  		return;
>  	BUG_ON(pud_bad(*pud));
>  
> -	pmd = pmd_offset(pud, hyp_addr);
> +	pmd = pmd_offset(pud, addr);
>  	free_ptes(pmd, addr);
>  	pmd_free(NULL, pmd);
>  	pud_clear(pud);
>  }
>  
>  /**
> - * free_hyp_pmds - free a Hyp-mode level-2 tables and child level-3 tables
> + * free_hyp_pgds - free Hyp-mode page tables
>   *
> - * Assumes this is a page table used strictly in Hyp-mode and therefore contains
> + * Assumes hyp_pgd is a page table used strictly in Hyp-mode and therefore contains
>   * either mappings in the kernel memory area (above PAGE_OFFSET), or
>   * device mappings in the vmalloc range (from VMALLOC_START to VMALLOC_END).
>   */
> -void free_hyp_pmds(void)
> +void free_hyp_pgds(void)
>  {
>  	unsigned long addr;
>  
>  	mutex_lock(&kvm_hyp_pgd_mutex);
> -	for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE)
> -		free_hyp_pgd_entry(addr);
> -	for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
> -		free_hyp_pgd_entry(addr);
> +
> +	if (hyp_pgd) {
> +		for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE)
> +			free_hyp_pgd_entry(hyp_pgd, KERN_TO_HYP(addr));
> +		for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
> +			free_hyp_pgd_entry(hyp_pgd, KERN_TO_HYP(addr));
> +		kfree(hyp_pgd);
> +	}
> +
>  	mutex_unlock(&kvm_hyp_pgd_mutex);
>  }
>  
> @@ -741,7 +745,7 @@ int kvm_mmu_init(void)
>  
>  	return 0;
>  out:
> -	kfree(hyp_pgd);
> +	free_hyp_pgds();
>  	return err;
>  }
>  
> -- 
> 1.8.1.4
> 
> 

Acked-by: Christoffer Dall <cdall at cs.columbia.edu>



More information about the linux-arm-kernel mailing list