2018-11-29 19:02:34

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 00/13] powerpc/32s: Use BATs for STRICT_KERNEL_RWX

The purpose of this serie is to use BATs with STRICT_KERNEL_RWX
See patch 12 for details.

Christophe Leroy (13):
powerpc/mm: add exec protection on powerpc 603
powerpc/mm/32: add base address to mmu_mapin_ram()
powerpc/mm/32s: rework mmu_mapin_ram()
powerpc/mm/32s: use generic mmu_mapin_ram() for all blocks.
powerpc/wii: remove wii_mmu_mapin_mem2()
powerpc/mm/32s: use _PAGE_EXEC in setbat()
powerpc/mm/32s: add setibat() clearibat() and update_bats()
powerpc/32: add helper to write into segment registers
powerpc/mmu: add is_strict_kernel_rwx() helper
powerpc/kconfig: define PAGE_SHIFT inside Kconfig
powerpc/kconfig: define CONFIG_DATA_SHIFT and CONFIG_ETEXT_SHIFT
powerpc/mm/32s: Use BATs for STRICT_KERNEL_RWX
powerpc/kconfig: make _etext and data areas alignment configurable on
Book3s 32

arch/powerpc/Kconfig | 46 +++++++
arch/powerpc/include/asm/book3s/32/hash.h | 1 +
arch/powerpc/include/asm/book3s/32/mmu-hash.h | 2 +
arch/powerpc/include/asm/book3s/32/pgtable.h | 29 ++--
arch/powerpc/include/asm/cputable.h | 8 +-
arch/powerpc/include/asm/mmu.h | 11 ++
arch/powerpc/include/asm/page.h | 13 +-
arch/powerpc/include/asm/reg.h | 5 +
arch/powerpc/kernel/head_32.S | 37 ++++-
arch/powerpc/kernel/vmlinux.lds.S | 9 +-
arch/powerpc/mm/40x_mmu.c | 2 +-
arch/powerpc/mm/44x_mmu.c | 2 +-
arch/powerpc/mm/8xx_mmu.c | 2 +-
arch/powerpc/mm/dump_linuxpagetables-generic.c | 2 -
arch/powerpc/mm/fsl_booke_mmu.c | 2 +-
arch/powerpc/mm/init_32.c | 6 +-
arch/powerpc/mm/mmu_decl.h | 10 +-
arch/powerpc/mm/pgtable.c | 20 +--
arch/powerpc/mm/pgtable_32.c | 35 +++--
arch/powerpc/mm/ppc_mmu_32.c | 178 +++++++++++++++++++++----
arch/powerpc/platforms/embedded6xx/wii.c | 24 ----
21 files changed, 324 insertions(+), 120 deletions(-)

--
2.13.3



2018-11-29 19:01:36

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

This patch reworks mmu_mapin_ram() to be more generic and map as much
blocks as possible. It now supports blocks not starting at address 0.

It scans DBATs array to find free ones instead of forcing the use of
BAT2 and BAT3.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/mm/ppc_mmu_32.c | 61 +++++++++++++++++++++++++++++---------------
1 file changed, 40 insertions(+), 21 deletions(-)

diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 3a29e88308b0..61c10ee00ba2 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -72,39 +72,58 @@ unsigned long p_block_mapped(phys_addr_t pa)
return 0;
}

+static int find_free_bat(void)
+{
+ int b;
+
+ if (cpu_has_feature(CPU_FTR_601)) {
+ for (b = 0; b < 4; b++) {
+ struct ppc_bat *bat = BATS[b];
+
+ if (!(bat[0].batl & 0x40))
+ return b;
+ }
+ } else {
+ int n = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
+
+ for (b = 0; b < n; b++) {
+ struct ppc_bat *bat = BATS[b];
+
+ if (!(bat[1].batu & 3))
+ return b;
+ }
+ }
+ return -1;
+}
+
+static unsigned int block_size(unsigned long base, unsigned long top)
+{
+ unsigned int max_size = (cpu_has_feature(CPU_FTR_601) ? 8 : 256) << 20;
+ unsigned int base_shift = (fls(base) - 1) & 31;
+ unsigned int block_shift = (fls(top - base) - 1) & 31;
+
+ return min3(max_size, 1U << base_shift, 1U << block_shift);
+}
+
unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
- unsigned long tot, bl, done;
- unsigned long max_size = (256<<20);
+ int idx;

if (__map_without_bats) {
printk(KERN_DEBUG "RAM mapped without BATs\n");
return 0;
}

- /* Set up BAT2 and if necessary BAT3 to cover RAM. */
+ while ((idx = find_free_bat()) != -1 && base != top) {
+ unsigned int size = block_size(base, top);

- /* Make sure we don't map a block larger than the
- smallest alignment of the physical address. */
- tot = top;
- for (bl = 128<<10; bl < max_size; bl <<= 1) {
- if (bl * 2 > tot)
+ if (size < 128 << 10)
break;
+ setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
+ base += size;
}

- setbat(2, PAGE_OFFSET, 0, bl, PAGE_KERNEL_X);
- done = (unsigned long)bat_addrs[2].limit - PAGE_OFFSET + 1;
- if ((done < tot) && !bat_addrs[3].limit) {
- /* use BAT3 to cover a bit more */
- tot -= done;
- for (bl = 128<<10; bl < max_size; bl <<= 1)
- if (bl * 2 > tot)
- break;
- setbat(3, PAGE_OFFSET+done, done, bl, PAGE_KERNEL_X);
- done = (unsigned long)bat_addrs[3].limit - PAGE_OFFSET + 1;
- }
-
- return done;
+ return base;
}

/*
--
2.13.3


2018-11-29 19:01:45

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 05/13] powerpc/wii: remove wii_mmu_mapin_mem2()

wii_mmu_mapin_mem2() is not used anymore, remove it.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/platforms/embedded6xx/wii.c | 24 ------------------------
1 file changed, 24 deletions(-)

diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index ecf703ee3a76..235fe81aa2b1 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -54,10 +54,6 @@
static void __iomem *hw_ctrl;
static void __iomem *hw_gpio;

-unsigned long wii_hole_start;
-unsigned long wii_hole_size;
-
-
static int __init page_aligned(unsigned long x)
{
return !(x & (PAGE_SIZE-1));
@@ -69,26 +65,6 @@ void __init wii_memory_fixups(void)

BUG_ON(memblock.memory.cnt != 2);
BUG_ON(!page_aligned(p[0].base) || !page_aligned(p[1].base));
-
- /* determine hole */
- wii_hole_start = ALIGN(p[0].base + p[0].size, PAGE_SIZE);
- wii_hole_size = p[1].base - wii_hole_start;
-}
-
-unsigned long __init wii_mmu_mapin_mem2(unsigned long top)
-{
- unsigned long delta, size, bl;
- unsigned long max_size = (256<<20);
-
- /* MEM2 64MB@0x10000000 */
- delta = wii_hole_start + wii_hole_size;
- size = top - delta;
- for (bl = 128<<10; bl < max_size; bl <<= 1) {
- if (bl * 2 > size)
- break;
- }
- setbat(4, PAGE_OFFSET+delta, delta, bl, PAGE_KERNEL_X);
- return delta + bl;
}

static void __noreturn wii_spin(void)
--
2.13.3


2018-11-29 19:01:52

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 06/13] powerpc/mm/32s: use _PAGE_EXEC in setbat()

Do not set IBAT when setbat() is called without _PAGE_EXEC

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/mm/ppc_mmu_32.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 61c10ee00ba2..1078095d9407 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -130,6 +130,7 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
* Set up one of the I/D BAT (block address translation) register pairs.
* The parameters are not checked; in particular size must be a power
* of 2 between 128k and 256M.
+ * On 603+, only set IBAT when _PAGE_EXEC is set
*/
void __init setbat(int index, unsigned long virt, phys_addr_t phys,
unsigned int size, pgprot_t prot)
@@ -156,11 +157,12 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys,
bat[1].batu |= 1; /* Vp = 1 */
if (flags & _PAGE_GUARDED) {
/* G bit must be zero in IBATs */
- bat[0].batu = bat[0].batl = 0;
- } else {
- /* make IBAT same as DBAT */
- bat[0] = bat[1];
+ flags &= ~_PAGE_EXEC;
}
+ if (flags & _PAGE_EXEC)
+ bat[0] = bat[1];
+ else
+ bat[0].batu = bat[0].batl = 0;
} else {
/* 601 cpu */
if (bl > BL_8M)
--
2.13.3


2018-11-29 19:01:58

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 04/13] powerpc/mm/32s: use generic mmu_mapin_ram() for all blocks.

Now that mmu_mapin_ram() is able to handle other blocks
than the one starting at 0, the WII can use it for all
its blocks.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/mm/pgtable_32.c | 25 +++++++------------------
1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index c030f24d1d05..68a5e2be5343 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -271,26 +271,15 @@ static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top)

