From: Michael Gernoth Date: Sun, 22 May 2011 19:55:03 +0000 (+0200) Subject: use setup_mm_for_reboot from current kernels, no need for init_mm X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/ms2-kexec/commitdiff_plain/c4f2433ea405da1feeee7e15c64c8452eda8cd39?ds=inline use setup_mm_for_reboot from current kernels, no need for init_mm --- diff --git a/Makefile b/Makefile index adf1b83..61a5644 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ CROSS_PATH=$(PWD)/../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin EXTRA_CFLAGS += -DCONFIG_KEXEC -Wall obj-m += kexec_load.o -kexec_load-objs := kexec.o machine_kexec.o mmu.o sys.o core.o relocate_kernel.o \ +kexec_load-objs := kexec.o machine_kexec.o idmap.o sys.o core.o relocate_kernel.o \ proc-v7.o tlb-v7.o cache-v7.o abort-ev7.o pabort-v7.o copypage-v6.o entry-common.o driver_sys.o all: diff --git a/idmap.c b/idmap.c new file mode 100644 index 0000000..e667f74 --- /dev/null +++ b/idmap.c @@ -0,0 +1,92 @@ +#include + +#include +#include +#include + +static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, + unsigned long prot) +{ + pmd_t *pmd = pmd_offset(pud, addr); + + addr = (addr & PMD_MASK) | prot; + pmd[0] = __pmd(addr); + addr += SECTION_SIZE; + pmd[1] = __pmd(addr); + flush_pmd_entry(pmd); +} + +static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, + unsigned long prot) +{ + pud_t *pud = pud_offset(pgd, addr); + unsigned long next; + + do { + next = pud_addr_end(addr, end); + idmap_add_pmd(pud, addr, next, prot); + } while (pud++, addr = next, addr != end); +} + +void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) +{ + unsigned long prot, next; + + prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; +#if 0 + if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) + prot |= PMD_BIT4; +#endif + + pgd += pgd_index(addr); + do { + next = pgd_addr_end(addr, end); + idmap_add_pud(pgd, addr, next, prot); + } while (pgd++, addr = next, addr != end); +} + +#ifdef CONFIG_SMP +static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end) +{ + pmd_t *pmd = pmd_offset(pud, addr); + pmd_clear(pmd); +} + +static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end) +{ + pud_t *pud = pud_offset(pgd, addr); + unsigned long next; + + do { + next = pud_addr_end(addr, end); + idmap_del_pmd(pud, addr, next); + } while (pud++, addr = next, addr != end); +} + +void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) +{ + unsigned long next; + + pgd += pgd_index(addr); + do { + next = pgd_addr_end(addr, end); + idmap_del_pud(pgd, addr, next); + } while (pgd++, addr = next, addr != end); +} +#endif + +/* + * In order to soft-boot, we need to insert a 1:1 mapping in place of + * the user-mode pages. This will then ensure that we have predictable + * results when turning the mmu off + */ +void setup_mm_for_reboot(char mode) +{ + /* + * We need to access to user-mode page tables here. For kernel threads + * we don't have any user-mode mappings so we use the context that we + * "borrowed". + */ + identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE); + local_flush_tlb_all(); +}