···11+#ifndef __ASM_IDMAP_H22+#define __ASM_IDMAP_H33+44+#include <linux/compiler.h>55+#include <asm/pgtable.h>66+77+/* Tag a function as requiring to be executed via an identity mapping. */88+#define __idmap __section(.idmap.text) noinline notrace99+1010+extern pgd_t *idmap_pgd;1111+1212+void setup_mm_for_reboot(void);1313+1414+#endif /* __ASM_IDMAP_H */
···11#include <linux/kernel.h>2233#include <asm/cputype.h>44+#include <asm/idmap.h>45#include <asm/pgalloc.h>56#include <asm/pgtable.h>77+#include <asm/sections.h>88+99+pgd_t *idmap_pgd;610711static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,812 unsigned long prot)···3228 } while (pud++, addr = next, addr != end);3329}34303535-void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)3131+static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)3632{3733 unsigned long prot, next;3834···4743 } while (pgd++, addr = next, addr != end);4844}49455050-#ifdef CONFIG_SMP5151-static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end)4646+extern char __idmap_text_start[], __idmap_text_end[];4747+4848+static int __init init_static_idmap(void)5249{5353- pmd_t *pmd = pmd_offset(pud, addr);5454- pmd_clear(pmd);5050+ phys_addr_t idmap_start, idmap_end;5151+5252+ idmap_pgd = pgd_alloc(&init_mm);5353+ if (!idmap_pgd)5454+ return -ENOMEM;5555+5656+ /* Add an identity mapping for the physical address of the section. */5757+ idmap_start = virt_to_phys((void *)__idmap_text_start);5858+ idmap_end = virt_to_phys((void *)__idmap_text_end);5959+6060+ pr_info("Setting up static identity map for 0x%llx - 0x%llx\n",6161+ (long long)idmap_start, (long long)idmap_end);6262+ identity_mapping_add(idmap_pgd, idmap_start, idmap_end);6363+6464+ return 0;5565}5656-5757-static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end)5858-{5959- pud_t *pud = pud_offset(pgd, addr);6060- unsigned long next;6161-6262- do {6363- next = pud_addr_end(addr, end);6464- idmap_del_pmd(pud, addr, next);6565- } while (pud++, addr = next, addr != end);6666-}6767-6868-void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)6969-{7070- unsigned long next;7171-7272- pgd += pgd_index(addr);7373- do {7474- next = pgd_addr_end(addr, end);7575- idmap_del_pud(pgd, addr, next);7676- } while (pgd++, addr = next, addr != end);7777-}7878-#endif6666+early_initcall(init_static_idmap);79678068/*8181- * In order to soft-boot, we need to insert a 1:1 mapping in place of8282- * the user-mode pages. This will then ensure that we have predictable8383- * results when turning the mmu off6969+ * In order to soft-boot, we need to switch to a 1:1 mapping for the7070+ * cpu_reset functions. This will then ensure that we have predictable7171+ * results when turning off the mmu.8472 */8573void setup_mm_for_reboot(void)8674{8787- /*8888- * We need to access to user-mode page tables here. For kernel threads8989- * we don't have any user-mode mappings so we use the context that we9090- * "borrowed".9191- */9292- identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE);7575+ /* Clean and invalidate L1. */7676+ flush_cache_all();7777+7878+ /* Switch to the identity mapping. */7979+ cpu_switch_mm(idmap_pgd, &init_mm);8080+8181+ /* Flush the TLB. */9382 local_flush_tlb_all();9483}
···4545 * Params : loc(r0) address to jump to4646 * Purpose : Sets up everything for a reset and jump to the location for soft reset.4747 */4848+ .pushsection .idmap.text, "ax"4849ENTRY(cpu_arm7tdmi_reset)4950 mov pc, r05151+ENDPROC(cpu_arm7tdmi_reset)5252+ .popsection50535154 __CPUINIT5255
···4848 * Params : r0 = address to jump to4949 * Notes : This sets up everything for a reset5050 */5151+ .pushsection .idmap.text, "ax"5152ENTRY(cpu_arm940_reset)5253 mov ip, #05354 mcr p15, 0, ip, c7, c5, 0 @ flush I cache···5958 bic ip, ip, #0x00001000 @ i-cache6059 mcr p15, 0, ip, c1, c0, 0 @ ctrl register6160 mov pc, r06161+ENDPROC(cpu_arm940_reset)6262+ .popsection62636364/*6465 * cpu_arm940_do_idle()
+3
arch/arm/mm/proc-arm946.S
···5555 * Params : r0 = address to jump to5656 * Notes : This sets up everything for a reset5757 */5858+ .pushsection .idmap.text, "ax"5859ENTRY(cpu_arm946_reset)5960 mov ip, #06061 mcr p15, 0, ip, c7, c5, 0 @ flush I cache···6665 bic ip, ip, #0x00001000 @ i-cache6766 mcr p15, 0, ip, c1, c0, 0 @ ctrl register6867 mov pc, r06868+ENDPROC(cpu_arm946_reset)6969+ .popsection69707071/*7172 * cpu_arm946_do_idle()
+3
arch/arm/mm/proc-arm9tdmi.S
···4545 * Params : loc(r0) address to jump to4646 * Purpose : Sets up everything for a reset and jump to the location for soft reset.4747 */4848+ .pushsection .idmap.text, "ax"4849ENTRY(cpu_arm9tdmi_reset)4950 mov pc, r05151+ENDPROC(cpu_arm9tdmi_reset)5252+ .popsection50535154 __CPUINIT5255
+3
arch/arm/mm/proc-fa526.S
···5757 * loc: location to jump to for soft reset5858 */5959 .align 46060+ .pushsection .idmap.text, "ax"6061ENTRY(cpu_fa526_reset)6162/* TODO: Use CP8 if possible... */6263 mov ip, #0···7473 nop7574 nop7675 mov pc, r07676+ENDPROC(cpu_fa526_reset)7777+ .popsection77787879/*7980 * cpu_fa526_do_idle()