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

Reply via email to