void __init mapin_ram(void)
{
- unsigned long s, top;
-
-#ifndef CONFIG_WII
- top = total_lowmem;
- s = mmu_mapin_ram(0, top);
- __mapin_ram_chunk(s, top);
-#else
- if (!wii_hole_size) {
- s = mmu_mapin_ram(0, total_lowmem);
- __mapin_ram_chunk(s, total_lowmem);
- } else {
- top = wii_hole_start;
- s = mmu_mapin_ram(0, top);
- __mapin_ram_chunk(s, top);
+ struct memblock_region *reg;
+
+ for_each_memblock(memory, reg) {
+ unsigned long base = reg->base;
+ unsigned long top = base + reg->size;

- top = memblock_end_of_DRAM();
- s = wii_mmu_mapin_mem2(top);
- __mapin_ram_chunk(s, top);
+ base = mmu_mapin_ram(base, top);
+ __mapin_ram_chunk(base, top);
}
-#endif
}

/* Scan the real Linux page tables and return a PTE pointer for
--
2.13.3


2018-11-29 19:01:59

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 13/13] powerpc/kconfig: make _etext and data areas alignment configurable on Book3s 32

Depending on the number of available BATs for mapping the different
kernel areas, it might be needed to increase the alignment of _etext
and/or of data areas.

This patchs allows the user to do it via Kconfig.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/Kconfig | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ffcf4d7a1186..bab9dab815d9 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -728,16 +728,44 @@ config THREAD_SHIFT
Used to define the stack size. The default is almost always what you
want. Only change this if you know what you are doing.

+config ETEXT_SHIFT_BOOL
+ bool "Set custom etext alignment" if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the kernel end of text alignment. When
+ RAM is mapped by blocks, the alignment needs to fit the size and
+ number of possible blocks. The default should be OK for most configs.
+
+ Say N here unless you know what you are doing.
+
config ETEXT_SHIFT
- int
+ int "_etext shift" if ETEXT_SHIFT_BOOL
+ range 17 28 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default 17 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default PPC_PAGE_SHIFT
+ help
+ On Book3S 32 (603+), IBATs are used to map kernel text.
+ Smaller is the alignment, greater is the number of necessary IBATs.
+
+config DATA_SHIFT_BOOL
+ bool "Set custom data alignment" if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the kernel data alignment. When
+ RAM is mapped by blocks, the alignment needs to fit the size and
+ number of possible blocks. The default should be OK for most configs.
+
+ Say N here unless you know what you are doing.

config DATA_SHIFT
- int
+ int "Data shift" if DATA_SHIFT_BOOL
default 24 if STRICT_KERNEL_RWX && PPC64
+ range 17 28 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default PPC_PAGE_SHIFT
+ help
+ On Book3S 32 (603+), DBATs are used to map kernel text and rodata RO.
+ Smaller is the alignment, greater is the number of necessary DBATs.

config FORCE_MAX_ZONEORDER
int "Maximum zone order"
--
2.13.3


2018-11-29 19:02:06

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 12/13] powerpc/mm/32s: Use BATs for STRICT_KERNEL_RWX

Today, STRICT_KERNEL_RWX is based on the use of regular pages
to map kernel pages.

On Book3s 32, it has three consequences:
- Using pages instead of BAT for mapping kernel linear memory severely
impacts performance.
- Exec protection is not effective because no-execute cannot be set at
page level (except on 603 which doesn't have hash tables)
- Write protection is not effective because PP bits do not provide RO
mode for kernel-only pages (except on 603 which handles it in software
via PAGE_DIRTY)

On the 603+, we have:
- Independent IBAT and DBAT allowing limitation of exec parts.
- NX bit can be set in segment registers to forbit execution on memory
mapped by pages.
- RO mode on DBATs even for kernel-only blocks.

On the 601, there is nothing much we can do other than warn the user
about it, because:
- BATs are common to instructions and data.
- BAT do not provide RO mode for kernel-only blocks.
- segment registers don't have the NX bit.

In order to use IBAT for exec protection, this patch:
- Aligns _etext to BAT block sizes (128kb)
- Set NX bit in kernel segment register (Except on vmalloc area when
CONFIG_MODULES is selected)
- Maps kernel text with IBATs.

In order to use DBAT for exec protection, this patch:
- Aligns RW DATA to BAT block sizes (4M)
- Maps kernel RO area with write prohibited DBATs
- Maps remaining memory with remaining DBATs

Here is what we get with this patch on a 832x when activating
STRICT_KERNEL_RWX:

Symbols:
c0000000 T _stext
c0680000 R __start_rodata
c0680000 R _etext
c0800000 T __init_begin
c0800000 T _sinittext

~# cat /sys/kernel/debug/block_address_translation
---[ Instruction Block Address Translation ]---
0: 0xc0000000-0xc03fffff 0x00000000 Kernel EXEC coherent
1: 0xc0400000-0xc05fffff 0x00400000 Kernel EXEC coherent
2: 0xc0600000-0xc067ffff 0x00600000 Kernel EXEC coherent
3: -
4: -
5: -
6: -
7: -

---[ Data Block Address Translation ]---
0: 0xc0000000-0xc07fffff 0x00000000 Kernel RO coherent
1: 0xc0800000-0xc0ffffff 0x00800000 Kernel RW coherent
2: 0xc1000000-0xc1ffffff 0x01000000 Kernel RW coherent
3: 0xc2000000-0xc3ffffff 0x02000000 Kernel RW coherent
4: 0xc4000000-0xc7ffffff 0x04000000 Kernel RW coherent
5: 0xc8000000-0xcfffffff 0x08000000 Kernel RW coherent
6: 0xd0000000-0xdfffffff 0x10000000 Kernel RW coherent
7: -

~# cat /sys/kernel/debug/segment_registers
---[ User Segments ]---
0x00000000-0x0fffffff Kern key 1 User key 1 VSID 0xa085d0
0x10000000-0x1fffffff Kern key 1 User key 1 VSID 0xa086e1
0x20000000-0x2fffffff Kern key 1 User key 1 VSID 0xa087f2
0x30000000-0x3fffffff Kern key 1 User key 1 VSID 0xa08903
0x40000000-0x4fffffff Kern key 1 User key 1 VSID 0xa08a14
0x50000000-0x5fffffff Kern key 1 User key 1 VSID 0xa08b25
0x60000000-0x6fffffff Kern key 1 User key 1 VSID 0xa08c36
0x70000000-0x7fffffff Kern key 1 User key 1 VSID 0xa08d47
0x80000000-0x8fffffff Kern key 1 User key 1 VSID 0xa08e58
0x90000000-0x9fffffff Kern key 1 User key 1 VSID 0xa08f69
0xa0000000-0xafffffff Kern key 1 User key 1 VSID 0xa0907a
0xb0000000-0xbfffffff Kern key 1 User key 1 VSID 0xa0918b

---[ Kernel Segments ]---
0xc0000000-0xcfffffff Kern key 0 User key 1 No Exec VSID 0x000ccc
0xd0000000-0xdfffffff Kern key 0 User key 1 No Exec VSID 0x000ddd
0xe0000000-0xefffffff Kern key 0 User key 1 No Exec VSID 0x000eee
0xf0000000-0xffffffff Kern key 0 User key 1 No Exec VSID 0x000fff

Aligning _etext to 128kb allows to map up to 32Mb text with 8 IBATs:
16Mb + 8Mb + 4Mb + 2Mb + 1Mb + 512kb + 256kb + 128kb (+ 128kb) = 32Mb
(A 9th IBAT is unneeded as 32Mb would need only a single 32Mb block)

Aligning data to 4M allows to map up to 512Mb data with 8 DBATs:
16Mb + 8Mb + 4Mb + 4Mb + 32Mb + 64Mb + 128Mb + 256Mb = 512Mb

Because some processors only have 4 BATs and because some targets need
DBATs for mapping other areas, the following patch will allow to
modify _etext and data alignment.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/Kconfig | 2 +
arch/powerpc/include/asm/book3s/32/pgtable.h | 11 ++++
arch/powerpc/mm/init_32.c | 4 +-
arch/powerpc/mm/mmu_decl.h | 8 +++
arch/powerpc/mm/pgtable_32.c | 10 +++-
arch/powerpc/mm/ppc_mmu_32.c | 87 ++++++++++++++++++++++++++--
6 files changed, 112 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index f3e420f3f1d7..ffcf4d7a1186 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -730,11 +730,13 @@ config THREAD_SHIFT

config ETEXT_SHIFT
int
+ default 17 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default PPC_PAGE_SHIFT

config DATA_SHIFT
int
default 24 if STRICT_KERNEL_RWX && PPC64
+ default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default PPC_PAGE_SHIFT

config FORCE_MAX_ZONEORDER
diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h
index cf844fed4527..05e973f24446 100644
--- a/arch/powerpc/include/asm/book3s/32/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/32/pgtable.h
@@ -174,7 +174,18 @@ static inline bool pte_user(pte_t pte)
* of RAM. -- Cort
*/
#define VMALLOC_OFFSET (0x1000000) /* 16M */
+
+/*
+ * With CONFIG_STRICT_KERNEL_RWX, kernel segments are set NX. But when modules
+ * are used, NX cannot be set on VMALLOC space. So vmalloc VM space and linear
+ * memory shall not share segments.
+ */
+#if defined(CONFIG_STRICT_KERNEL_RWX) && defined(CONFIG_MODULES)
+#define VMALLOC_START ((_ALIGN((long)high_memory, 256L << 20) + VMALLOC_OFFSET) & \
+ ~(VMALLOC_OFFSET - 1))
+#else
#define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)))
+#endif
#define VMALLOC_END ioremap_bot

#ifndef __ASSEMBLY__
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index ee5a430b9a18..bc28995a37ea 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -108,10 +108,8 @@ static void __init MMU_setup(void)
__map_without_bats = 1;
__map_without_ltlbs = 1;
}
- if (strict_kernel_rwx_enabled()) {
- __map_without_bats = 1;
+ if (strict_kernel_rwx_enabled())
__map_without_ltlbs = 1;
- }
}

