FROMLIST: arm64: mm: Map entry trampoline into trampoline and kernel page tables
authorWill Deacon <will.deacon@arm.com>
Tue, 14 Nov 2017 14:14:17 +0000 (14:14 +0000)
committerGreg Kroah-Hartman <gregkh@google.com>
Sat, 6 Jan 2018 10:14:01 +0000 (11:14 +0100)
The exception entry trampoline needs to be mapped at the same virtual
address in both the trampoline page table (which maps nothing else)
and also the kernel page table, so that we can swizzle TTBR1_EL1 on
exceptions from and return to EL0.

This patch maps the trampoline at a fixed virtual address in the fixmap
area of the kernel virtual address space, which allows the kernel proper
to be randomized with respect to the trampoline when KASLR is enabled.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Laura Abbott <labbott@redhat.com>
Tested-by: Shanker Donthineni <shankerd@codeaurora.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
(cherry picked from git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
 commit 51a0048beb449682d632d0af52a515adb9f9882e)

Change-Id: I31b2dcdf4db36c3e31181fe43ccb984f9efb6ac6
[ghackmann@google.com:
 - adjust context
 - tweak __create_pgd_mapping() call to match 4.4 APIs]
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
arch/arm64/include/asm/fixmap.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/asm-offsets.c
arch/arm64/mm/mmu.c

index 1a617d46fce93247cf42fd0cda36a1355fc89aa9..8fa98f26129af1e342244604494336a2c62698df 100644 (file)
@@ -50,6 +50,10 @@ enum fixed_addresses {
 
        FIX_EARLYCON_MEM_BASE,
        FIX_TEXT_POKE0,
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+       FIX_ENTRY_TRAMP_TEXT,
+#define TRAMP_VALIAS           (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT))
+#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
        __end_of_permanent_fixed_addresses,
 
        /*
index def3ba0901ba69eae17f4169e6dbb0f2b8e4d37c..81eee57ad519c7e0445aa6c052320ccaa555f94d 100644 (file)
@@ -714,6 +714,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
+extern pgd_t tramp_pg_dir[PTRS_PER_PGD];
 
 /*
  * Encode and decode a swap entry:
index 3288c0cae9e6c2dbbe09cde6ca603b984da9ee4b..3fa949f04ce4fb455a3bcafa7caa91fd61838596 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/kvm_host.h>
+#include <asm/fixmap.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/smp_plat.h>
@@ -182,5 +183,9 @@ int main(void)
 #endif
   DEFINE(ARM_SMCCC_RES_X0_OFFS,        offsetof(struct arm_smccc_res, a0));
   DEFINE(ARM_SMCCC_RES_X2_OFFS,        offsetof(struct arm_smccc_res, a2));
+  BLANK();
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+  DEFINE(TRAMP_VALIAS,         TRAMP_VALIAS);
+#endif
   return 0;
 }
index e6409dc0cea9212ad22f2eaded638b6b3296e44d..a383ec16f1b738dc45ac9acd2af40f43f03b93b4 100644 (file)
@@ -494,6 +494,29 @@ static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end,
        vm_area_add_early(vma);
 }
 
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+static int __init map_entry_trampoline(void)
+{
+       extern char __entry_tramp_text_start[];
+
+       pgprot_t prot = PAGE_KERNEL_EXEC;
+       phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start);
+
+       /* The trampoline is always mapped and can therefore be global */
+       pgprot_val(prot) &= ~PTE_NG;
+
+       /* Map only the text into the trampoline page table */
+       memset(tramp_pg_dir, 0, PGD_SIZE);
+       __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
+                            prot, late_pgtable_alloc);
+
+       /* ...as well as the kernel page table */
+       __set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot);
+       return 0;
+}
+core_initcall(map_entry_trampoline);
+#endif
+
 /*
  * Create fine-grained mappings for the kernel.
  */