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 <will.deacon@xxxxxxx> > Reviewed-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx> > Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> > Signed-off-by: Christoffer Dall <c.dall@xxxxxxxxxxxxxxxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html