/*
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index c29f061b1678..ccf994f1c4d2 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -165,3 +165,11 @@ unsigned long p_block_mapped(phys_addr_t pa);
static inline phys_addr_t v_block_mapped(unsigned long va) { return 0; }
static inline unsigned long p_block_mapped(phys_addr_t pa) { return 0; }
#endif
+
+#if defined(CONFIG_PPC_BOOK3S_32)
+void mmu_mark_initmem_nx(void);
+void mmu_mark_rodata_ro(void);
+#else
+static inline void mmu_mark_initmem_nx(void) { }
+static inline void mmu_mark_rodata_ro(void) { }
+#endif
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 68a5e2be5343..c78dba1f961a 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -365,7 +365,10 @@ void mark_initmem_nx(void)
unsigned long numpages = PFN_UP((unsigned long)_einittext) -
PFN_DOWN((unsigned long)_sinittext);

- change_page_attr(page, numpages, PAGE_KERNEL);
+ if (v_block_mapped((unsigned long)_stext) + 1)
+ mmu_mark_initmem_nx();
+ else
+ change_page_attr(page, numpages, PAGE_KERNEL);
}

#ifdef CONFIG_STRICT_KERNEL_RWX
@@ -374,6 +377,11 @@ void mark_rodata_ro(void)
struct page *page;
unsigned long numpages;

+ if (v_block_mapped((unsigned long)_sinittext)) {
+ mmu_mark_rodata_ro();
+ return;
+ }
+
page = virt_to_page(_stext);
numpages = PFN_UP((unsigned long)_etext) -
PFN_DOWN((unsigned long)_stext);
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 58dd71686707..83f8ce50169e 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -31,6 +31,7 @@
#include <asm/prom.h>
#include <asm/mmu.h>
#include <asm/machdep.h>
+#include <asm/sections.h>

#include "mmu_decl.h"

@@ -137,15 +138,10 @@ static void clearibat(int index)
bat[0].batl = 0;
}

-unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
+unsigned long __init __mmu_mapin_ram(unsigned long base, unsigned long top)
{
int idx;

- if (__map_without_bats) {
- printk(KERN_DEBUG "RAM mapped without BATs\n");
- return 0;
- }
-
while ((idx = find_free_bat()) != -1 && base != top) {
unsigned int size = block_size(base, top);

@@ -158,6 +154,85 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
return base;
}

+unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
+{
+ int done;
+ unsigned long border = (unsigned long)__init_begin - PAGE_OFFSET;
+
+ if (__map_without_bats) {
+ pr_debug("RAM mapped without BATs\n");
+ return 0;
+ }
+
+ if (!strict_kernel_rwx_enabled() || base >= border || top <= border)
+ return __mmu_mapin_ram(base, top);
+
+ done = __mmu_mapin_ram(base, border);
+ if (done != border - base)
+ return done;
+
+ return done + __mmu_mapin_ram(border, top);
+}
+
+void mmu_mark_initmem_nx(void)
+{
+ int nb = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
+ int i;
+ unsigned long base = (unsigned long)_stext - PAGE_OFFSET;
+ unsigned long top = (unsigned long)_etext - PAGE_OFFSET;
+ unsigned long size;
+
+ if (cpu_has_feature(CPU_FTR_601))
+ return;
+
+ 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);
+ base += size;
+ }
+ if (base < top) {
+ size = block_size(base, top);
+ size = max(size, 128UL << 10);
+ if ((top - base) > size) {
+ if (strict_kernel_rwx_enabled())
+ pr_warn("Kernel _etext not properly aligned\n");
+ size <<= 1;
+ }
+ setibat(i++, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
+ base += size;
+ }
+ for (; i < nb; i++)
+ clearibat(i);
+
+ update_bats();
+
+ for (i = TASK_SIZE >> 28; i < 16; i++) {
+ /* Do not set NX on VM space for modules */
+ if (IS_ENABLED(CONFIG_MODULES) &&
+ (VMALLOC_START & 0xf0000000) == i << 28)
+ break;
+ mtsrin(mfsrin(i << 28) | 0x10000000, i << 28);
+ }
+}
+
+void mmu_mark_rodata_ro(void)
+{
+ int nb = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
+ int i;
+
+ if (cpu_has_feature(CPU_FTR_601))
+ return;
+
+ for (i = 0; i < nb; i++) {
+ struct ppc_bat *bat = BATS[i];
+
+ if (bat_addrs[i].start < (unsigned long)__init_begin)
+ bat[1].batl = (bat[1].batl & ~BPP_RW) | BPP_RX;
+ }
+
+ update_bats();
+}
+
/*
* Set up one of the I/D BAT (block address translation) register pairs.
* The parameters are not checked; in particular size must be a power
--
2.13.3


2018-11-29 19:02:09

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 10/13] powerpc/kconfig: define PAGE_SHIFT inside Kconfig

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/Kconfig | 7 +++++++
arch/powerpc/include/asm/page.h | 13 ++-----------
2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8be31261aec8..4a81a80d0635 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -711,6 +711,13 @@ config PPC_256K_PAGES

endchoice

+config PPC_PAGE_SHIFT
+ int
+ default 18 if PPC_256K_PAGES
+ default 16 if PPC_64K_PAGES
+ default 14 if PPC_16K_PAGES
+ default 12
+
config THREAD_SHIFT
int "Thread shift" if EXPERT
range 13 15
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index 9ea903221a9f..d12a55441629 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -20,20 +20,11 @@

/*
* On regular PPC32 page size is 4K (but we support 4K/16K/64K/256K pages
- * on PPC44x). For PPC64 we support either 4K or 64K software
+ * on PPC44x and 4K/16K on 8xx). For PPC64 we support either 4K or 64K software
* page size. When using 64K pages however, whether we are really supporting
* 64K pages in HW or not is irrelevant to those definitions.
*/
-#if defined(CONFIG_PPC_256K_PAGES)
-#define PAGE_SHIFT 18
-#elif defined(CONFIG_PPC_64K_PAGES)
-#define PAGE_SHIFT 16
-#elif defined(CONFIG_PPC_16K_PAGES)
-#define PAGE_SHIFT 14
-#else
-#define PAGE_SHIFT 12
-#endif
-
+#define PAGE_SHIFT CONFIG_PPC_PAGE_SHIFT
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)

#ifndef __ASSEMBLY__
--
2.13.3


2018-11-29 19:02:38

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 01/13] powerpc/mm: add exec protection on powerpc 603

The 603 doesn't have a HASH table, TLB misses are handled by
software. It is then possible to generate page fault when
_PAGE_EXEC is not set like in nohash/32.

There is one "reserved" PTE bit available, this patch uses
it for _PAGE_EXEC.

In order to support it, set_pte_filter() and
set_access_flags_filter() are made common, and the handling
is made dependent on MMU_FTR_HPTE_TABLE

Reviewed-by: Aneesh Kumar K.V <[email protected]>
Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/include/asm/book3s/32/hash.h | 1 +
arch/powerpc/include/asm/book3s/32/pgtable.h | 18 +++++++++---------
arch/powerpc/include/asm/cputable.h | 8 ++++----
arch/powerpc/kernel/head_32.S | 2 +-
arch/powerpc/mm/dump_linuxpagetables-generic.c | 2 --
arch/powerpc/mm/pgtable.c | 20 +++++++++++---------
6 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/32/hash.h b/arch/powerpc/include/asm/book3s/32/hash.h
index f2892c7ab73e..2a0a467d2985 100644
--- a/arch/powerpc/include/asm/book3s/32/hash.h
+++ b/arch/powerpc/include/asm/book3s/32/hash.h
@@ -26,6 +26,7 @@
#define _PAGE_WRITETHRU 0x040 /* W: cache write-through */
#define _PAGE_DIRTY 0x080 /* C: page changed */
#define _PAGE_ACCESSED 0x100 /* R: page referenced */
+#define _PAGE_EXEC 0x200 /* software: exec allowed */
#define _PAGE_RW 0x400 /* software: user write access allowed */
#define _PAGE_SPECIAL 0x800 /* software: Special page */

diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h
index c21d33704633..cf844fed4527 100644
--- a/arch/powerpc/include/asm/book3s/32/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/32/pgtable.h
@@ -10,9 +10,9 @@
/* And here we include common definitions */

#define _PAGE_KERNEL_RO 0
-#define _PAGE_KERNEL_ROX 0
+#define _PAGE_KERNEL_ROX (_PAGE_EXEC)
#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW)
-#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW)
+#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC)

#define _PAGE_HPTEFLAGS _PAGE_HASHPTE

@@ -66,11 +66,11 @@ static inline bool pte_user(pte_t pte)
*/
#define PAGE_NONE __pgprot(_PAGE_BASE)
#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
+#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER)
+#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)

/* Permission masks used for kernel mappings */
#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
@@ -318,7 +318,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
int psize)
{
unsigned long set = pte_val(entry) &
- (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW);
+ (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);

pte_update(ptep, 0, set);

@@ -384,7 +384,7 @@ static inline int pte_dirty(pte_t pte) { return !!(pte_val(pte) & _PAGE_DIRTY);
static inline int pte_young(pte_t pte) { return !!(pte_val(pte) & _PAGE_ACCESSED); }
static inline int pte_special(pte_t pte) { return !!(pte_val(pte) & _PAGE_SPECIAL); }
static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
-static inline bool pte_exec(pte_t pte) { return true; }
+static inline bool pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }

static inline int pte_present(pte_t pte)
{
@@ -451,7 +451,7 @@ static inline pte_t pte_wrprotect(pte_t pte)

static inline pte_t pte_exprotect(pte_t pte)
{
- return pte;
+ return __pte(pte_val(pte) & ~_PAGE_EXEC);
}

static inline pte_t pte_mkclean(pte_t pte)
@@ -466,7 +466,7 @@ static inline pte_t pte_mkold(pte_t pte)

static inline pte_t pte_mkexec(pte_t pte)
{
- return pte;
+ return __pte(pte_val(pte) | _PAGE_EXEC);
}

static inline pte_t pte_mkpte(pte_t pte)
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 29f49a35d6ee..a0395ccbbe9e 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -296,7 +296,7 @@ static inline void cpu_feature_keys_init(void) { }
#define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE | CPU_FTR_USE_RTC)
#define CPU_FTRS_603 (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | \
- CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE | CPU_FTR_NOEXECUTE)
#define CPU_FTRS_604 (CPU_FTR_COMMON | CPU_FTR_PPC_LE)
#define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_L2CR | \
@@ -367,15 +367,15 @@ static inline void cpu_feature_keys_init(void) { }
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | \
CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
-#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE)
+#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_NOEXECUTE)
#define CPU_FTRS_G2_LE (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | \
CPU_FTR_MAYBE_CAN_NAP)
#define CPU_FTRS_E300 (CPU_FTR_MAYBE_CAN_DOZE | \
CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_COMMON)
+ CPU_FTR_COMMON | CPU_FTR_NOEXECUTE)
#define CPU_FTRS_E300C2 (CPU_FTR_MAYBE_CAN_DOZE | \
CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
+ CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE | CPU_FTR_NOEXECUTE)
#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON)
#define CPU_FTRS_8XX (CPU_FTR_NOEXECUTE)
#define CPU_FTRS_40X (CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 61ca27929355..d1c39b5ccfd6 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -499,7 +499,7 @@ InstructionTLBMiss:
lis r1,PAGE_OFFSET@h /* check if kernel address */
cmplw 0,r1,r3
mfspr r2,SPRN_SPRG_THREAD
- li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
+ li r1,_PAGE_USER|_PAGE_PRESENT|_PAGE_EXEC /* low addresses tested as user */
lwz r2,PGDIR(r2)
bge- 112f
mfspr r2,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
diff --git a/arch/powerpc/mm/dump_linuxpagetables-generic.c b/arch/powerpc/mm/dump_linuxpagetables-generic.c
index 1e3829ec1348..3fe98a0974c6 100644
--- a/arch/powerpc/mm/dump_linuxpagetables-generic.c
+++ b/arch/powerpc/mm/dump_linuxpagetables-generic.c
@@ -21,13 +21,11 @@ static const struct flag_info flag_array[] = {
.set = "rw",
.clear = "r ",
}, {
-#ifndef CONFIG_PPC_BOOK3S_32
.mask = _PAGE_EXEC,
.val = _PAGE_EXEC,
.set = " X ",
.clear = " ",
}, {
-#endif
.mask = _PAGE_PRESENT,
.val = _PAGE_PRESENT,
.set = "present",
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 1e33dccbd176..d3d61d29b4f1 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -74,7 +74,7 @@ static struct page *maybe_pte_to_page(pte_t pte)
* support falls into the same category.
*/

-static pte_t set_pte_filter(pte_t pte)
+static pte_t set_pte_filter_hash(pte_t pte)
{
if (radix_enabled())
return pte;
@@ -93,14 +93,12 @@ static pte_t set_pte_filter(pte_t pte)
return pte;
}

-static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma,
- int dirty)
-{
- return pte;
-}
-
#else /* CONFIG_PPC_BOOK3S */

