Commit 9e9a367c authored by Christoffer Dall's avatar Christoffer Dall

ARM: Section based HYP idmap

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.
Reviewed-by: default avatarWill Deacon <will.deacon@arm.com>
Reviewed-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarChristoffer Dall <c.dall@virtualopensystems.com>
parent cc577c26
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define __idmap __section(.idmap.text) noinline notrace #define __idmap __section(.idmap.text) noinline notrace
extern pgd_t *idmap_pgd; extern pgd_t *idmap_pgd;
extern pgd_t *hyp_pgd;
void setup_mm_for_reboot(void); void setup_mm_for_reboot(void);
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) #define PMD_SECT_XN (_AT(pmdval_t, 1) << 54)
#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0)) #define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0))
#define PMD_SECT_AP_READ (_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)) #define PMD_SECT_TEX(x) (_AT(pmdval_t, 0))
/* /*
......
...@@ -19,7 +19,11 @@ ...@@ -19,7 +19,11 @@
ALIGN_FUNCTION(); \ ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__idmap_text_start) = .; \ VMLINUX_SYMBOL(__idmap_text_start) = .; \
*(.idmap.text) \ *(.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 #ifdef CONFIG_HOTPLUG_CPU
#define ARM_CPU_DISCARD(x) #define ARM_CPU_DISCARD(x)
......
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h>
#include <asm/cputype.h> #include <asm/cputype.h>
#include <asm/idmap.h> #include <asm/idmap.h>
...@@ -6,6 +8,7 @@ ...@@ -6,6 +8,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/system_info.h> #include <asm/system_info.h>
#include <asm/virt.h>
pgd_t *idmap_pgd; pgd_t *idmap_pgd;
...@@ -59,11 +62,17 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, ...@@ -59,11 +62,17 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
} while (pud++, addr = next, addr != 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);
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()) if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
prot |= PMD_BIT4; prot |= PMD_BIT4;
...@@ -74,28 +83,52 @@ static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long e ...@@ -74,28 +83,52 @@ static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long e
} while (pgd++, addr = next, addr != end); } while (pgd++, addr = next, addr != end);
} }
#if defined(CONFIG_ARM_VIRT_EXT) && defined(CONFIG_ARM_LPAE)
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;
pr_info("Setting up static HYP identity map for 0x%p - 0x%p\n",
__hyp_idmap_text_start, __hyp_idmap_text_end);
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[]; extern char __idmap_text_start[], __idmap_text_end[];
static int __init init_static_idmap(void) static int __init init_static_idmap(void)
{ {
phys_addr_t idmap_start, idmap_end; int ret;
idmap_pgd = pgd_alloc(&init_mm); idmap_pgd = pgd_alloc(&init_mm);
if (!idmap_pgd) if (!idmap_pgd)
return -ENOMEM; return -ENOMEM;
/* Add an identity mapping for the physical address of the section. */ pr_info("Setting up static identity map for 0x%p - 0x%p\n",
idmap_start = virt_to_phys((void *)__idmap_text_start); __idmap_text_start, __idmap_text_end);
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", ret = init_static_idmap_hyp();
(long long)idmap_start, (long long)idmap_end);
identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
/* Flush L1 for the hardware to see this page table content */ /* Flush L1 for the hardware to see this page table content */
flush_cache_louis(); flush_cache_louis();
return 0; return ret;
} }
early_initcall(init_static_idmap); early_initcall(init_static_idmap);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment