ARM: provide improved virt_to_idmap() functionality
authorRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 15 Mar 2016 14:55:03 +0000 (14:55 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 3 May 2016 10:13:54 +0000 (11:13 +0100)
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>
arch/arm/include/asm/memory.h
arch/arm/mach-keystone/keystone.c
arch/arm/mm/idmap.c

index 9427fd6325527e95ff9e5ad0a3f2bd973481e22a..ca208335fde60f5743d3f3affc20c385d1770a27 100644 (file)
@@ -288,19 +288,38 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define __va(x)                        ((void *)__phys_to_virt((phys_addr_t)(x)))
 #define pfn_to_kaddr(pfn)      __va((phys_addr_t)(pfn) << PAGE_SHIFT)
 
-extern unsigned long (*arch_virt_to_idmap)(unsigned long x);
+extern long long arch_phys_to_idmap_offset;
 
 /*
- * These are for systems that have a hardware interconnect supported alias of
- * physical memory for idmap purposes.  Most cases should leave these
+ * These are for systems that have a hardware interconnect supported alias
+ * of physical memory for idmap purposes.  Most cases should leave these
  * untouched.  Note: this can only return addresses less than 4GiB.
  */
+#define IDMAP_INVALID_ADDR ((u32)~0)
+
+static inline unsigned long phys_to_idmap(phys_addr_t addr)
+{
+       if (IS_ENABLED(CONFIG_MMU) && arch_phys_to_idmap_offset) {
+               addr += arch_phys_to_idmap_offset;
+               if (addr > (u32)~0)
+                       addr = IDMAP_INVALID_ADDR;
+       }
+       return addr;
+}
+
+static inline phys_addr_t idmap_to_phys(unsigned long idmap)
+{
+       phys_addr_t addr = idmap;
+
+       if (IS_ENABLED(CONFIG_MMU) && arch_phys_to_idmap_offset)
+               addr -= arch_phys_to_idmap_offset;
+
+       return addr;
+}
+
 static inline unsigned long __virt_to_idmap(unsigned long x)
 {
-       if (IS_ENABLED(CONFIG_MMU) && arch_virt_to_idmap)
-               return arch_virt_to_idmap(x);
-       else
-               return __virt_to_phys(x);
+       return phys_to_idmap(__virt_to_phys(x));
 }
 
 #define virt_to_idmap(x)       __virt_to_idmap((unsigned long)(x))
index e6b9cb1e6709753b6e25166d8b9cac395d9a2c42..a33a296b00dce8f1f65331fa6dad71745f116d9c 100644 (file)
@@ -63,11 +63,6 @@ static void __init keystone_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static unsigned long keystone_virt_to_idmap(unsigned long x)
-{
-       return (phys_addr_t)(x) - CONFIG_PAGE_OFFSET + KEYSTONE_LOW_PHYS_START;
-}
-
 static long long __init keystone_pv_fixup(void)
 {
        long long offset;
@@ -91,7 +86,7 @@ static long long __init keystone_pv_fixup(void)
        offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START;
 
        /* Populate the arch idmap hook */
-       arch_virt_to_idmap = keystone_virt_to_idmap;
+       arch_phys_to_idmap_offset = -offset;
 
        return offset;
 }
index bd274a05b8ffa9446160d1de69f777d9431c629b..c1a48f88764ea8da4ec3b0abd9dcd197678841ea 100644 (file)
@@ -15,7 +15,7 @@
  * page tables.
  */
 pgd_t *idmap_pgd;
-unsigned long (*arch_virt_to_idmap)(unsigned long x);
+long long arch_phys_to_idmap_offset;
 
 #ifdef CONFIG_ARM_LPAE
 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
This page took 0.033572 seconds and 5 git commands to generate.