+static pte_t set_pte_filter_hash(pte_t pte) { return pte; }
+
+#endif /* CONFIG_PPC_BOOK3S */
+
/* Embedded type MMU with HW exec support. This is a bit more complicated
* as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so
* instead we "filter out" the exec permission for non clean pages.
@@ -109,6 +107,9 @@ static pte_t set_pte_filter(pte_t pte)
{
struct page *pg;

+ if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
+ return set_pte_filter_hash(pte);
+
/* No exec permission in the first place, move on */
if (!pte_exec(pte) || !pte_looks_normal(pte))
return pte;
@@ -138,6 +139,9 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma,
{
struct page *pg;

+ if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
+ return pte;
+
/* So here, we only care about exec faults, as we use them
* to recover lost _PAGE_EXEC and perform I$/D$ coherency
* if necessary. Also if _PAGE_EXEC is already set, same deal,
@@ -172,8 +176,6 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma,
return pte_mkexec(pte);
}

-#endif /* CONFIG_PPC_BOOK3S */
-
/*
* set_pte stores a linux PTE into the linux page table.
*/
--
2.13.3


2018-11-29 19:03:09

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 08/13] powerpc/32: add helper to write into segment registers

This patch add an helper which wraps 'mtsrin' instruction
to write into segment registers.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/include/asm/reg.h | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index de52c3166ba4..c9c382e57017 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1423,6 +1423,11 @@ static inline void msr_check_and_clear(unsigned long bits)
#define mfsrin(v) ({unsigned int rval; \
asm volatile("mfsrin %0,%1" : "=r" (rval) : "r" (v)); \
rval;})
+
+static inline void mtsrin(u32 val, u32 idx)
+{
+ asm volatile("mtsrin %0, %1" : : "r" (val), "r" (idx));
+}
#endif

#define proc_trap() asm volatile("trap")
--
2.13.3


2018-11-29 19:03:37

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 11/13] powerpc/kconfig: define CONFIG_DATA_SHIFT and CONFIG_ETEXT_SHIFT

CONFIG_STRICT_KERNEL_RWX requires a special alignment
for DATA for some subarches. Today it is just defined
as an #ifdef in vmlinux.lds.S

In order to get more flexibility, this patch moves the
definition of this alignment in Kconfig

On some subarches, CONFIG_STRICT_KERNEL_RWX will
require a special alignment of _etext.

This patch also adds a configuration item for it in Kconfig

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/Kconfig | 9 +++++++++
arch/powerpc/kernel/vmlinux.lds.S | 9 +++------
2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 4a81a80d0635..f3e420f3f1d7 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -728,6 +728,15 @@ config THREAD_SHIFT
Used to define the stack size. The default is almost always what you
want. Only change this if you know what you are doing.

+config ETEXT_SHIFT
+ int
+ default PPC_PAGE_SHIFT
+
+config DATA_SHIFT
+ int
+ default 24 if STRICT_KERNEL_RWX && PPC64
+ default PPC_PAGE_SHIFT
+
config FORCE_MAX_ZONEORDER
int "Maximum zone order"
range 8 9 if PPC64 && PPC_64K_PAGES
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 1148c3c60c3b..d210dcfe915a 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -12,11 +12,8 @@
#include <asm/cache.h>
#include <asm/thread_info.h>

-#if defined(CONFIG_STRICT_KERNEL_RWX) && !defined(CONFIG_PPC32)
-#define STRICT_ALIGN_SIZE (1 << 24)
-#else
-#define STRICT_ALIGN_SIZE PAGE_SIZE
-#endif
+#define STRICT_ALIGN_SIZE (1 << CONFIG_DATA_SHIFT)
+#define ETEXT_ALIGN_SIZE (1 << CONFIG_ETEXT_SHIFT)

ENTRY(_stext)

@@ -131,7 +128,7 @@ SECTIONS

} :kernel

- . = ALIGN(PAGE_SIZE);
+ . = ALIGN(ETEXT_ALIGN_SIZE);
_etext = .;
PROVIDE32 (etext = .);

--
2.13.3


2018-11-29 19:03:37

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 09/13] powerpc/mmu: add is_strict_kernel_rwx() helper

Add a helper to know whether STRICT_KERNEL_RWX is enabled.

This is based on rodata_enabled flag which is defined only
when CONFIG_STRICT_KERNEL_RWX is selected.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/include/asm/mmu.h | 11 +++++++++++
arch/powerpc/mm/init_32.c | 4 +---
2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index eb20eb3b8fb0..6343cbf5b651 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -268,6 +268,17 @@ static inline u16 get_mm_addr_key(struct mm_struct *mm, unsigned long address)
}
#endif /* CONFIG_PPC_MEM_KEYS */

+#ifdef CONFIG_STRICT_KERNEL_RWX
+static inline bool strict_kernel_rwx_enabled(void)
+{
+ return rodata_enabled;
+}
+#else
+static inline bool strict_kernel_rwx_enabled(void)
+{
+ return false;
+}
+#endif
#endif /* !__ASSEMBLY__ */

/* The kernel use the constants below to index in the page sizes array.
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 3e59e5d64b01..ee5a430b9a18 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -108,12 +108,10 @@ static void __init MMU_setup(void)
__map_without_bats = 1;
__map_without_ltlbs = 1;
}
-#ifdef CONFIG_STRICT_KERNEL_RWX
- if (rodata_enabled) {
+ if (strict_kernel_rwx_enabled()) {
__map_without_bats = 1;
__map_without_ltlbs = 1;
}
-#endif
}

/*
--
2.13.3


2018-11-29 19:03:59

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 07/13] powerpc/mm/32s: add setibat() clearibat() and update_bats()

setibat() and clearibat() allows to manipulate IBATs independently
of DBATs.

update_bats() allows to update bats after init. This is done
with MMU off.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/include/asm/book3s/32/mmu-hash.h | 2 ++
arch/powerpc/kernel/head_32.S | 35 +++++++++++++++++++++++++++
arch/powerpc/mm/ppc_mmu_32.c | 32 ++++++++++++++++++++++++
3 files changed, 69 insertions(+)

diff --git a/arch/powerpc/include/asm/book3s/32/mmu-hash.h b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
index e38c91388c40..b4ccb832d4fb 100644
--- a/arch/powerpc/include/asm/book3s/32/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
@@ -83,6 +83,8 @@ typedef struct {
unsigned long vdso_base;
} mm_context_t;

+void update_bats(void);
+
#endif /* !__ASSEMBLY__ */

/* We happily ignore the smaller BATs on 601, we don't actually use
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index d1c39b5ccfd6..0f4c72ebb151 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -1101,6 +1101,41 @@ BEGIN_MMU_FTR_SECTION
END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
blr

+_ENTRY(update_bats)
+ lis r4, 1f@h
+ ori r4, r4, 1f@l
+ tophys(r4, r4)
+ mfmsr r6
+ mflr r7
+ li r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)
+ rlwinm r0, r6, 0, ~MSR_RI
+ rlwinm r0, r0, 0, ~MSR_EE
+ mtmsr r0
+ mtspr SPRN_SRR0, r4
+ mtspr SPRN_SRR1, r3
+ SYNC
+ RFI
+1: bl clear_bats
+ lis r3, BATS@ha
+ addi r3, r3, BATS@l
+ tophys(r3, r3)
+ LOAD_BAT(0, r3, r4, r5)
+ LOAD_BAT(1, r3, r4, r5)
+ LOAD_BAT(2, r3, r4, r5)
+ LOAD_BAT(3, r3, r4, r5)
+BEGIN_MMU_FTR_SECTION
+ LOAD_BAT(4, r3, r4, r5)
+ LOAD_BAT(5, r3, r4, r5)
+ LOAD_BAT(6, r3, r4, r5)
+ LOAD_BAT(7, r3, r4, r5)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
+ li r3, MSR_KERNEL & ~(MSR_IR | MSR_DR | MSR_RI)
+ mtmsr r3
+ mtspr SPRN_SRR0, r7
+ mtspr SPRN_SRR1, r6
+ SYNC
+ RFI
+
flush_tlbs:
lis r10, 0x40
1: addic. r10, r10, -0x1000
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 1078095d9407..58dd71686707 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -105,6 +105,38 @@ static unsigned int block_size(unsigned long base, unsigned long top)
return min3(max_size, 1U << base_shift, 1U << block_shift);
}

+/*
+ * Set up one of the IBAT (block address translation) register pairs.
+ * The parameters are not checked; in particular size must be a power
+ * 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)
+{
+ unsigned int bl = (size >> 17) - 1;
+ int wimgxpp;
+ struct ppc_bat *bat = BATS[index];
+ unsigned long flags = pgprot_val(prot);
+
+ if (!cpu_has_feature(CPU_FTR_NEED_COHERENT))
+ flags &= ~_PAGE_COHERENT;
+
+ wimgxpp = (flags & _PAGE_COHERENT) | (_PAGE_EXEC ? BPP_RX : BPP_XX);
+ bat[0].batu = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
+ bat[0].batl = BAT_PHYS_ADDR(phys) | wimgxpp;
+ if (flags & _PAGE_USER)
+ bat[0].batu |= 1; /* Vp = 1 */
+}
+
+static void clearibat(int index)
+{
+ struct ppc_bat *bat = BATS[index];
+
+ bat[0].batu = 0;
+ bat[0].batl = 0;
+}
+
unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
int idx;
--
2.13.3


