Skip to content

Commit 9e9a367

Browse files
author
Christoffer Dall
committed
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: Will Deacon <will.deacon@arm.com> Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
1 parent cc577c2 commit 9e9a367

File tree

4 files changed

+51
-12
lines changed

4 files changed

+51
-12
lines changed

arch/arm/include/asm/idmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define __idmap __section(.idmap.text) noinline notrace
99

1010
extern pgd_t *idmap_pgd;
11+
extern pgd_t *hyp_pgd;
1112

1213
void setup_mm_for_reboot(void);
1314

arch/arm/include/asm/pgtable-3level-hwdef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#define PMD_SECT_XN (_AT(pmdval_t, 1) << 54)
4545
#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0))
4646
#define PMD_SECT_AP_READ (_AT(pmdval_t, 0))
47+
#define PMD_SECT_AP1 (_AT(pmdval_t, 1) << 6)
4748
#define PMD_SECT_TEX(x) (_AT(pmdval_t, 0))
4849

4950
/*

arch/arm/kernel/vmlinux.lds.S

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919
ALIGN_FUNCTION(); \
2020
VMLINUX_SYMBOL(__idmap_text_start) = .; \
2121
*(.idmap.text) \
22-
VMLINUX_SYMBOL(__idmap_text_end) = .;
22+
VMLINUX_SYMBOL(__idmap_text_end) = .; \
23+
ALIGN_FUNCTION(); \
24+
VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \
25+
*(.hyp.idmap.text) \
26+
VMLINUX_SYMBOL(__hyp_idmap_text_end) = .;
2327

2428
#ifdef CONFIG_HOTPLUG_CPU
2529
#define ARM_CPU_DISCARD(x)

arch/arm/mm/idmap.c

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
#include <linux/module.h>
12
#include <linux/kernel.h>
3+
#include <linux/slab.h>
24

35
#include <asm/cputype.h>
46
#include <asm/idmap.h>
57
#include <asm/pgalloc.h>
68
#include <asm/pgtable.h>
79
#include <asm/sections.h>
810
#include <asm/system_info.h>
11+
#include <asm/virt.h>
912

1013
pgd_t *idmap_pgd;
1114

@@ -59,11 +62,17 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
5962
} while (pud++, addr = next, addr != end);
6063
}
6164

62-
static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
65+
static void identity_mapping_add(pgd_t *pgd, const char *text_start,
66+
const char *text_end, unsigned long prot)
6367
{
64-
unsigned long prot, next;
68+
unsigned long addr, end;
69+
unsigned long next;
70+
71+
addr = virt_to_phys(text_start);
72+
end = virt_to_phys(text_end);
73+
74+
prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
6575

66-
prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
6776
if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
6877
prot |= PMD_BIT4;
6978

@@ -74,28 +83,52 @@ static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long e
7483
} while (pgd++, addr = next, addr != end);
7584
}
7685

86+
#if defined(CONFIG_ARM_VIRT_EXT) && defined(CONFIG_ARM_LPAE)
87+
pgd_t *hyp_pgd;
88+
89+
extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[];
90+
91+
static int __init init_static_idmap_hyp(void)
92+
{
93+
hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
94+
if (!hyp_pgd)
95+
return -ENOMEM;
96+
97+
pr_info("Setting up static HYP identity map for 0x%p - 0x%p\n",
98+
__hyp_idmap_text_start, __hyp_idmap_text_end);
99+
identity_mapping_add(hyp_pgd, __hyp_idmap_text_start,
100+
__hyp_idmap_text_end, PMD_SECT_AP1);
101+
102+
return 0;
103+
}
104+
#else
105+
static int __init init_static_idmap_hyp(void)
106+
{
107+
return 0;
108+
}
109+
#endif
110+
77111
extern char __idmap_text_start[], __idmap_text_end[];
78112

79113
static int __init init_static_idmap(void)
80114
{
81-
phys_addr_t idmap_start, idmap_end;
115+
int ret;
82116

83117
idmap_pgd = pgd_alloc(&init_mm);
84118
if (!idmap_pgd)
85119
return -ENOMEM;
86120

87-
/* Add an identity mapping for the physical address of the section. */
88-
idmap_start = virt_to_phys((void *)__idmap_text_start);
89-
idmap_end = virt_to_phys((void *)__idmap_text_end);
121+
pr_info("Setting up static identity map for 0x%p - 0x%p\n",
122+
__idmap_text_start, __idmap_text_end);
123+
identity_mapping_add(idmap_pgd, __idmap_text_start,
124+
__idmap_text_end, 0);
90125

91-
pr_info("Setting up static identity map for 0x%llx - 0x%llx\n",
92-
(long long)idmap_start, (long long)idmap_end);
93-
identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
126+
ret = init_static_idmap_hyp();
94127

95128
/* Flush L1 for the hardware to see this page table content */
96129
flush_cache_louis();
97130

98-
return 0;
131+
return ret;
99132
}
100133
early_initcall(init_static_idmap);
101134

0 commit comments

Comments
 (0)