aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2016-03-15 10:55:03 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2016-05-03 06:13:54 -0400
commit981b6714dbd26609212536b9fed43e49db1459cf (patch)
treed1929db350c1ad747a5ff2ade1bc7b01c4fd39a2
parent61603016e2122bf95328321b2f1a64277202b6e3 (diff)
ARM: provide improved virt_to_idmap() functionality
For kexec, we need more functionality from the IDMAP system. We need to be able to convert physical addresses to their identity mappped versions as well as virtual addresses. Convert the existing arch_virt_to_idmap() to deal with physical addresses instead. Acked-by: Santosh Shilimkar <ssantosh@kernel.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/memory.h33
-rw-r--r--arch/arm/mach-keystone/keystone.c7
-rw-r--r--arch/arm/mm/idmap.c2
3 files changed, 28 insertions, 14 deletions
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 9427fd632552..ca208335fde6 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -288,19 +288,38 @@ static inline void *phys_to_virt(phys_addr_t x)
288#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) 288#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
289#define pfn_to_kaddr(pfn) __va((phys_addr_t)(pfn) << PAGE_SHIFT) 289#define pfn_to_kaddr(pfn) __va((phys_addr_t)(pfn) << PAGE_SHIFT)
290 290
291extern unsigned long (*arch_virt_to_idmap)(unsigned long x); 291extern long long arch_phys_to_idmap_offset;
292 292
293/* 293/*
294 * These are for systems that have a hardware interconnect supported alias of 294 * These are for systems that have a hardware interconnect supported alias
295 * physical memory for idmap purposes. Most cases should leave these 295 * of physical memory for idmap purposes. Most cases should leave these
296 * untouched. Note: this can only return addresses less than 4GiB. 296 * untouched. Note: this can only return addresses less than 4GiB.
297 */ 297 */
298#define IDMAP_INVALID_ADDR ((u32)~0)
299
300static inline unsigned long phys_to_idmap(phys_addr_t addr)
301{
302 if (IS_ENABLED(CONFIG_MMU) && arch_phys_to_idmap_offset) {
303 addr += arch_phys_to_idmap_offset;
304 if (addr > (u32)~0)
305 addr = IDMAP_INVALID_ADDR;
306 }
307 return addr;
308}
309
310static inline phys_addr_t idmap_to_phys(unsigned long idmap)
311{
312 phys_addr_t addr = idmap;
313
314 if (IS_ENABLED(CONFIG_MMU) && arch_phys_to_idmap_offset)
315 addr -= arch_phys_to_idmap_offset;
316
317 return addr;
318}
319
298static inline unsigned long __virt_to_idmap(unsigned long x) 320static inline unsigned long __virt_to_idmap(unsigned long x)
299{ 321{
300 if (IS_ENABLED(CONFIG_MMU) && arch_virt_to_idmap) 322 return phys_to_idmap(__virt_to_phys(x));
301 return arch_virt_to_idmap(x);
302 else
303 return __virt_to_phys(x);
304} 323}
305 324
306#define virt_to_idmap(x) __virt_to_idmap((unsigned long)(x)) 325#define virt_to_idmap(x) __virt_to_idmap((unsigned long)(x))
diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
index e6b9cb1e6709..a33a296b00dc 100644
--- a/arch/arm/mach-keystone/keystone.c
+++ b/arch/arm/mach-keystone/keystone.c
@@ -63,11 +63,6 @@ static void __init keystone_init(void)
63 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 63 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
64} 64}
65 65
66static unsigned long keystone_virt_to_idmap(unsigned long x)
67{
68 return (phys_addr_t)(x) - CONFIG_PAGE_OFFSET + KEYSTONE_LOW_PHYS_START;
69}
70
71static long long __init keystone_pv_fixup(void) 66static long long __init keystone_pv_fixup(void)
72{ 67{
73 long long offset; 68 long long offset;
@@ -91,7 +86,7 @@ static long long __init keystone_pv_fixup(void)
91 offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START; 86 offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START;
92 87
93 /* Populate the arch idmap hook */ 88 /* Populate the arch idmap hook */
94 arch_virt_to_idmap = keystone_virt_to_idmap; 89 arch_phys_to_idmap_offset = -offset;
95 90
96 return offset; 91 return offset;
97} 92}
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index bd274a05b8ff..c1a48f88764e 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -15,7 +15,7 @@
15 * page tables. 15 * page tables.
16 */ 16 */
17pgd_t *idmap_pgd; 17pgd_t *idmap_pgd;
18unsigned long (*arch_virt_to_idmap)(unsigned long x); 18long long arch_phys_to_idmap_offset;
19 19
20#ifdef CONFIG_ARM_LPAE 20#ifdef CONFIG_ARM_LPAE
21static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, 21static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,