2018-11-29 19:04:29

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH v1 02/13] powerpc/mm/32: add base address to mmu_mapin_ram()

At the time being, mmu_mapin_ram() always maps RAM from the beginning.
But some platforms like the WII have to map a second block of RAM.

This patch adds to mmu_mapin_ram() the base address of the block.
At the moment, only base address 0 is supported.

Signed-off-by: Christophe Leroy <[email protected]>
---
arch/powerpc/mm/40x_mmu.c | 2 +-
arch/powerpc/mm/44x_mmu.c | 2 +-
arch/powerpc/mm/8xx_mmu.c | 2 +-
arch/powerpc/mm/fsl_booke_mmu.c | 2 +-
arch/powerpc/mm/mmu_decl.h | 2 +-
arch/powerpc/mm/pgtable_32.c | 6 +++---
arch/powerpc/mm/ppc_mmu_32.c | 2 +-
7 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
index 61ac468c87c6..b9cf6f8764b0 100644
--- a/arch/powerpc/mm/40x_mmu.c
+++ b/arch/powerpc/mm/40x_mmu.c
@@ -93,7 +93,7 @@ void __init MMU_init_hw(void)
#define LARGE_PAGE_SIZE_16M (1<<24)
#define LARGE_PAGE_SIZE_4M (1<<22)

-unsigned long __init mmu_mapin_ram(unsigned long top)
+unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
unsigned long v, s, mapped;
phys_addr_t p;
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index 12d92518e898..f59df82896a0 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -178,7 +178,7 @@ void __init MMU_init_hw(void)
flush_instruction_cache();
}

-unsigned long __init mmu_mapin_ram(unsigned long top)
+unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
unsigned long addr;
unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c
index 01b7f5107c3a..50b640c7a7f9 100644
--- a/arch/powerpc/mm/8xx_mmu.c
+++ b/arch/powerpc/mm/8xx_mmu.c
@@ -107,7 +107,7 @@ static void __init mmu_patch_cmp_limit(s32 *site, unsigned long mapped)
patch_instruction_site(site, instr);
}

-unsigned long __init mmu_mapin_ram(unsigned long top)
+unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
unsigned long mapped;

diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 080d49b26c3a..210cbc1faf63 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -221,7 +221,7 @@ unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx, bool dryrun)
#error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS"
#endif

-unsigned long __init mmu_mapin_ram(unsigned long top)
+unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1;
}
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 8574fbbc45e0..c29f061b1678 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -130,7 +130,7 @@ extern void wii_memory_fixups(void);
*/
#ifdef CONFIG_PPC32
extern void MMU_init_hw(void);
-extern unsigned long mmu_mapin_ram(unsigned long top);
+unsigned long mmu_mapin_ram(unsigned long base, unsigned long top);
#endif

#ifdef CONFIG_PPC_FSL_BOOK3E
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index bda3c6f1bd32..c030f24d1d05 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -275,15 +275,15 @@ void __init mapin_ram(void)

#ifndef CONFIG_WII
top = total_lowmem;
- s = mmu_mapin_ram(top);
+ s = mmu_mapin_ram(0, top);
__mapin_ram_chunk(s, top);
#else
if (!wii_hole_size) {
- s = mmu_mapin_ram(total_lowmem);
+ s = mmu_mapin_ram(0, total_lowmem);
__mapin_ram_chunk(s, total_lowmem);
} else {
top = wii_hole_start;
- s = mmu_mapin_ram(top);
+ s = mmu_mapin_ram(0, top);
__mapin_ram_chunk(s, top);

top = memblock_end_of_DRAM();
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index f6f575bae3bc..3a29e88308b0 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -72,7 +72,7 @@ unsigned long p_block_mapped(phys_addr_t pa)
return 0;
}

-unsigned long __init mmu_mapin_ram(unsigned long top)
+unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
unsigned long tot, bl, done;
unsigned long max_size = (256<<20);
--
2.13.3


2018-12-03 21:58:40

by J. Neuschäfer

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

Hi,

On Thu, Nov 29, 2018 at 07:00:16PM +0000, Christophe Leroy wrote:
> This patch reworks mmu_mapin_ram() to be more generic and map as much
> blocks as possible. It now supports blocks not starting at address 0.
>
> It scans DBATs array to find free ones instead of forcing the use of
> BAT2 and BAT3.
>
> Signed-off-by: Christophe Leroy <[email protected]>
> ---

I've just tested this series on my Wii, and starting from this patch
(03/13), it hangs at the following lines of output:

[ 0.000000] printk: bootconsole [udbg0] enabled
[ 0.000000] Total memory = 319MB; using 1024kB for hash table (at (ptrval))

Before this patch it looks like this and boots to userspace:

[ 0.000000] printk: bootconsole [udbg0] enabled
[ 0.000000] Total memory = 319MB; using 1024kB for hash table (at (ptrval))
[ 0.000000] Linux version 4.20.0-rc5-wii-00022-gfbb911b84755 (jn@longitude) (gcc version 8.2.0 (Debian 8.2.0-9)) #1337 PREEMPT Mon Dec 3 21:49:02 CET 2018
ug_udbg_init: early -> final
usbgecko_udbg: ready
[ 0.000000] Using wii machine description
...

I've tested at patch 1, 2, 3, 4, and 13, so I don't know if it works
somewhere in the middle, but probably not.

(And in case you're wondering about the 22 in the version string: Those
are mostly patches that give me a serial console.)

I'm not sure what is going on, because I haven't looked closely at the
patches or tried to debug the problem. If you have some debugging tips,
I can try them.


Jonathan Neuschäfer


Attachments:
(No filename) (1.50 kB)
signature.asc (849.00 B)
Download all attachments

2018-12-13 12:19:06

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

Hi,

On 12/03/2018 09:55 PM, Jonathan Neuschäfer wrote:
> Hi,
>
> On Thu, Nov 29, 2018 at 07:00:16PM +0000, Christophe Leroy wrote:
>> This patch reworks mmu_mapin_ram() to be more generic and map as much
>> blocks as possible. It now supports blocks not starting at address 0.
>>
>> It scans DBATs array to find free ones instead of forcing the use of
>> BAT2 and BAT3.
>>
>> Signed-off-by: Christophe Leroy <[email protected]>
>> ---
>
> I've just tested this series on my Wii, and starting from this patch
> (03/13), it hangs at the following lines of output:
>
> [ 0.000000] printk: bootconsole [udbg0] enabled
> [ 0.000000] Total memory = 319MB; using 1024kB for hash table (at (ptrval))
>
> Before this patch it looks like this and boots to userspace:
>
> [ 0.000000] printk: bootconsole [udbg0] enabled
> [ 0.000000] Total memory = 319MB; using 1024kB for hash table (at (ptrval))
> [ 0.000000] Linux version 4.20.0-rc5-wii-00022-gfbb911b84755 (jn@longitude) (gcc version 8.2.0 (Debian 8.2.0-9)) #1337 PREEMPT Mon Dec 3 21:49:02 CET 2018
> ug_udbg_init: early -> final
> usbgecko_udbg: ready
> [ 0.000000] Using wii machine description

Can you tell/provide the .config and dts used ?

You seem to have 319MB RAM wherease arch/powerpc/boot/dts/wii.dts only
has 88MB Memory:

memory {
device_type = "memory";
reg = <0x00000000 0x01800000 /* MEM1 24MB 1T-SRAM */
0x10000000 0x04000000>; /* MEM2 64MB GDDR3 */
};

Christophe

> ...
>
> I've tested at patch 1, 2, 3, 4, and 13, so I don't know if it works
> somewhere in the middle, but probably not.
>
> (And in case you're wondering about the 22 in the version string: Those
> are mostly patches that give me a serial console.)
>
> I'm not sure what is going on, because I haven't looked closely at the
> patches or tried to debug the problem. If you have some debugging tips,
> I can try them.
>
>
> Jonathan Neuschäfer
>

2018-12-13 14:52:51

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

Hi Again,

Le 13/12/2018 à 13:16, Christophe Leroy a écrit :
> Hi,
>
> On 12/03/2018 09:55 PM, Jonathan Neuschäfer wrote:
>> Hi,
>>
>> On Thu, Nov 29, 2018 at 07:00:16PM +0000, Christophe Leroy wrote:
>>> This patch reworks mmu_mapin_ram() to be more generic and map as much
>>> blocks as possible. It now supports blocks not starting at address 0.
>>>
>>> It scans DBATs array to find free ones instead of forcing the use of
>>> BAT2 and BAT3.
>>>
>>> Signed-off-by: Christophe Leroy <[email protected]>
>>> ---
>>
>> I've just tested this series on my Wii, and starting from this patch
>> (03/13), it hangs at the following lines of output:
>>
>> [    0.000000] printk: bootconsole [udbg0] enabled
>> [    0.000000] Total memory = 319MB; using 1024kB for hash table (at
>> (ptrval))
>>
>> Before this patch it looks like this and boots to userspace:
>>
>> [    0.000000] printk: bootconsole [udbg0] enabled
>> [    0.000000] Total memory = 319MB; using 1024kB for hash table (at
>> (ptrval))
>> [    0.000000] Linux version 4.20.0-rc5-wii-00022-gfbb911b84755
>> (jn@longitude) (gcc version 8.2.0 (Debian 8.2.0-9)) #1337 PREEMPT Mon
>> Dec 3 21:49:02 CET 2018
>> ug_udbg_init: early -> final
>> usbgecko_udbg: ready
>> [    0.000000] Using wii machine description
>
> Can you tell/provide the .config and dts used ?
>
> You seem to have 319MB RAM wherease arch/powerpc/boot/dts/wii.dts only
> has 88MB Memory:
>
>     memory {
>         device_type = "memory";
>         reg = <0x00000000 0x01800000    /* MEM1 24MB 1T-SRAM */
>                0x10000000 0x04000000>;    /* MEM2 64MB GDDR3 */
>     };

