Fixes: 63b2bc619565 ("powerpc/mm/32s: Use BATs for STRICT_KERNEL_RWX") Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr> --- arch/powerpc/kernel/machine_kexec_32.c | 8 ++++++++ arch/powerpc/mm/book3s32/mmu.c | 7 +++++-- arch/powerpc/mm/mmu_decl.h | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c index affe5dcce7f4..83e61a8f8468 100644 --- a/arch/powerpc/kernel/machine_kexec_32.c +++ b/arch/powerpc/kernel/machine_kexec_32.c @@ -15,6 +15,7 @@ #include <asm/cacheflush.h> #include <asm/hw_irq.h> #include <asm/io.h> +#include <mm/mmu_decl.h> typedef void (*relocate_new_kernel_t)( unsigned long indirection_page, @@ -35,6 +36,8 @@ void default_machine_kexec(struct kimage *image) unsigned long page_list; unsigned long reboot_code_buffer, reboot_code_buffer_phys; relocate_new_kernel_t rnk; + unsigned long bat_size = 128 << 10; + unsigned long bat_mask = ~(bat_size - 1); /* Interrupts aren't acceptable while we reboot */ local_irq_disable(); @@ -54,6 +57,11 @@ void default_machine_kexec(struct kimage *image) memcpy((void *)reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size); + printk(KERN_INFO "Reboot code buffer at %lx\n", reboot_code_buffer); + mtsrin(mfsrin(reboot_code_buffer) & ~SR_NX, reboot_code_buffer); + setibat(7, reboot_code_buffer & bat_mask, reboot_code_buffer_phys & bat_mask, + bat_size, PAGE_KERNEL_TEXT); + flush_icache_range(reboot_code_buffer, reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); printk(KERN_INFO "Bye!\n"); diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c index fc073cb2c517..7124700edb0f 100644 --- a/arch/powerpc/mm/book3s32/mmu.c +++ b/arch/powerpc/mm/book3s32/mmu.c @@ -124,8 +124,8 @@ static unsigned int block_size(unsigned long base, unsigned long top) * of 2 between 128k and 256M. * Only for 603+ ... */ -static void setibat(int index, unsigned long virt, phys_addr_t phys, - unsigned int size, pgprot_t prot) +void setibat(int index, unsigned long virt, phys_addr_t phys, + unsigned int size, pgprot_t prot) { unsigned int bl = (size >> 17) - 1; int wimgxpp; @@ -197,6 +197,9 @@ void mmu_mark_initmem_nx(void) if (cpu_has_feature(CPU_FTR_601)) return; + if (IS_ENABLED(CONFIG_KEXEC)) + nb--; + for (i = 0; i < nb - 1 && base < top && top - base > (128 << 10);) { size = block_size(base, top); setibat(i++, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT); diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 7bac0aa2026a..478584d50cf2 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -103,6 +103,8 @@ void print_system_hash_info(void); extern void mapin_ram(void); extern void setbat(int index, unsigned long virt, phys_addr_t phys, unsigned int size, pgprot_t prot); +void setibat(int index, unsigned long virt, phys_addr_t phys, + unsigned int size, pgprot_t prot); extern int __map_without_bats; extern unsigned int rtas_data, rtas_size; -- 2.13.3