On Tue, Jan 08, 2013 at 01:38:48PM -0500, Christoffer Dall wrote:
> Add a method (hyp_idmap_setup) to populate a hyp pgd with an
> identity mapping of the code contained in the .hyp.idmap.text
> section.
> 
> Offer a method to drop this identity mapping through
> hyp_idmap_teardown.
> 
> Make all the above depend on CONFIG_ARM_VIRT_EXT and CONFIG_ARM_LPAE.
> 
> Cc: Will Deacon <[email protected]>
> Reviewed-by: Marcelo Tosatti <[email protected]>
> Signed-off-by: Marc Zyngier <[email protected]>
> Signed-off-by: Christoffer Dall <[email protected]>
> ---
>  arch/arm/include/asm/idmap.h                |    1 +
>  arch/arm/include/asm/pgtable-3level-hwdef.h |    1 +
>  arch/arm/kernel/vmlinux.lds.S               |    6 +++
>  arch/arm/mm/idmap.c                         |   54 
> ++++++++++++++++++++++-----
>  4 files changed, 50 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h
> index bf863ed..1a66f907 100644
> --- a/arch/arm/include/asm/idmap.h
> +++ b/arch/arm/include/asm/idmap.h
> @@ -8,6 +8,7 @@
>  #define __idmap __section(.idmap.text) noinline notrace
>  
>  extern pgd_t *idmap_pgd;
> +extern pgd_t *hyp_pgd;
>  
>  void setup_mm_for_reboot(void);
>  
> diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h 
> b/arch/arm/include/asm/pgtable-3level-hwdef.h
> index d795282..a2d404e 100644
> --- a/arch/arm/include/asm/pgtable-3level-hwdef.h
> +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h
> @@ -44,6 +44,7 @@
>  #define PMD_SECT_XN          (_AT(pmdval_t, 1) << 54)
>  #define PMD_SECT_AP_WRITE    (_AT(pmdval_t, 0))
>  #define PMD_SECT_AP_READ     (_AT(pmdval_t, 0))
> +#define PMD_SECT_AP1         (_AT(pmdval_t, 1) << 6)
>  #define PMD_SECT_TEX(x)              (_AT(pmdval_t, 0))
>  
>  /*
> diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
> index 11c1785..b571484 100644
> --- a/arch/arm/kernel/vmlinux.lds.S
> +++ b/arch/arm/kernel/vmlinux.lds.S
> @@ -19,7 +19,11 @@
>       ALIGN_FUNCTION();                                               \
>       VMLINUX_SYMBOL(__idmap_text_start) = .;                         \
>       *(.idmap.text)                                                  \
> -     VMLINUX_SYMBOL(__idmap_text_end) = .;
> +     VMLINUX_SYMBOL(__idmap_text_end) = .;                           \
> +     ALIGN_FUNCTION();                                               \
> +     VMLINUX_SYMBOL(__hyp_idmap_text_start) = .;                     \
> +     *(.hyp.idmap.text)                                              \
> +     VMLINUX_SYMBOL(__hyp_idmap_text_end) = .;
>  
>  #ifdef CONFIG_HOTPLUG_CPU
>  #define ARM_CPU_DISCARD(x)
> diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
> index 99db769..d9213a5 100644
> --- a/arch/arm/mm/idmap.c
> +++ b/arch/arm/mm/idmap.c
> @@ -1,4 +1,6 @@
> +#include <linux/module.h>
>  #include <linux/kernel.h>
> +#include <linux/slab.h>
>  
>  #include <asm/cputype.h>
>  #include <asm/idmap.h>
> @@ -6,6 +8,7 @@
>  #include <asm/pgtable.h>
>  #include <asm/sections.h>
>  #include <asm/system_info.h>
> +#include <asm/virt.h>
>  
>  pgd_t *idmap_pgd;
>  
> @@ -59,11 +62,20 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, 
> unsigned long end,
>       } while (pud++, addr = next, addr != end);
>  }
>  
> -static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned 
> long end)
> +static void identity_mapping_add(pgd_t *pgd, const char *text_start,
> +                              const char *text_end, unsigned long prot)
>  {
> -     unsigned long prot, next;
> +     unsigned long addr, end;
> +     unsigned long next;
> +
> +     addr = virt_to_phys(text_start);
> +     end = virt_to_phys(text_end);
How does this work with phys addresses greater than 32bit (with
LPAE)? This was the same before the patch too, but I am still
curious. Since __virt_to_phys() returns unsigned long kernel cannot be
put in high memory, right?


> +
> +     pr_info("Setting up static %sidentity map for 0x%llx - 0x%llx\n",
> +             prot ? "HYP " : "",
> +             (long long)addr, (long long)end);
> +     prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
>  
> -     prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
>       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
>               prot |= PMD_BIT4;
>  
> @@ -74,28 +86,48 @@ static void identity_mapping_add(pgd_t *pgd, unsigned 
> long addr, unsigned long e
>       } while (pgd++, addr = next, addr != end);
>  }
>  
> +#ifdef CONFIG_ARM_VIRT_EXT
> +pgd_t *hyp_pgd;
> +
> +extern char  __hyp_idmap_text_start[], __hyp_idmap_text_end[];
> +
> +static int __init init_static_idmap_hyp(void)
> +{
> +     hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
> +     if (!hyp_pgd)
> +             return -ENOMEM;
> +
> +     identity_mapping_add(hyp_pgd, __hyp_idmap_text_start,
> +                          __hyp_idmap_text_end, PMD_SECT_AP1);
> +
> +     return 0;
> +}
> +#else
> +static int __init init_static_idmap_hyp(void)
> +{
> +     return 0;
> +}
> +#endif
> +
>  extern char  __idmap_text_start[], __idmap_text_end[];
>  
>  static int __init init_static_idmap(void)
>  {
> -     phys_addr_t idmap_start, idmap_end;
> +     int ret;
>  
>       idmap_pgd = pgd_alloc(&init_mm);
>       if (!idmap_pgd)
>               return -ENOMEM;
>  
> -     /* Add an identity mapping for the physical address of the section. */
> -     idmap_start = virt_to_phys((void *)__idmap_text_start);
> -     idmap_end = virt_to_phys((void *)__idmap_text_end);
> +     identity_mapping_add(idmap_pgd, __idmap_text_start,
> +                          __idmap_text_end, 0);
>  
> -     pr_info("Setting up static identity map for 0x%llx - 0x%llx\n",
> -             (long long)idmap_start, (long long)idmap_end);
> -     identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
> +     ret = init_static_idmap_hyp();
>  
>       /* Flush L1 for the hardware to see this page table content */
>       flush_cache_louis();
>  
> -     return 0;
> +     return ret;
>  }
>  early_initcall(init_static_idmap);
>  
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
                        Gleb.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to