Putting the same description in my mpc832x board DTS and doing a few
hacks to get the WII functions called, I get the following:

[ 0.000000] Top of RAM: 0x14000000, Total RAM: 0x5800000
[ 0.000000] Memory hole size: 232MB
[ 0.000000] Zone ranges:
[ 0.000000] DMA [mem 0x0000000000000000-0x0000000013ffffff]
[ 0.000000] Normal empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000000000000-0x00000000017fffff]
[ 0.000000] node 0: [mem 0x0000000010000000-0x0000000013ffffff]
[ 0.000000] Initmem setup node 0 [mem
0x0000000000000000-0x0000000013ffffff]
[ 0.000000] On node 0 totalpages: 22528
[ 0.000000] DMA zone: 640 pages used for memmap
[ 0.000000] DMA zone: 0 pages reserved
[ 0.000000] DMA zone: 22528 pages, LIFO batch:3
[ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[ 0.000000] pcpu-alloc: [0] 0
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 21888
[ 0.000000] Kernel command line: loglevel=7
ip=192.168.2.5:192.168.2.2::255.0
[ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536
bytes)
[ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
[ 0.000000] Memory: 77060K/90112K available (6548K kernel code, 1156K
rwdata,
[ 0.000000] Kernel virtual memory layout:
[ 0.000000] * 0xfffdf000..0xfffff000 : fixmap
[ 0.000000] * 0xfdffd000..0xfe000000 : early ioremap
[ 0.000000] * 0xd5000000..0xfdffd000 : vmalloc & ioremap




root@vgoippro:~# cat /sys/kernel/debug/powerpc/block_address_translation
---[ Instruction Block Address Translation ]---
0: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC coherent
1: -
2: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC coherent
3: -
4: 0xd0000000-0xd3ffffff 0x10000000 Kernel EXEC coherent
5: -
6: -
7: -

---[ Data Block Address Translation ]---
0: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW coherent
1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
2: 0xc1000000-0xc17fffff 0x01000000 Kernel RW coherent
3: -
4: 0xd0000000-0xd3ffffff 0x10000000 Kernel RW coherent
5: -
6: -
7: -


Could you please provide the dmesg and
/sys/kernel/debug/powerpc/block_address_translation from before this
patch, so that we can compare and identify the differences if any ?

Thanks
Christophe



>
> Christophe
>
>> ...
>>
>> I've tested at patch 1, 2, 3, 4, and 13, so I don't know if it works
>> somewhere in the middle, but probably not.
>>
>> (And in case you're wondering about the 22 in the version string: Those
>> are mostly patches that give me a serial console.)
>>
>> I'm not sure what is going on, because I haven't looked closely at the
>> patches or tried to debug the problem. If you have some debugging tips,
>> I can try them.
>>
>>
>> Jonathan Neuschäfer
>>

2018-12-17 01:35:29

by J. Neuschäfer

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

Hi, thanks for your reply.

On Thu, Dec 13, 2018 at 03:51:32PM +0100, Christophe Leroy wrote:
> Hi Again,
>
> Le 13/12/2018 à 13:16, Christophe Leroy a écrit :
[...]
> > Can you tell/provide the .config and dts used ?

I'm using wii.dts and almost the wii_defconfig from my tree (save-
defconfig result is attached), which is 4.20-rc5 plus a few patches:

https://github.com/neuschaefer/linux wii-4.20-rc5 (w/o your patches)
https://github.com/neuschaefer/linux wii-4.20-rc5-ppcbat (w/ your patches 1-3)

> > You seem to have 319MB RAM wherease arch/powerpc/boot/dts/wii.dts only
> > has 88MB Memory:
> >
> >     memory {
> >         device_type = "memory";
> >         reg = <0x00000000 0x01800000    /* MEM1 24MB 1T-SRAM */
> >                0x10000000 0x04000000>;    /* MEM2 64MB GDDR3 */
> >     };

This is, I think, because something marks all the address space from 0
to the end of MEM2 as RAM, and then cuts out a hole in the middle. I'm
not sure about the exact mechanism.

Unfortunately this hole has to be treated carefully because it contains
MMIO devices.

> Putting the same description in my mpc832x board DTS and doing a few hacks
> to get the WII functions called, I get the following:
>
> [ 0.000000] Top of RAM: 0x14000000, Total RAM: 0x5800000
> [ 0.000000] Memory hole size: 232MB
> [ 0.000000] Zone ranges:
> [ 0.000000] DMA [mem 0x0000000000000000-0x0000000013ffffff]
> [ 0.000000] Normal empty
> [ 0.000000] Movable zone start for each node
> [ 0.000000] Early memory node ranges
> [ 0.000000] node 0: [mem 0x0000000000000000-0x00000000017fffff]
> [ 0.000000] node 0: [mem 0x0000000010000000-0x0000000013ffffff]
> [ 0.000000] Initmem setup node 0 [mem
> 0x0000000000000000-0x0000000013ffffff]
> [ 0.000000] On node 0 totalpages: 22528
> [ 0.000000] DMA zone: 640 pages used for memmap
> [ 0.000000] DMA zone: 0 pages reserved
> [ 0.000000] DMA zone: 22528 pages, LIFO batch:3
> [ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
> [ 0.000000] pcpu-alloc: [0] 0
> [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 21888
> [ 0.000000] Kernel command line: loglevel=7
> ip=192.168.2.5:192.168.2.2::255.0
> [ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536
> bytes)
> [ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
> [ 0.000000] Memory: 77060K/90112K available (6548K kernel code, 1156K
> rwdata,
> [ 0.000000] Kernel virtual memory layout:
> [ 0.000000] * 0xfffdf000..0xfffff000 : fixmap
> [ 0.000000] * 0xfdffd000..0xfe000000 : early ioremap
> [ 0.000000] * 0xd5000000..0xfdffd000 : vmalloc & ioremap
>
>
>
>
> root@vgoippro:~# cat /sys/kernel/debug/powerpc/block_address_translation
> ---[ Instruction Block Address Translation ]---
> 0: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC coherent
> 1: -
> 2: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC coherent
> 3: -
> 4: 0xd0000000-0xd3ffffff 0x10000000 Kernel EXEC coherent
> 5: -
> 6: -
> 7: -
>
> ---[ Data Block Address Translation ]---
> 0: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW coherent
> 1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
> 2: 0xc1000000-0xc17fffff 0x01000000 Kernel RW coherent
> 3: -
> 4: 0xd0000000-0xd3ffffff 0x10000000 Kernel RW coherent
> 5: -
> 6: -
> 7: -
>
>
> Could you please provide the dmesg and
> /sys/kernel/debug/powerpc/block_address_translation from before this patch,
> so that we can compare and identify the differences if any ?

After applying the patch that adds this debugfs file and enabling
CONFIG_PPC_PTDUMP, I get this:

# cat /sys/kernel/debug/powerpc/block_address_translation
---[ Instruction Block Address Translation ]---
0: -
1: -
2: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC
3: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC
4: 0xd0000000-0xd1ffffff 0x10000000 Kernel EXEC
5: -
6: -
7: -

---[ Data Block Address Translation ]---
0: -
1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
2: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW
3: 0xc1000000-0xc17fffff 0x01000000 Kernel RW
4: 0xd0000000-0xd1ffffff 0x10000000 Kernel RW
5: -
6: -
7: -

dmesg is attached.


I added some tracing to the setbat function:

diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index f6f575bae3bc..4da3dc54fe46 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -120,6 +120,9 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys,
struct ppc_bat *bat = BATS[index];
unsigned long flags = pgprot_val(prot);

+ pr_info("setbat(%u, %px, %px, %px, %lx)\n",
+ index, (void *)virt, (void *)phys, (void *)size, flags);
+
if ((flags & _PAGE_NO_CACHE) ||
(cpu_has_feature(CPU_FTR_NEED_COHERENT) == 0))
flags &= ~_PAGE_COHERENT;


And here's what I got:

Before your patches (circa v4.20-rc5):
[ 0.000000] setbat(2, c0000000, 00000000, 01000000, 591)
[ 0.000000] setbat(3, c1000000, 01000000, 00800000, 591)
[ 0.000000] setbat(4, d0000000, 10000000, 02000000, 591)

With patches 1-3:
[ 0.000000] setbat(0, c0000000, 00000000, 01000000, 311)
[ 0.000000] setbat(2, c1000000, 01000000, 00800000, 311)
[ 0.000000] setbat(4, d0000000, 10000000, 02000000, 791)

According to arch/powerpc/include/asm/book3s/32/hash.h,
- 0x591 = _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | _PAGE_PRESENT
- 0x311 = _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_COHERENT | _PAGE_PRESENT
- 0x791 = _PAGE_RW | _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | _PAGE_PRESENT

Changing the flags back to 0x591 in setbat doesn't result in a booting
system.


> > > I've tested at patch 1, 2, 3, 4, and 13, so I don't know if it works
> > > somewhere in the middle, but probably not.

(I get the same results if I also merge powerpc/next, btw)


I hope this helps somewhat,
Jonathan Neuschäfer


Attachments:
(No filename) (0.00 B)
signature.asc (849.00 B)
Download all attachments

2018-12-17 10:25:53

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()



Le 17/12/2018 ? 02:28, Jonathan Neusch?fer a ?crit?:
> Hi, thanks for your reply.
>
> On Thu, Dec 13, 2018 at 03:51:32PM +0100, Christophe Leroy wrote:
>> Hi Again,
>>
>> Le 13/12/2018 ? 13:16, Christophe Leroy a ?crit?:
> [...]
>>> Can you tell/provide the .config and dts used ?
>
> I'm using wii.dts and almost the wii_defconfig from my tree (save-
> defconfig result is attached), which is 4.20-rc5 plus a few patches:
>
> https://github.com/neuschaefer/linux wii-4.20-rc5 (w/o your patches)
> https://github.com/neuschaefer/linux wii-4.20-rc5-ppcbat (w/ your patches 1-3)
>
>>> You seem to have 319MB RAM wherease arch/powerpc/boot/dts/wii.dts only
>>> has 88MB Memory:
>>>
>>> ????memory {
>>> ??????? device_type = "memory";
>>> ??????? reg = <0x00000000 0x01800000??? /* MEM1 24MB 1T-SRAM */
>>> ?????????????? 0x10000000 0x04000000>;??? /* MEM2 64MB GDDR3 */
>>> ????};
>
> This is, I think, because something marks all the address space from 0
> to the end of MEM2 as RAM, and then cuts out a hole in the middle. I'm
> not sure about the exact mechanism.
>
> Unfortunately this hole has to be treated carefully because it contains
> MMIO devices.
>
>> Putting the same description in my mpc832x board DTS and doing a few hacks
>> to get the WII functions called, I get the following:
>>
>> [ 0.000000] Top of RAM: 0x14000000, Total RAM: 0x5800000
>> [ 0.000000] Memory hole size: 232MB
>> [ 0.000000] Zone ranges:
>> [ 0.000000] DMA [mem 0x0000000000000000-0x0000000013ffffff]
>> [ 0.000000] Normal empty
>> [ 0.000000] Movable zone start for each node
>> [ 0.000000] Early memory node ranges
>> [ 0.000000] node 0: [mem 0x0000000000000000-0x00000000017fffff]
>> [ 0.000000] node 0: [mem 0x0000000010000000-0x0000000013ffffff]
>> [ 0.000000] Initmem setup node 0 [mem
>> 0x0000000000000000-0x0000000013ffffff]
>> [ 0.000000] On node 0 totalpages: 22528
>> [ 0.000000] DMA zone: 640 pages used for memmap
>> [ 0.000000] DMA zone: 0 pages reserved
>> [ 0.000000] DMA zone: 22528 pages, LIFO batch:3
>> [ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
>> [ 0.000000] pcpu-alloc: [0] 0
>> [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 21888
>> [ 0.000000] Kernel command line: loglevel=7
>> ip=192.168.2.5:192.168.2.2::255.0
>> [ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536
>> bytes)
>> [ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
>> [ 0.000000] Memory: 77060K/90112K available (6548K kernel code, 1156K
>> rwdata,
>> [ 0.000000] Kernel virtual memory layout:
>> [ 0.000000] * 0xfffdf000..0xfffff000 : fixmap
>> [ 0.000000] * 0xfdffd000..0xfe000000 : early ioremap
>> [ 0.000000] * 0xd5000000..0xfdffd000 : vmalloc & ioremap
>>
>>
>>
>>
>> root@vgoippro:~# cat /sys/kernel/debug/powerpc/block_address_translation
>> ---[ Instruction Block Address Translation ]---
>> 0: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC coherent
>> 1: -
>> 2: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC coherent
>> 3: -
>> 4: 0xd0000000-0xd3ffffff 0x10000000 Kernel EXEC coherent
>> 5: -
>> 6: -
>> 7: -
>>
>> ---[ Data Block Address Translation ]---
>> 0: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW coherent
>> 1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
>> 2: 0xc1000000-0xc17fffff 0x01000000 Kernel RW coherent
>> 3: -
>> 4: 0xd0000000-0xd3ffffff 0x10000000 Kernel RW coherent
>> 5: -
>> 6: -
>> 7: -
>>
>>
>> Could you please provide the dmesg and
>> /sys/kernel/debug/powerpc/block_address_translation from before this patch,
>> so that we can compare and identify the differences if any ?
>
> After applying the patch that adds this debugfs file and enabling
> CONFIG_PPC_PTDUMP, I get this:
>
> # cat /sys/kernel/debug/powerpc/block_address_translation
> ---[ Instruction Block Address Translation ]---
> 0: -
> 1: -
> 2: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC
> 3: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC
> 4: 0xd0000000-0xd1ffffff 0x10000000 Kernel EXEC
> 5: -
> 6: -
> 7: -
>
> ---[ Data Block Address Translation ]---
> 0: -
> 1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
> 2: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW
> 3: 0xc1000000-0xc17fffff 0x01000000 Kernel RW
> 4: 0xd0000000-0xd1ffffff 0x10000000 Kernel RW
> 5: -
> 6: -
> 7: -
>
> dmesg is attached.
>
>
> I added some tracing to the setbat function:
>
> diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
> index f6f575bae3bc..4da3dc54fe46 100644
> --- a/arch/powerpc/mm/ppc_mmu_32.c
> +++ b/arch/powerpc/mm/ppc_mmu_32.c
> @@ -120,6 +120,9 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys,
> struct ppc_bat *bat = BATS[index];
> unsigned long flags = pgprot_val(prot);
>
> + pr_info("setbat(%u, %px, %px, %px, %lx)\n",
> + index, (void *)virt, (void *)phys, (void *)size, flags);
> +
> if ((flags & _PAGE_NO_CACHE) ||
> (cpu_has_feature(CPU_FTR_NEED_COHERENT) == 0))
> flags &= ~_PAGE_COHERENT;
>
>
> And here's what I got:
>
> Before your patches (circa v4.20-rc5):
> [ 0.000000] setbat(2, c0000000, 00000000, 01000000, 591)
> [ 0.000000] setbat(3, c1000000, 01000000, 00800000, 591)
> [ 0.000000] setbat(4, d0000000, 10000000, 02000000, 591)

Ok, I have not tested against raw v4.20-rc5. I always powerpc/merge
branch as the reference. Maybe I should try that.

>
> With patches 1-3:
> [ 0.000000] setbat(0, c0000000, 00000000, 01000000, 311)
> [ 0.000000] setbat(2, c1000000, 01000000, 00800000, 311)
> [ 0.000000] setbat(4, d0000000, 10000000, 02000000, 791)

What we see is that BAT0 is not used in the origin. I have always
wondered the reason, maybe there is something odd behind and BAT0 shall
no ne used.

Could you try and modify find_free_bat() so that it starts at b = 1
instead of b = 0 ?

>
> According to arch/powerpc/include/asm/book3s/32/hash.h,
> - 0x591 = _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | _PAGE_PRESENT
> - 0x311 = _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_COHERENT | _PAGE_PRESENT
> - 0x791 = _PAGE_RW | _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | _PAGE_PRESENT
>

Yes, patch 1 added _PAGE_EXEC which explains this 0x200.
Do you confirm it still works well with only patch 1 ?

And patch 3 uses PAGE_KERNEL_TEXT instead of PAGE_KERNEL_X, hence the
lack of _PAGE_RW, which should not be necessary.



> Changing the flags back to 0x591 in setbat doesn't result in a booting
> system.
>
>
>>>> I've tested at patch 1, 2, 3, 4, and 13, so I don't know if it works
>>>> somewhere in the middle, but probably not.
>
> (I get the same results if I also merge powerpc/next, btw)

Ok, then no need for me to test with raw 4.20 rc 5.

Christophe

>
>
> I hope this helps somewhat,
> Jonathan Neusch?fer
>

2018-12-18 03:07:02

by J. Neuschäfer

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

On Mon, Dec 17, 2018 at 10:29:18AM +0100, Christophe Leroy wrote:
> > With patches 1-3:
> > [ 0.000000] setbat(0, c0000000, 00000000, 01000000, 311)
> > [ 0.000000] setbat(2, c1000000, 01000000, 00800000, 311)
> > [ 0.000000] setbat(4, d0000000, 10000000, 02000000, 791)
>
> What we see is that BAT0 is not used in the origin. I have always wondered
> the reason, maybe there is something odd behind and BAT0 shall no ne used.
>
> Could you try and modify find_free_bat() so that it starts at b = 1 instead
> of b = 0 ?

In this case, setbat is called with index 2, 3, and 4, but the Wii still
doesn't boot.

> > According to arch/powerpc/include/asm/book3s/32/hash.h,
> > - 0x591 = _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | _PAGE_PRESENT
> > - 0x311 = _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_COHERENT | _PAGE_PRESENT
> > - 0x791 = _PAGE_RW | _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | _PAGE_PRESENT
> >
>
> Yes, patch 1 added _PAGE_EXEC which explains this 0x200.
> Do you confirm it still works well with only patch 1 ?

Patch 1 alone boots to userspace.


Jonathan


Attachments:
(No filename) (1.12 kB)
signature.asc (849.00 B)
Download all attachments

2018-12-18 09:20:48

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()



On 12/18/2018 03:05 AM, Jonathan Neusch?fer wrote:
> On Mon, Dec 17, 2018 at 10:29:18AM +0100, Christophe Leroy wrote:
>>> With patches 1-3:
>>> [ 0.000000] setbat(0, c0000000, 00000000, 01000000, 311)
>>> [ 0.000000] setbat(2, c1000000, 01000000, 00800000, 311)
>>> [ 0.000000] setbat(4, d0000000, 10000000, 02000000, 791)
>>
>> What we see is that BAT0 is not used in the origin. I have always wondered
>> the reason, maybe there is something odd behind and BAT0 shall no ne used.
>>
>> Could you try and modify find_free_bat() so that it starts at b = 1 instead
>> of b = 0 ?
>
> In this case, setbat is called with index 2, 3, and 4, but the Wii still
> doesn't boot.
>
>>> According to arch/powerpc/include/asm/book3s/32/hash.h,
>>> - 0x591 = _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | _PAGE_PRESENT
>>> - 0x311 = _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_COHERENT | _PAGE_PRESENT
>>> - 0x791 = _PAGE_RW | _PAGE_EXEC | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | _PAGE_PRESENT
>>>
>>
>> Yes, patch 1 added _PAGE_EXEC which explains this 0x200.
>> Do you confirm it still works well with only patch 1 ?
>
> Patch 1 alone boots to userspace.
>

Ok, thanks for testing.

The only difference I see then are the flags. Everything else is seems
identical.

I know you tried already, but would you mind trying once more with the
following change ?

diff --git b/arch/powerpc/mm/ppc_mmu_32.c a/arch/powerpc/mm/ppc_mmu_32.c
index 61c10ee00ba2..628fba266663 100644
--- b/arch/powerpc/mm/ppc_mmu_32.c
+++ a/arch/powerpc/mm/ppc_mmu_32.c
@@ -119,7 +119,7 @@ unsigned long __init mmu_mapin_ram(unsigned long
base, unsigned long top)

if (size < 128 << 10)
break;
- setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
+ setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_X);
base += size;
}

I think we may have some code trying to modify the kernel text without
using code patching functions.

Thanks,
Christophe


>
> Jonathan
>

2018-12-18 14:10:29

by J. Neuschäfer

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

On Tue, Dec 18, 2018 at 09:18:42AM +0000, Christophe Leroy wrote:
> The only difference I see then are the flags. Everything else is seems
> identical.
>
> I know you tried already, but would you mind trying once more with the
> following change ?
>
[...]
> - setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
> + setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_X);

Good call, with this workaround on top of patches 1-3, it boots again:

# mount -t debugfs d /sys/kernel/debug
# cat /sys/kernel/debug/powerpc/block_address_translation
---[ Instruction Block Address Translation ]---
0: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC
1: -
2: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC
3: -
4: 0xd0000000-0xd1ffffff 0x10000000 Kernel EXEC
5: -
6: -
7: -

---[ Data Block Address Translation ]---
0: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW
1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
2: 0xc1000000-0xc17fffff 0x01000000 Kernel RW
3: -
4: 0xd0000000-0xd1ffffff 0x10000000 Kernel RW
5: -
6: -
7: -

> I think we may have some code trying to modify the kernel text without using
> code patching functions.

Is there any faster way than to sprinkle some printks in setup_kernel
and try to find the guilty piece of code this way?


Jonathan


Attachments:
(No filename) (1.38 kB)
signature.asc (849.00 B)
Download all attachments

2018-12-18 14:17:16

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()



Le 18/12/2018 ? 15:07, Jonathan Neusch?fer a ?crit?:
> On Tue, Dec 18, 2018 at 09:18:42AM +0000, Christophe Leroy wrote:
>> The only difference I see then are the flags. Everything else is seems
>> identical.
>>
>> I know you tried already, but would you mind trying once more with the
>> following change ?
>>
> [...]
>> - setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
>> + setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_X);
>
> Good call, with this workaround on top of patches 1-3, it boots again:
>
> # mount -t debugfs d /sys/kernel/debug
> # cat /sys/kernel/debug/powerpc/block_address_translation
> ---[ Instruction Block Address Translation ]---
> 0: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC
> 1: -
> 2: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC
> 3: -
> 4: 0xd0000000-0xd1ffffff 0x10000000 Kernel EXEC
> 5: -
> 6: -
> 7: -
>
> ---[ Data Block Address Translation ]---
> 0: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW
> 1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
> 2: 0xc1000000-0xc17fffff 0x01000000 Kernel RW
> 3: -
> 4: 0xd0000000-0xd1ffffff 0x10000000 Kernel RW
> 5: -
> 6: -
> 7: -
>
>> I think we may have some code trying to modify the kernel text without using
>> code patching functions.
>
> Is there any faster way than to sprinkle some printks in setup_kernel
> and try to find the guilty piece of code this way?

Can you start with the serie
https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=75072 ?

Christophe

>
>
> Jonathan
>

2018-12-18 14:56:37

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()



Le 18/12/2018 ? 15:15, Christophe Leroy a ?crit?:
>
>
> Le 18/12/2018 ? 15:07, Jonathan Neusch?fer a ?crit?:
>> On Tue, Dec 18, 2018 at 09:18:42AM +0000, Christophe Leroy wrote:
>>> The only difference I see then are the flags. Everything else is seems
>>> identical.
>>>
>>> I know you tried already, but would you mind trying once more with the
>>> following change ?
>>>
>> [...]
>>> -??????? setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
>>> +??????? setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_X);
>>
>> Good call, with this workaround on top of patches 1-3, it boots again:
>>
>> ????# mount -t debugfs d /sys/kernel/debug
>> ????# cat /sys/kernel/debug/powerpc/block_address_translation
>> ????---[ Instruction Block Address Translation ]---
>> ????0: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC
>> ????1:???????? -
>> ????2: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC
>> ????3:???????? -
>> ????4: 0xd0000000-0xd1ffffff 0x10000000 Kernel EXEC
>> ????5:???????? -
>> ????6:???????? -
>> ????7:???????? -
>>
>> ????---[ Data Block Address Translation ]---
>> ????0: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW
>> ????1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
>> ????2: 0xc1000000-0xc17fffff 0x01000000 Kernel RW
>> ????3:???????? -
>> ????4: 0xd0000000-0xd1ffffff 0x10000000 Kernel RW
>> ????5:???????? -
>> ????6:???????? -
>> ????7:???????? -
>>
>>> I think we may have some code trying to modify the kernel text
>>> without using
>>> code patching functions.
>>
>> Is there any faster way than to sprinkle some printks in setup_kernel
>> and try to find the guilty piece of code this way?
>
> Can you start with the serie
> https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=75072 ?

Ok, the thing I was thinking about was the MMU_init_hw() but it is
called before mapin_ram() so it should not be a problem. Not sure that
serie improves anything at all here.

So there must be something else, pretty early (before the system is able
to properly handle and display an Oops for write to RO area.)

Does anybody have an idea of what it can be ?

Christophe

>
> Christophe
>
>>
>>
>> Jonathan
>>

2018-12-18 15:07:10

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()



Le 18/12/2018 ? 15:55, Christophe Leroy a ?crit?:
>
>
> Le 18/12/2018 ? 15:15, Christophe Leroy a ?crit?:
>>
>>
>> Le 18/12/2018 ? 15:07, Jonathan Neusch?fer a ?crit?:
>>> On Tue, Dec 18, 2018 at 09:18:42AM +0000, Christophe Leroy wrote:
>>>> The only difference I see then are the flags. Everything else is seems
>>>> identical.
>>>>
>>>> I know you tried already, but would you mind trying once more with the
>>>> following change ?
>>>>
>>> [...]
>>>> -??????? setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
>>>> +??????? setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_X);
>>>
>>> Good call, with this workaround on top of patches 1-3, it boots again:
>>>
>>> ????# mount -t debugfs d /sys/kernel/debug
>>> ????# cat /sys/kernel/debug/powerpc/block_address_translation
>>> ????---[ Instruction Block Address Translation ]---
>>> ????0: 0xc0000000-0xc0ffffff 0x00000000 Kernel EXEC
>>> ????1:???????? -
>>> ????2: 0xc1000000-0xc17fffff 0x01000000 Kernel EXEC
>>> ????3:???????? -
>>> ????4: 0xd0000000-0xd1ffffff 0x10000000 Kernel EXEC
>>> ????5:???????? -
>>> ????6:???????? -
>>> ????7:???????? -
>>>
>>> ????---[ Data Block Address Translation ]---
>>> ????0: 0xc0000000-0xc0ffffff 0x00000000 Kernel RW
>>> ????1: 0xfffe0000-0xffffffff 0x0d000000 Kernel RW no cache guarded
>>> ????2: 0xc1000000-0xc17fffff 0x01000000 Kernel RW
>>> ????3:???????? -
>>> ????4: 0xd0000000-0xd1ffffff 0x10000000 Kernel RW
>>> ????5:???????? -
>>> ????6:???????? -
>>> ????7:???????? -
>>>
>>>> I think we may have some code trying to modify the kernel text
>>>> without using
>>>> code patching functions.
>>>
>>> Is there any faster way than to sprinkle some printks in setup_kernel
>>> and try to find the guilty piece of code this way?
>>
>> Can you start with the serie
>> https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=75072 ?
>
> Ok, the thing I was thinking about was the MMU_init_hw() but it is
> called before mapin_ram() so it should not be a problem. Not sure that
> serie improves anything at all here.
>
> So there must be something else, pretty early (before the system is able
> to properly handle and display an Oops for write to RO area.)
>
> Does anybody have an idea of what it can be ?


Stupid of me. In fact at the time being, BATS cover both RO and RW data
areas, so it can definitly not be mapped with PAGE_KERNEL_ROX.

In fact, as I have CONFIG_BDI_SWITCH in my setup, PAGE_KERNEL_TEXT is
PAGE_KERNEL_X on my side. That's the reason why I missed it.

With this change being done to patch 3, does the overall serie works for
you ?

Thanks
Christophe



>
> Christophe
>
>>
>> Christophe
>>
>>>
>>>
>>> Jonathan
>>>

2018-12-18 17:07:14

by J. Neuschäfer

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

On Tue, Dec 18, 2018 at 04:04:42PM +0100, Christophe Leroy wrote:
> Stupid of me. In fact at the time being, BATS cover both RO and RW data
> areas, so it can definitly not be mapped with PAGE_KERNEL_ROX.
>
> In fact, as I have CONFIG_BDI_SWITCH in my setup, PAGE_KERNEL_TEXT is
> PAGE_KERNEL_X on my side. That's the reason why I missed it.
>
> With this change being done to patch 3, does the overall serie works for you ?

Yes, with the PAGE_KERNEL_X change, the whole series boots on the Wii.


Jonathan


Attachments:
(No filename) (523.00 B)
signature.asc (849.00 B)
Download all attachments

2018-12-18 18:42:31

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH v1 03/13] powerpc/mm/32s: rework mmu_mapin_ram()

Le 18/12/2018 ? 18:04, Jonathan Neusch?fer a ?crit?:
> On Tue, Dec 18, 2018 at 04:04:42PM +0100, Christophe Leroy wrote:
>> Stupid of me. In fact at the time being, BATS cover both RO and RW data
>> areas, so it can definitly not be mapped with PAGE_KERNEL_ROX.
>>
>> In fact, as I have CONFIG_BDI_SWITCH in my setup, PAGE_KERNEL_TEXT is
>> PAGE_KERNEL_X on my side. That's the reason why I missed it.
>>
>> With this change being done to patch 3, does the overall serie works for you ?
>
> Yes, with the PAGE_KERNEL_X change, the whole series boots on the Wii.

That's great, many thanks for testing.

Christophe

>
>
> Jonathan
>