LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 11/11] powerpc/code-patching: Replace patch_instruction() by ppc_inst_write() in selftests
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

The purpose of selftests is to check that instructions are
properly formed. Not to check that they properly run.

For that test it uses normal memory, not special test
memory.

In preparation of a future patch enforcing patch_instruction()
to be used only on valid text areas, implement a ppc_inst_write()
instruction which is the complement of ppc_inst_read(). This
new function writes the formated instruction in valid kernel
memory and doesn't bother about icache.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/include/asm/inst.h       |  8 +++
 arch/powerpc/lib/test-code-patching.c | 85 ++++++++++++++-------------
 2 files changed, 53 insertions(+), 40 deletions(-)

diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 631436f3f5c3..21fe8594e078 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -131,6 +131,14 @@ static inline unsigned long ppc_inst_as_ulong(ppc_inst_t x)
 		return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x);
 }
 
+static inline void ppc_inst_write(u32 *ptr, ppc_inst_t x)
+{
+	if (!ppc_inst_prefixed(x))
+		*ptr = ppc_inst_val(x);
+	else
+		*(u64 *)ptr = ppc_inst_as_ulong(x);
+}
+
 #define PPC_INST_STR_LEN sizeof("00000000 00000000")
 
 static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], ppc_inst_t x)
diff --git a/arch/powerpc/lib/test-code-patching.c b/arch/powerpc/lib/test-code-patching.c
index e358c9d8a03e..c44823292f73 100644
--- a/arch/powerpc/lib/test-code-patching.c
+++ b/arch/powerpc/lib/test-code-patching.c
@@ -54,39 +54,39 @@ static void __init test_branch_iform(void)
 	check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
 
 	/* Absolute branch to 0x100 */
-	patch_instruction(iptr, ppc_inst(0x48000103));
+	ppc_inst_write(iptr, ppc_inst(0x48000103));
 	check(instr_is_branch_to_addr(iptr, 0x100));
 	/* Absolute branch to 0x420fc */
-	patch_instruction(iptr, ppc_inst(0x480420ff));
+	ppc_inst_write(iptr, ppc_inst(0x480420ff));
 	check(instr_is_branch_to_addr(iptr, 0x420fc));
 	/* Maximum positive relative branch, + 20MB - 4B */
-	patch_instruction(iptr, ppc_inst(0x49fffffc));
+	ppc_inst_write(iptr, ppc_inst(0x49fffffc));
 	check(instr_is_branch_to_addr(iptr, addr + 0x1FFFFFC));
 	/* Smallest negative relative branch, - 4B */
-	patch_instruction(iptr, ppc_inst(0x4bfffffc));
+	ppc_inst_write(iptr, ppc_inst(0x4bfffffc));
 	check(instr_is_branch_to_addr(iptr, addr - 4));
 	/* Largest negative relative branch, - 32 MB */
-	patch_instruction(iptr, ppc_inst(0x4a000000));
+	ppc_inst_write(iptr, ppc_inst(0x4a000000));
 	check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
 
 	/* Branch to self, with link */
 	err = create_branch(&instr, iptr, addr, BRANCH_SET_LINK);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr));
 
 	/* Branch to self - 0x100, with link */
 	err = create_branch(&instr, iptr, addr - 0x100, BRANCH_SET_LINK);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr - 0x100));
 
 	/* Branch to self + 0x100, no link */
 	err = create_branch(&instr, iptr, addr + 0x100, 0);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr + 0x100));
 
 	/* Maximum relative negative offset, - 32 MB */
 	err = create_branch(&instr, iptr, addr - 0x2000000, BRANCH_SET_LINK);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
 
 	/* Out of range relative negative offset, - 32 MB + 4*/
@@ -103,7 +103,7 @@ static void __init test_branch_iform(void)
 
 	/* Check flags are masked correctly */
 	err = create_branch(&instr, iptr, addr, 0xFFFFFFFC);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr));
 	check(ppc_inst_equal(instr, ppc_inst(0x48000000)));
 }
@@ -143,19 +143,19 @@ static void __init test_branch_bform(void)
 	check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
 
 	/* Absolute conditional branch to 0x100 */
-	patch_instruction(iptr, ppc_inst(0x43ff0103));
+	ppc_inst_write(iptr, ppc_inst(0x43ff0103));
 	check(instr_is_branch_to_addr(iptr, 0x100));
 	/* Absolute conditional branch to 0x20fc */
-	patch_instruction(iptr, ppc_inst(0x43ff20ff));
+	ppc_inst_write(iptr, ppc_inst(0x43ff20ff));
 	check(instr_is_branch_to_addr(iptr, 0x20fc));
 	/* Maximum positive relative conditional branch, + 32 KB - 4B */
-	patch_instruction(iptr, ppc_inst(0x43ff7ffc));
+	ppc_inst_write(iptr, ppc_inst(0x43ff7ffc));
 	check(instr_is_branch_to_addr(iptr, addr + 0x7FFC));
 	/* Smallest negative relative conditional branch, - 4B */
-	patch_instruction(iptr, ppc_inst(0x43fffffc));
+	ppc_inst_write(iptr, ppc_inst(0x43fffffc));
 	check(instr_is_branch_to_addr(iptr, addr - 4));
 	/* Largest negative relative conditional branch, - 32 KB */
-	patch_instruction(iptr, ppc_inst(0x43ff8000));
+	ppc_inst_write(iptr, ppc_inst(0x43ff8000));
 	check(instr_is_branch_to_addr(iptr, addr - 0x8000));
 
 	/* All condition code bits set & link */
@@ -163,22 +163,22 @@ static void __init test_branch_bform(void)
 
 	/* Branch to self */
 	err = create_cond_branch(&instr, iptr, addr, flags);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr));
 
 	/* Branch to self - 0x100 */
 	err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr - 0x100));
 
 	/* Branch to self + 0x100 */
 	err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr + 0x100));
 
 	/* Maximum relative negative offset, - 32 KB */
 	err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr - 0x8000));
 
 	/* Out of range relative negative offset, - 32 KB + 4*/
@@ -195,7 +195,7 @@ static void __init test_branch_bform(void)
 
 	/* Check flags are masked correctly */
 	err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
-	patch_instruction(iptr, instr);
+	ppc_inst_write(iptr, instr);
 	check(instr_is_branch_to_addr(iptr, addr));
 	check(ppc_inst_equal(instr, ppc_inst(0x43FF0000)));
 }
@@ -215,20 +215,22 @@ static void __init test_translate_branch(void)
 	/* Simple case, branch to self moved a little */
 	p = buf;
 	addr = (unsigned long)p;
-	patch_branch(p, addr, 0);
+	create_branch(&instr, p, addr, 0);
+	ppc_inst_write(p, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	q = p + 4;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(q, addr));
 
 	/* Maximum negative case, move b . to addr + 32 MB */
 	p = buf;
 	addr = (unsigned long)p;
-	patch_branch(p, addr, 0);
+	create_branch(&instr, p, addr, 0);
+	ppc_inst_write(p, instr);
 	q = buf + 0x2000000;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	check(instr_is_branch_to_addr(q, addr));
 	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x4a000000)));
@@ -236,10 +238,11 @@ static void __init test_translate_branch(void)
 	/* Maximum positive case, move x to x - 32 MB + 4 */
 	p = buf + 0x2000000;
 	addr = (unsigned long)p;
-	patch_branch(p, addr, 0);
+	create_branch(&instr, p, addr, 0);
+	ppc_inst_write(p, instr);
 	q = buf + 4;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	check(instr_is_branch_to_addr(q, addr));
 	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x49fffffc)));
@@ -247,20 +250,22 @@ static void __init test_translate_branch(void)
 	/* Jump to x + 16 MB moved to x + 20 MB */
 	p = buf;
 	addr = 0x1000000 + (unsigned long)buf;
-	patch_branch(p, addr, BRANCH_SET_LINK);
+	create_branch(&instr, p, addr, BRANCH_SET_LINK);
+	ppc_inst_write(p, instr);
 	q = buf + 0x1400000;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	check(instr_is_branch_to_addr(q, addr));
 
 	/* Jump to x + 16 MB moved to x - 16 MB + 4 */
 	p = buf + 0x1000000;
 	addr = 0x2000000 + (unsigned long)buf;
-	patch_branch(p, addr, 0);
+	create_branch(&instr, p, addr, 0);
+	ppc_inst_write(p, instr);
 	q = buf + 4;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	check(instr_is_branch_to_addr(q, addr));
 
@@ -271,21 +276,21 @@ static void __init test_translate_branch(void)
 	p = buf;
 	addr = (unsigned long)p;
 	create_cond_branch(&instr, p, addr, 0);
-	patch_instruction(p, instr);
+	ppc_inst_write(p, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	q = buf + 4;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(q, addr));
 
 	/* Maximum negative case, move b . to addr + 32 KB */
 	p = buf;
 	addr = (unsigned long)p;
 	create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
-	patch_instruction(p, instr);
+	ppc_inst_write(p, instr);
 	q = buf + 0x8000;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	check(instr_is_branch_to_addr(q, addr));
 	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff8000)));
@@ -294,10 +299,10 @@ static void __init test_translate_branch(void)
 	p = buf + 0x8000;
 	addr = (unsigned long)p;
 	create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
-	patch_instruction(p, instr);
+	ppc_inst_write(p, instr);
 	q = buf + 4;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	check(instr_is_branch_to_addr(q, addr));
 	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff7ffc)));
@@ -306,10 +311,10 @@ static void __init test_translate_branch(void)
 	p = buf;
 	addr = 0x3000 + (unsigned long)buf;
 	create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
-	patch_instruction(p, instr);
+	ppc_inst_write(p, instr);
 	q = buf + 0x5000;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	check(instr_is_branch_to_addr(q, addr));
 
@@ -317,10 +322,10 @@ static void __init test_translate_branch(void)
 	p = buf + 0x2000;
 	addr = 0x4000 + (unsigned long)buf;
 	create_cond_branch(&instr, p, addr, 0);
-	patch_instruction(p, instr);
+	ppc_inst_write(p, instr);
 	q = buf + 4;
 	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
+	ppc_inst_write(q, instr);
 	check(instr_is_branch_to_addr(p, addr));
 	check(instr_is_branch_to_addr(q, addr));
 
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 04/11] powerpc/code-patching: Fix unmap_patch_area() error handling
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

pXd_offset() doesn't return NULL. When the base is NULL, it
still adds the offset.

Use pXd_none() to check validity instead. It also improves
performance by folding out none existing levels as pXd_none()
always returns 0 in that case.

Such an error is unexpected, use WARN_ON() so that the caller
doesn't have to worry about it, and drop the returned value.

And now that unmap_patch_area() doesn't return error, we can
take into account the error returned by __patch_instruction().

While at it, remove the 'inline' property which is useless.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/lib/code-patching.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 4ce2b6457757..5fa719a4ee69 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -94,7 +94,7 @@ static int map_patch_area(void *addr, unsigned long text_poke_addr)
 	return map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
 }
 
-static inline int unmap_patch_area(unsigned long addr)
+static void unmap_patch_area(unsigned long addr)
 {
 	pte_t *ptep;
 	pmd_t *pmdp;
@@ -103,32 +103,30 @@ static inline int unmap_patch_area(unsigned long addr)
 	pgd_t *pgdp;
 
 	pgdp = pgd_offset_k(addr);
-	if (unlikely(!pgdp))
-		return -EINVAL;
+	if (WARN_ON(pgd_none(*pgdp)))
+		return;
 
 	p4dp = p4d_offset(pgdp, addr);
-	if (unlikely(!p4dp))
-		return -EINVAL;
+	if (WARN_ON(p4d_none(*p4dp)))
+		return;
 
 	pudp = pud_offset(p4dp, addr);
-	if (unlikely(!pudp))
-		return -EINVAL;
+	if (WARN_ON(pud_none(*pudp)))
+		return;
 
 	pmdp = pmd_offset(pudp, addr);
-	if (unlikely(!pmdp))
-		return -EINVAL;
+	if (WARN_ON(pmd_none(*pmdp)))
+		return;
 
 	ptep = pte_offset_kernel(pmdp, addr);
-	if (unlikely(!ptep))
-		return -EINVAL;
+	if (WARN_ON(pte_none(*ptep)))
+		return;
 
 	/*
 	 * In hash, pte_clear flushes the tlb, in radix, we have to
 	 */
 	pte_clear(&init_mm, addr, ptep);
 	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
-
-	return 0;
 }
 
 static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
@@ -156,11 +154,9 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 
 	patch_addr = (u32 *)(text_poke_addr + (kaddr & ~PAGE_MASK));
 
-	__patch_instruction(addr, instr, patch_addr);
+	err = __patch_instruction(addr, instr, patch_addr);
 
-	err = unmap_patch_area(text_poke_addr);
-	if (err)
-		pr_warn("failed to unmap %lx\n", text_poke_addr);
+	unmap_patch_area(text_poke_addr);
 
 out:
 	local_irq_restore(flags);
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 03/11] powerpc/code-patching: Fix error handling in do_patch_instruction()
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

Use real errors instead of using -1 as error, so that errors
returned by callees can be used towards callers.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/lib/code-patching.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 7bb8dd2dc19e..4ce2b6457757 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -85,19 +85,13 @@ void __init poking_init(void)
 static int map_patch_area(void *addr, unsigned long text_poke_addr)
 {
 	unsigned long pfn;
-	int err;
 
 	if (is_vmalloc_or_module_addr(addr))
 		pfn = vmalloc_to_pfn(addr);
 	else
 		pfn = __pa_symbol(addr) >> PAGE_SHIFT;
 
-	err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
-
-	if (err)
-		return -1;
-
-	return 0;
+	return map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
 }
 
 static inline int unmap_patch_area(unsigned long addr)
@@ -156,10 +150,9 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 	local_irq_save(flags);
 
 	text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr;
-	if (map_patch_area(addr, text_poke_addr)) {
-		err = -1;
+	err = map_patch_area(addr, text_poke_addr);
+	if (err)
 		goto out;
-	}
 
 	patch_addr = (u32 *)(text_poke_addr + (kaddr & ~PAGE_MASK));
 
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 06/11] powerpc/code-patching: Fix patch_branch() return on out-of-range failure
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

Do not silentely ignore a failure of create_branch() in
patch_branch(). Return -ERANGE.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/lib/code-patching.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index a43ca22313ee..e7a2a41ae8eb 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -191,7 +191,9 @@ int patch_branch(u32 *addr, unsigned long target, int flags)
 {
 	ppc_inst_t instr;
 
-	create_branch(&instr, addr, target, flags);
+	if (create_branch(&instr, addr, target, flags))
+		return -ERANGE;
+
 	return patch_instruction(addr, instr);
 }
 
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 02/11] powerpc/code-patching: Remove init_mem_is_free
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

A new state has been added by commit d2635f2012a4 ("mm: create a new
system state and fix core_kernel_text()"). That state tells when
initmem is about to be released and is redundant with init_mem_is_free.

Remove init_mem_is_free.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/include/asm/setup.h | 1 -
 arch/powerpc/lib/code-patching.c | 3 +--
 arch/powerpc/mm/mem.c            | 2 --
 3 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index 6c1a7d217d1a..426a2d8d028f 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -9,7 +9,6 @@ extern void ppc_printk_progress(char *s, unsigned short hex);
 
 extern unsigned int rtas_data;
 extern unsigned long long memory_limit;
-extern bool init_mem_is_free;
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
 struct device_node;
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 4fe4464b7a84..7bb8dd2dc19e 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -15,7 +15,6 @@
 #include <asm/tlbflush.h>
 #include <asm/page.h>
 #include <asm/code-patching.h>
-#include <asm/setup.h>
 #include <asm/inst.h>
 
 static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr)
@@ -187,7 +186,7 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 int patch_instruction(u32 *addr, ppc_inst_t instr)
 {
 	/* Make sure we aren't patching a freed init section */
-	if (init_mem_is_free && init_section_contains(addr, 4))
+	if (system_state >= SYSTEM_FREEING_INITMEM && init_section_contains(addr, 4))
 		return 0;
 
 	return do_patch_instruction(addr, instr);
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index bd5d91a31183..8e301cd8925b 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -26,7 +26,6 @@
 #include <mm/mmu_decl.h>
 
 unsigned long long memory_limit;
-bool init_mem_is_free;
 
 unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss;
 EXPORT_SYMBOL(empty_zero_page);
@@ -312,7 +311,6 @@ void free_initmem(void)
 {
 	ppc_md.progress = ppc_printk_progress;
 	mark_initmem_nx();
-	init_mem_is_free = true;
 	free_initmem_default(POISON_FREE_INITMEM);
 }
 
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 01/11] powerpc/code-patching: Remove pr_debug()/pr_devel() messages and fix check()
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel

code-patching has been working for years now, time has come to
remove debugging messages.

Change useful message to KERN_INFO and remove other ones.

Also add KERN_ERR to check() macro and change it into a do/while
to make checkpatch happy.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
This series applies on top of series "[v5,1/5] powerpc/inst: Refactor ___get_user_instr()" https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=274258

 arch/powerpc/lib/code-patching.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 312324a26df3..4fe4464b7a84 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -95,7 +95,6 @@ static int map_patch_area(void *addr, unsigned long text_poke_addr)
 
 	err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
 
-	pr_devel("Mapped addr %lx with pfn %lx:%d\n", text_poke_addr, pfn, err);
 	if (err)
 		return -1;
 
@@ -130,8 +129,6 @@ static inline int unmap_patch_area(unsigned long addr)
 	if (unlikely(!ptep))
 		return -EINVAL;
 
-	pr_devel("clearing mm %p, pte %p, addr %lx\n", &init_mm, ptep, addr);
-
 	/*
 	 * In hash, pte_clear flushes the tlb, in radix, we have to
 	 */
@@ -190,10 +187,9 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 int patch_instruction(u32 *addr, ppc_inst_t instr)
 {
 	/* Make sure we aren't patching a freed init section */
-	if (init_mem_is_free && init_section_contains(addr, 4)) {
-		pr_debug("Skipping init section patching addr: 0x%px\n", addr);
+	if (init_mem_is_free && init_section_contains(addr, 4))
 		return 0;
-	}
+
 	return do_patch_instruction(addr, instr);
 }
 NOKPROBE_SYMBOL(patch_instruction);
@@ -411,8 +407,10 @@ static void __init test_trampoline(void)
 	asm ("nop;\n");
 }
 
-#define check(x)	\
-	if (!(x)) printk("code-patching: test failed at line %d\n", __LINE__);
+#define check(x)	do {	\
+	if (!(x))		\
+		pr_err("code-patching: test failed at line %d\n", __LINE__); \
+} while (0)
 
 static void __init test_branch_iform(void)
 {
@@ -737,7 +735,7 @@ static inline void test_prefixed_patching(void) {}
 
 static int __init test_code_patching(void)
 {
-	printk(KERN_DEBUG "Running code patching self-tests ...\n");
+	pr_info("Running code patching self-tests ...\n");
 
 	test_branch_iform();
 	test_branch_bform();
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 07/11] powerpc/code-patching: Use test_trampoline for prefixed patch test
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

Use the dedicated test_trampoline function for testing prefixed
patching like other tests and remove the hand coded assembly stuff.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/lib/Makefile             |  2 +-
 arch/powerpc/lib/code-patching.c      | 24 +++++++++---------------
 arch/powerpc/lib/test_code-patching.S | 20 --------------------
 3 files changed, 10 insertions(+), 36 deletions(-)
 delete mode 100644 arch/powerpc/lib/test_code-patching.S

diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 9e5d0f413b71..c2654894b468 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -19,7 +19,7 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING
 CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING
 endif
 
-obj-y += alloc.o code-patching.o feature-fixups.o pmem.o test_code-patching.o
+obj-y += alloc.o code-patching.o feature-fixups.o pmem.o
 
 ifndef CONFIG_KASAN
 obj-y	+=	string.o memcmp_$(BITS).o
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index e7a2a41ae8eb..2d878e67df3f 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -399,7 +399,7 @@ static int instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
 
 static void __init test_trampoline(void)
 {
-	asm ("nop;\n");
+	asm ("nop;nop;\n");
 }
 
 #define check(x)	do {	\
@@ -708,25 +708,19 @@ static void __init test_translate_branch(void)
 	vfree(buf);
 }
 
-#ifdef CONFIG_PPC64
 static void __init test_prefixed_patching(void)
 {
-	extern unsigned int code_patching_test1[];
-	extern unsigned int code_patching_test1_expected[];
-	extern unsigned int end_code_patching_test1[];
+	u32 *iptr = (u32 *)ppc_function_entry(test_trampoline);
+	u32 expected[2] = {OP_PREFIX << 26, 0};
+	ppc_inst_t inst = ppc_inst_prefix(OP_PREFIX << 26, 0);
 
-	__patch_instruction(code_patching_test1,
-			    ppc_inst_prefix(OP_PREFIX << 26, 0x00000000),
-			    code_patching_test1);
+	if (!IS_ENABLED(CONFIG_PPC64))
+		return;
+
+	patch_instruction(iptr, inst);
 
-	check(!memcmp(code_patching_test1,
-		      code_patching_test1_expected,
-		      sizeof(unsigned int) *
-		      (end_code_patching_test1 - code_patching_test1)));
+	check(!memcmp(iptr, expected, sizeof(expected)));
 }
-#else
-static inline void test_prefixed_patching(void) {}
-#endif
 
 static int __init test_code_patching(void)
 {
diff --git a/arch/powerpc/lib/test_code-patching.S b/arch/powerpc/lib/test_code-patching.S
deleted file mode 100644
index a9be6107844e..000000000000
--- a/arch/powerpc/lib/test_code-patching.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2020 IBM Corporation
- */
-#include <asm/ppc-opcode.h>
-
-	.text
-
-#define globl(x)		\
-	.globl x;	\
-x:
-
-globl(code_patching_test1)
-	nop
-	nop
-globl(end_code_patching_test1)
-
-globl(code_patching_test1_expected)
-	.long OP_PREFIX << 26
-	.long 0x0000000
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 05/11] powerpc/code-patching: Reorganise do_patch_instruction() to ease error handling
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

Split do_patch_instruction() in two functions, the caller doing the
spin locking and the callee doing everything else.

And remove a few unnecessary initialisations and intermediate
variables.

This allows the callee to return from anywhere in the function.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/lib/code-patching.c | 37 ++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 5fa719a4ee69..a43ca22313ee 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -129,13 +129,30 @@ static void unmap_patch_area(unsigned long addr)
 	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
 }
 
+static int __do_patch_instruction(u32 *addr, ppc_inst_t instr)
+{
+	int err;
+	u32 *patch_addr;
+	unsigned long text_poke_addr;
+
+	text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr;
+	patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
+
+	err = map_patch_area(addr, text_poke_addr);
+	if (err)
+		return err;
+
+	err = __patch_instruction(addr, instr, patch_addr);
+
+	unmap_patch_area(text_poke_addr);
+
+	return err;
+}
+
 static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 {
 	int err;
-	u32 *patch_addr = NULL;
 	unsigned long flags;
-	unsigned long text_poke_addr;
-	unsigned long kaddr = (unsigned long)addr;
 
 	/*
 	 * During early early boot patch_instruction is called
@@ -146,19 +163,7 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
 		return raw_patch_instruction(addr, instr);
 
 	local_irq_save(flags);
-
-	text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr;
-	err = map_patch_area(addr, text_poke_addr);
-	if (err)
-		goto out;
-
-	patch_addr = (u32 *)(text_poke_addr + (kaddr & ~PAGE_MASK));
-
-	err = __patch_instruction(addr, instr, patch_addr);
-
-	unmap_patch_area(text_poke_addr);
-
-out:
+	err = __do_patch_instruction(addr, instr);
 	local_irq_restore(flags);
 
 	return err;
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 09/11] powerpc/code-patching: Move instr_is_branch_{i/b}form() in code-patching.h
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

To enable moving selftests in their own C file in following patch,
move instr_is_branch_iform() and instr_is_branch_bform()
to code-patching.h

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/include/asm/code-patching.h | 15 +++++++++++++++
 arch/powerpc/lib/code-patching.c         | 15 ---------------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 275061c3c977..e26080539c31 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -58,6 +58,21 @@ static inline int modify_instruction_site(s32 *site, unsigned int clr, unsigned
 	return modify_instruction((unsigned int *)patch_site_addr(site), clr, set);
 }
 
+static inline unsigned int branch_opcode(ppc_inst_t instr)
+{
+	return ppc_inst_primary_opcode(instr) & 0x3F;
+}
+
+static inline int instr_is_branch_iform(ppc_inst_t instr)
+{
+	return branch_opcode(instr) == 18;
+}
+
+static inline int instr_is_branch_bform(ppc_inst_t instr)
+{
+	return branch_opcode(instr) == 16;
+}
+
 int instr_is_relative_branch(ppc_inst_t instr);
 int instr_is_relative_link_branch(ppc_inst_t instr);
 unsigned long branch_target(const u32 *instr);
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 17e6443eb6c8..e07de5db06c0 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -285,21 +285,6 @@ int create_cond_branch(ppc_inst_t *instr, const u32 *addr,
 	return 0;
 }
 
-static unsigned int branch_opcode(ppc_inst_t instr)
-{
-	return ppc_inst_primary_opcode(instr) & 0x3F;
-}
-
-static int instr_is_branch_iform(ppc_inst_t instr)
-{
-	return branch_opcode(instr) == 18;
-}
-
-static int instr_is_branch_bform(ppc_inst_t instr)
-{
-	return branch_opcode(instr) == 16;
-}
-
 int instr_is_relative_branch(ppc_inst_t instr)
 {
 	if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 10/11] powerpc/code-patching: Move code patching selftests in its own file
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

Code patching selftests are half of code-patching.c.
As they are guarded by CONFIG_CODE_PATCHING_SELFTESTS,
they'd be better in their own file.

Also add a missing __init for instr_is_branch_to_addr()

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/lib/Makefile                     |   2 +
 arch/powerpc/lib/code-patching.c              | 355 ------------------
 .../{code-patching.c => test-code-patching.c} | 353 +----------------
 3 files changed, 3 insertions(+), 707 deletions(-)
 copy arch/powerpc/lib/{code-patching.c => test-code-patching.c} (56%)

diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index c2654894b468..3e183f4b4bda 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -21,6 +21,8 @@ endif
 
 obj-y += alloc.o code-patching.o feature-fixups.o pmem.o
 
+obj-$(CONFIG_CODE_PATCHING_SELFTEST) += test-code-patching.o
+
 ifndef CONFIG_KASAN
 obj-y	+=	string.o memcmp_$(BITS).o
 obj-$(CONFIG_PPC32)	+= strlen_32.o
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index e07de5db06c0..906d43463366 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -3,13 +3,10 @@
  *  Copyright 2008 Michael Ellerman, IBM Corporation.
  */
 
-#include <linux/kernel.h>
 #include <linux/kprobes.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <linux/mm.h>
 #include <linux/cpuhotplug.h>
-#include <linux/slab.h>
 #include <linux/uaccess.h>
 
 #include <asm/tlbflush.h>
@@ -354,355 +351,3 @@ int translate_branch(ppc_inst_t *instr, const u32 *dest, const u32 *src)
 
 	return 1;
 }
-
-#ifdef CONFIG_CODE_PATCHING_SELFTEST
-
-static int instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
-{
-	if (instr_is_branch_iform(ppc_inst_read(instr)) ||
-	    instr_is_branch_bform(ppc_inst_read(instr)))
-		return branch_target(instr) == addr;
-
-	return 0;
-}
-
-static void __init test_trampoline(void)
-{
-	asm ("nop;nop;\n");
-}
-
-#define check(x)	do {	\
-	if (!(x))		\
-		pr_err("code-patching: test failed at line %d\n", __LINE__); \
-} while (0)
-
-static void __init test_branch_iform(void)
-{
-	int err;
-	ppc_inst_t instr;
-	u32 tmp[2];
-	u32 *iptr = tmp;
-	unsigned long addr = (unsigned long)tmp;
-
-	/* The simplest case, branch to self, no flags */
-	check(instr_is_branch_iform(ppc_inst(0x48000000)));
-	/* All bits of target set, and flags */
-	check(instr_is_branch_iform(ppc_inst(0x4bffffff)));
-	/* High bit of opcode set, which is wrong */
-	check(!instr_is_branch_iform(ppc_inst(0xcbffffff)));
-	/* Middle bits of opcode set, which is wrong */
-	check(!instr_is_branch_iform(ppc_inst(0x7bffffff)));
-
-	/* Simplest case, branch to self with link */
-	check(instr_is_branch_iform(ppc_inst(0x48000001)));
-	/* All bits of targets set */
-	check(instr_is_branch_iform(ppc_inst(0x4bfffffd)));
-	/* Some bits of targets set */
-	check(instr_is_branch_iform(ppc_inst(0x4bff00fd)));
-	/* Must be a valid branch to start with */
-	check(!instr_is_branch_iform(ppc_inst(0x7bfffffd)));
-
-	/* Absolute branch to 0x100 */
-	patch_instruction(iptr, ppc_inst(0x48000103));
-	check(instr_is_branch_to_addr(iptr, 0x100));
-	/* Absolute branch to 0x420fc */
-	patch_instruction(iptr, ppc_inst(0x480420ff));
-	check(instr_is_branch_to_addr(iptr, 0x420fc));
-	/* Maximum positive relative branch, + 20MB - 4B */
-	patch_instruction(iptr, ppc_inst(0x49fffffc));
-	check(instr_is_branch_to_addr(iptr, addr + 0x1FFFFFC));
-	/* Smallest negative relative branch, - 4B */
-	patch_instruction(iptr, ppc_inst(0x4bfffffc));
-	check(instr_is_branch_to_addr(iptr, addr - 4));
-	/* Largest negative relative branch, - 32 MB */
-	patch_instruction(iptr, ppc_inst(0x4a000000));
-	check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
-
-	/* Branch to self, with link */
-	err = create_branch(&instr, iptr, addr, BRANCH_SET_LINK);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr));
-
-	/* Branch to self - 0x100, with link */
-	err = create_branch(&instr, iptr, addr - 0x100, BRANCH_SET_LINK);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr - 0x100));
-
-	/* Branch to self + 0x100, no link */
-	err = create_branch(&instr, iptr, addr + 0x100, 0);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr + 0x100));
-
-	/* Maximum relative negative offset, - 32 MB */
-	err = create_branch(&instr, iptr, addr - 0x2000000, BRANCH_SET_LINK);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr - 0x2000000));
-
-	/* Out of range relative negative offset, - 32 MB + 4*/
-	err = create_branch(&instr, iptr, addr - 0x2000004, BRANCH_SET_LINK);
-	check(err);
-
-	/* Out of range relative positive offset, + 32 MB */
-	err = create_branch(&instr, iptr, addr + 0x2000000, BRANCH_SET_LINK);
-	check(err);
-
-	/* Unaligned target */
-	err = create_branch(&instr, iptr, addr + 3, BRANCH_SET_LINK);
-	check(err);
-
-	/* Check flags are masked correctly */
-	err = create_branch(&instr, iptr, addr, 0xFFFFFFFC);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr));
-	check(ppc_inst_equal(instr, ppc_inst(0x48000000)));
-}
-
-static void __init test_create_function_call(void)
-{
-	u32 *iptr;
-	unsigned long dest;
-	ppc_inst_t instr;
-
-	/* Check we can create a function call */
-	iptr = (u32 *)ppc_function_entry(test_trampoline);
-	dest = ppc_function_entry(test_create_function_call);
-	create_branch(&instr, iptr, dest, BRANCH_SET_LINK);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, dest));
-}
-
-static void __init test_branch_bform(void)
-{
-	int err;
-	unsigned long addr;
-	ppc_inst_t instr;
-	u32 tmp[2];
-	u32 *iptr = tmp;
-	unsigned int flags;
-
-	addr = (unsigned long)iptr;
-
-	/* The simplest case, branch to self, no flags */
-	check(instr_is_branch_bform(ppc_inst(0x40000000)));
-	/* All bits of target set, and flags */
-	check(instr_is_branch_bform(ppc_inst(0x43ffffff)));
-	/* High bit of opcode set, which is wrong */
-	check(!instr_is_branch_bform(ppc_inst(0xc3ffffff)));
-	/* Middle bits of opcode set, which is wrong */
-	check(!instr_is_branch_bform(ppc_inst(0x7bffffff)));
-
-	/* Absolute conditional branch to 0x100 */
-	patch_instruction(iptr, ppc_inst(0x43ff0103));
-	check(instr_is_branch_to_addr(iptr, 0x100));
-	/* Absolute conditional branch to 0x20fc */
-	patch_instruction(iptr, ppc_inst(0x43ff20ff));
-	check(instr_is_branch_to_addr(iptr, 0x20fc));
-	/* Maximum positive relative conditional branch, + 32 KB - 4B */
-	patch_instruction(iptr, ppc_inst(0x43ff7ffc));
-	check(instr_is_branch_to_addr(iptr, addr + 0x7FFC));
-	/* Smallest negative relative conditional branch, - 4B */
-	patch_instruction(iptr, ppc_inst(0x43fffffc));
-	check(instr_is_branch_to_addr(iptr, addr - 4));
-	/* Largest negative relative conditional branch, - 32 KB */
-	patch_instruction(iptr, ppc_inst(0x43ff8000));
-	check(instr_is_branch_to_addr(iptr, addr - 0x8000));
-
-	/* All condition code bits set & link */
-	flags = 0x3ff000 | BRANCH_SET_LINK;
-
-	/* Branch to self */
-	err = create_cond_branch(&instr, iptr, addr, flags);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr));
-
-	/* Branch to self - 0x100 */
-	err = create_cond_branch(&instr, iptr, addr - 0x100, flags);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr - 0x100));
-
-	/* Branch to self + 0x100 */
-	err = create_cond_branch(&instr, iptr, addr + 0x100, flags);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr + 0x100));
-
-	/* Maximum relative negative offset, - 32 KB */
-	err = create_cond_branch(&instr, iptr, addr - 0x8000, flags);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr - 0x8000));
-
-	/* Out of range relative negative offset, - 32 KB + 4*/
-	err = create_cond_branch(&instr, iptr, addr - 0x8004, flags);
-	check(err);
-
-	/* Out of range relative positive offset, + 32 KB */
-	err = create_cond_branch(&instr, iptr, addr + 0x8000, flags);
-	check(err);
-
-	/* Unaligned target */
-	err = create_cond_branch(&instr, iptr, addr + 3, flags);
-	check(err);
-
-	/* Check flags are masked correctly */
-	err = create_cond_branch(&instr, iptr, addr, 0xFFFFFFFC);
-	patch_instruction(iptr, instr);
-	check(instr_is_branch_to_addr(iptr, addr));
-	check(ppc_inst_equal(instr, ppc_inst(0x43FF0000)));
-}
-
-static void __init test_translate_branch(void)
-{
-	unsigned long addr;
-	void *p, *q;
-	ppc_inst_t instr;
-	void *buf;
-
-	buf = vmalloc(PAGE_ALIGN(0x2000000 + 1));
-	check(buf);
-	if (!buf)
-		return;
-
-	/* Simple case, branch to self moved a little */
-	p = buf;
-	addr = (unsigned long)p;
-	patch_branch(p, addr, 0);
-	check(instr_is_branch_to_addr(p, addr));
-	q = p + 4;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(q, addr));
-
-	/* Maximum negative case, move b . to addr + 32 MB */
-	p = buf;
-	addr = (unsigned long)p;
-	patch_branch(p, addr, 0);
-	q = buf + 0x2000000;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	check(instr_is_branch_to_addr(q, addr));
-	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x4a000000)));
-
-	/* Maximum positive case, move x to x - 32 MB + 4 */
-	p = buf + 0x2000000;
-	addr = (unsigned long)p;
-	patch_branch(p, addr, 0);
-	q = buf + 4;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	check(instr_is_branch_to_addr(q, addr));
-	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x49fffffc)));
-
-	/* Jump to x + 16 MB moved to x + 20 MB */
-	p = buf;
-	addr = 0x1000000 + (unsigned long)buf;
-	patch_branch(p, addr, BRANCH_SET_LINK);
-	q = buf + 0x1400000;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	check(instr_is_branch_to_addr(q, addr));
-
-	/* Jump to x + 16 MB moved to x - 16 MB + 4 */
-	p = buf + 0x1000000;
-	addr = 0x2000000 + (unsigned long)buf;
-	patch_branch(p, addr, 0);
-	q = buf + 4;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	check(instr_is_branch_to_addr(q, addr));
-
-
-	/* Conditional branch tests */
-
-	/* Simple case, branch to self moved a little */
-	p = buf;
-	addr = (unsigned long)p;
-	create_cond_branch(&instr, p, addr, 0);
-	patch_instruction(p, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	q = buf + 4;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(q, addr));
-
-	/* Maximum negative case, move b . to addr + 32 KB */
-	p = buf;
-	addr = (unsigned long)p;
-	create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
-	patch_instruction(p, instr);
-	q = buf + 0x8000;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	check(instr_is_branch_to_addr(q, addr));
-	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff8000)));
-
-	/* Maximum positive case, move x to x - 32 KB + 4 */
-	p = buf + 0x8000;
-	addr = (unsigned long)p;
-	create_cond_branch(&instr, p, addr, 0xFFFFFFFC);
-	patch_instruction(p, instr);
-	q = buf + 4;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	check(instr_is_branch_to_addr(q, addr));
-	check(ppc_inst_equal(ppc_inst_read(q), ppc_inst(0x43ff7ffc)));
-
-	/* Jump to x + 12 KB moved to x + 20 KB */
-	p = buf;
-	addr = 0x3000 + (unsigned long)buf;
-	create_cond_branch(&instr, p, addr, BRANCH_SET_LINK);
-	patch_instruction(p, instr);
-	q = buf + 0x5000;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	check(instr_is_branch_to_addr(q, addr));
-
-	/* Jump to x + 8 KB moved to x - 8 KB + 4 */
-	p = buf + 0x2000;
-	addr = 0x4000 + (unsigned long)buf;
-	create_cond_branch(&instr, p, addr, 0);
-	patch_instruction(p, instr);
-	q = buf + 4;
-	translate_branch(&instr, q, p);
-	patch_instruction(q, instr);
-	check(instr_is_branch_to_addr(p, addr));
-	check(instr_is_branch_to_addr(q, addr));
-
-	/* Free the buffer we were using */
-	vfree(buf);
-}
-
-static void __init test_prefixed_patching(void)
-{
-	u32 *iptr = (u32 *)ppc_function_entry(test_trampoline);
-	u32 expected[2] = {OP_PREFIX << 26, 0};
-	ppc_inst_t inst = ppc_inst_prefix(OP_PREFIX << 26, 0);
-
-	if (!IS_ENABLED(CONFIG_PPC64))
-		return;
-
-	patch_instruction(iptr, inst);
-
-	check(!memcmp(iptr, expected, sizeof(expected)));
-}
-
-static int __init test_code_patching(void)
-{
-	pr_info("Running code patching self-tests ...\n");
-
-	test_branch_iform();
-	test_branch_bform();
-	test_create_function_call();
-	test_translate_branch();
-	test_prefixed_patching();
-
-	return 0;
-}
-late_initcall(test_code_patching);
-
-#endif /* CONFIG_CODE_PATCHING_SELFTEST */
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/test-code-patching.c
similarity index 56%
copy from arch/powerpc/lib/code-patching.c
copy to arch/powerpc/lib/test-code-patching.c
index e07de5db06c0..e358c9d8a03e 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/test-code-patching.c
@@ -3,361 +3,12 @@
  *  Copyright 2008 Michael Ellerman, IBM Corporation.
  */
 
-#include <linux/kernel.h>
-#include <linux/kprobes.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/cpuhotplug.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
 
-#include <asm/tlbflush.h>
-#include <asm/page.h>
 #include <asm/code-patching.h>
-#include <asm/inst.h>
 
-static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr)
-{
-	if (!ppc_inst_prefixed(instr)) {
-		u32 val = ppc_inst_val(instr);
-
-		__put_kernel_nofault(patch_addr, &val, u32, failed);
-	} else {
-		u64 val = ppc_inst_as_ulong(instr);
-
-		__put_kernel_nofault(patch_addr, &val, u64, failed);
-	}
-
-	asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
-							    "r" (exec_addr));
-
-	return 0;
-
-failed:
-	return -EFAULT;
-}
-
-int raw_patch_instruction(u32 *addr, ppc_inst_t instr)
-{
-	return __patch_instruction(addr, instr, addr);
-}
-
-#ifdef CONFIG_STRICT_KERNEL_RWX
-static DEFINE_PER_CPU(struct vm_struct *, text_poke_area);
-
-static int text_area_cpu_up(unsigned int cpu)
-{
-	struct vm_struct *area;
-
-	area = get_vm_area(PAGE_SIZE, VM_ALLOC);
-	if (!area) {
-		WARN_ONCE(1, "Failed to create text area for cpu %d\n",
-			cpu);
-		return -1;
-	}
-	this_cpu_write(text_poke_area, area);
-
-	return 0;
-}
-
-static int text_area_cpu_down(unsigned int cpu)
-{
-	free_vm_area(this_cpu_read(text_poke_area));
-	return 0;
-}
-
-/*
- * Although BUG_ON() is rude, in this case it should only happen if ENOMEM, and
- * we judge it as being preferable to a kernel that will crash later when
- * someone tries to use patch_instruction().
- */
-void __init poking_init(void)
-{
-	BUG_ON(!cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
-		"powerpc/text_poke:online", text_area_cpu_up,
-		text_area_cpu_down));
-}
-
-/*
- * This can be called for kernel text or a module.
- */
-static int map_patch_area(void *addr, unsigned long text_poke_addr)
-{
-	unsigned long pfn;
-
-	if (is_vmalloc_or_module_addr(addr))
-		pfn = vmalloc_to_pfn(addr);
-	else
-		pfn = __pa_symbol(addr) >> PAGE_SHIFT;
-
-	return map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL);
-}
-
-static void unmap_patch_area(unsigned long addr)
-{
-	pte_t *ptep;
-	pmd_t *pmdp;
-	pud_t *pudp;
-	p4d_t *p4dp;
-	pgd_t *pgdp;
-
-	pgdp = pgd_offset_k(addr);
-	if (WARN_ON(pgd_none(*pgdp)))
-		return;
-
-	p4dp = p4d_offset(pgdp, addr);
-	if (WARN_ON(p4d_none(*p4dp)))
-		return;
-
-	pudp = pud_offset(p4dp, addr);
-	if (WARN_ON(pud_none(*pudp)))
-		return;
-
-	pmdp = pmd_offset(pudp, addr);
-	if (WARN_ON(pmd_none(*pmdp)))
-		return;
-
-	ptep = pte_offset_kernel(pmdp, addr);
-	if (WARN_ON(pte_none(*ptep)))
-		return;
-
-	/*
-	 * In hash, pte_clear flushes the tlb, in radix, we have to
-	 */
-	pte_clear(&init_mm, addr, ptep);
-	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
-}
-
-static int __do_patch_instruction(u32 *addr, ppc_inst_t instr)
-{
-	int err;
-	u32 *patch_addr;
-	unsigned long text_poke_addr;
-
-	text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr;
-	patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr));
-
-	err = map_patch_area(addr, text_poke_addr);
-	if (err)
-		return err;
-
-	err = __patch_instruction(addr, instr, patch_addr);
-
-	unmap_patch_area(text_poke_addr);
-
-	return err;
-}
-
-static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
-{
-	int err;
-	unsigned long flags;
-
-	/*
-	 * During early early boot patch_instruction is called
-	 * when text_poke_area is not ready, but we still need
-	 * to allow patching. We just do the plain old patching
-	 */
-	if (!this_cpu_read(text_poke_area))
-		return raw_patch_instruction(addr, instr);
-
-	local_irq_save(flags);
-	err = __do_patch_instruction(addr, instr);
-	local_irq_restore(flags);
-
-	return err;
-}
-#else /* !CONFIG_STRICT_KERNEL_RWX */
-
-static int do_patch_instruction(u32 *addr, ppc_inst_t instr)
-{
-	return raw_patch_instruction(addr, instr);
-}
-
-#endif /* CONFIG_STRICT_KERNEL_RWX */
-
-int patch_instruction(u32 *addr, ppc_inst_t instr)
-{
-	/* Make sure we aren't patching a freed init section */
-	if (system_state >= SYSTEM_FREEING_INITMEM && init_section_contains(addr, 4))
-		return 0;
-
-	return do_patch_instruction(addr, instr);
-}
-NOKPROBE_SYMBOL(patch_instruction);
-
-int patch_branch(u32 *addr, unsigned long target, int flags)
-{
-	ppc_inst_t instr;
-
-	if (create_branch(&instr, addr, target, flags))
-		return -ERANGE;
-
-	return patch_instruction(addr, instr);
-}
-
-bool is_offset_in_branch_range(long offset)
-{
-	/*
-	 * Powerpc branch instruction is :
-	 *
-	 *  0         6                 30   31
-	 *  +---------+----------------+---+---+
-	 *  | opcode  |     LI         |AA |LK |
-	 *  +---------+----------------+---+---+
-	 *  Where AA = 0 and LK = 0
-	 *
-	 * LI is a signed 24 bits integer. The real branch offset is computed
-	 * by: imm32 = SignExtend(LI:'0b00', 32);
-	 *
-	 * So the maximum forward branch should be:
-	 *   (0x007fffff << 2) = 0x01fffffc =  0x1fffffc
-	 * The maximum backward branch should be:
-	 *   (0xff800000 << 2) = 0xfe000000 = -0x2000000
-	 */
-	return (offset >= -0x2000000 && offset <= 0x1fffffc && !(offset & 0x3));
-}
-
-bool is_offset_in_cond_branch_range(long offset)
-{
-	return offset >= -0x8000 && offset <= 0x7fff && !(offset & 0x3);
-}
-
-/*
- * Helper to check if a given instruction is a conditional branch
- * Derived from the conditional checks in analyse_instr()
- */
-bool is_conditional_branch(ppc_inst_t instr)
-{
-	unsigned int opcode = ppc_inst_primary_opcode(instr);
-
-	if (opcode == 16)       /* bc, bca, bcl, bcla */
-		return true;
-	if (opcode == 19) {
-		switch ((ppc_inst_val(instr) >> 1) & 0x3ff) {
-		case 16:        /* bclr, bclrl */
-		case 528:       /* bcctr, bcctrl */
-		case 560:       /* bctar, bctarl */
-			return true;
-		}
-	}
-	return false;
-}
-NOKPROBE_SYMBOL(is_conditional_branch);
-
-int create_branch(ppc_inst_t *instr, const u32 *addr,
-		  unsigned long target, int flags)
-{
-	long offset;
-
-	*instr = ppc_inst(0);
-	offset = target;
-	if (! (flags & BRANCH_ABSOLUTE))
-		offset = offset - (unsigned long)addr;
-
-	/* Check we can represent the target in the instruction format */
-	if (!is_offset_in_branch_range(offset))
-		return 1;
-
-	/* Mask out the flags and target, so they don't step on each other. */
-	*instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC));
-
-	return 0;
-}
-
-int create_cond_branch(ppc_inst_t *instr, const u32 *addr,
-		       unsigned long target, int flags)
-{
-	long offset;
-
-	offset = target;
-	if (! (flags & BRANCH_ABSOLUTE))
-		offset = offset - (unsigned long)addr;
-
-	/* Check we can represent the target in the instruction format */
-	if (!is_offset_in_cond_branch_range(offset))
-		return 1;
-
-	/* Mask out the flags and target, so they don't step on each other. */
-	*instr = ppc_inst(0x40000000 | (flags & 0x3FF0003) | (offset & 0xFFFC));
-
-	return 0;
-}
-
-int instr_is_relative_branch(ppc_inst_t instr)
-{
-	if (ppc_inst_val(instr) & BRANCH_ABSOLUTE)
-		return 0;
-
-	return instr_is_branch_iform(instr) || instr_is_branch_bform(instr);
-}
-
-int instr_is_relative_link_branch(ppc_inst_t instr)
-{
-	return instr_is_relative_branch(instr) && (ppc_inst_val(instr) & BRANCH_SET_LINK);
-}
-
-static unsigned long branch_iform_target(const u32 *instr)
-{
-	signed long imm;
-
-	imm = ppc_inst_val(ppc_inst_read(instr)) & 0x3FFFFFC;
-
-	/* If the top bit of the immediate value is set this is negative */
-	if (imm & 0x2000000)
-		imm -= 0x4000000;
-
-	if ((ppc_inst_val(ppc_inst_read(instr)) & BRANCH_ABSOLUTE) == 0)
-		imm += (unsigned long)instr;
-
-	return (unsigned long)imm;
-}
-
-static unsigned long branch_bform_target(const u32 *instr)
-{
-	signed long imm;
-
-	imm = ppc_inst_val(ppc_inst_read(instr)) & 0xFFFC;
-
-	/* If the top bit of the immediate value is set this is negative */
-	if (imm & 0x8000)
-		imm -= 0x10000;
-
-	if ((ppc_inst_val(ppc_inst_read(instr)) & BRANCH_ABSOLUTE) == 0)
-		imm += (unsigned long)instr;
-
-	return (unsigned long)imm;
-}
-
-unsigned long branch_target(const u32 *instr)
-{
-	if (instr_is_branch_iform(ppc_inst_read(instr)))
-		return branch_iform_target(instr);
-	else if (instr_is_branch_bform(ppc_inst_read(instr)))
-		return branch_bform_target(instr);
-
-	return 0;
-}
-
-int translate_branch(ppc_inst_t *instr, const u32 *dest, const u32 *src)
-{
-	unsigned long target;
-	target = branch_target(src);
-
-	if (instr_is_branch_iform(ppc_inst_read(src)))
-		return create_branch(instr, dest, target,
-				     ppc_inst_val(ppc_inst_read(src)));
-	else if (instr_is_branch_bform(ppc_inst_read(src)))
-		return create_cond_branch(instr, dest, target,
-					  ppc_inst_val(ppc_inst_read(src)));
-
-	return 1;
-}
-
-#ifdef CONFIG_CODE_PATCHING_SELFTEST
-
-static int instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
+static int __init instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
 {
 	if (instr_is_branch_iform(ppc_inst_read(instr)) ||
 	    instr_is_branch_bform(ppc_inst_read(instr)))
@@ -704,5 +355,3 @@ static int __init test_code_patching(void)
 	return 0;
 }
 late_initcall(test_code_patching);
-
-#endif /* CONFIG_CODE_PATCHING_SELFTEST */
-- 
2.33.1


^ permalink raw reply related

* [PATCH v1 08/11] powerpc/code-patching: Move patch_exception() outside code-patching.c
From: Christophe Leroy @ 2021-12-02 12:00 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <3ff9823c0a812a8a145d979a9600a6d4591b80ee.1638446239.git.christophe.leroy@csgroup.eu>

patch_exception() is dedicated to book3e/64 is nothing more than
a normal use of patch_branch(), so move it into a place dedicated
to book3e/64.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 arch/powerpc/include/asm/code-patching.h     |  7 -------
 arch/powerpc/include/asm/exception-64e.h     |  4 ++++
 arch/powerpc/include/asm/nohash/64/pgtable.h |  6 ++++++
 arch/powerpc/lib/code-patching.c             | 16 ----------------
 arch/powerpc/mm/nohash/book3e_pgtable.c      | 14 ++++++++++++++
 5 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 46e8c5a8ce51..275061c3c977 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -63,13 +63,6 @@ int instr_is_relative_link_branch(ppc_inst_t instr);
 unsigned long branch_target(const u32 *instr);
 int translate_branch(ppc_inst_t *instr, const u32 *dest, const u32 *src);
 bool is_conditional_branch(ppc_inst_t instr);
-#ifdef CONFIG_PPC_BOOK3E_64
-void __patch_exception(int exc, unsigned long addr);
-#define patch_exception(exc, name) do { \
-	extern unsigned int name; \
-	__patch_exception((exc), (unsigned long)&name); \
-} while (0)
-#endif
 
 #define OP_RT_RA_MASK	0xffff0000UL
 #define LIS_R2		(PPC_RAW_LIS(_R2, 0))
diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index 40cdcb2fb057..b1ef1e92c34a 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -149,6 +149,10 @@ exc_##label##_book3e:
 	addi	r11,r13,PACA_EXTLB;					    \
 	TLB_MISS_RESTORE(r11)
 
+#ifndef __ASSEMBLY__
+extern unsigned int interrupt_base_book3e;
+#endif
+
 #define SET_IVOR(vector_number, vector_offset)	\
 	LOAD_REG_ADDR(r3,interrupt_base_book3e);\
 	ori	r3,r3,vector_offset@l;		\
diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h
index 9d2905a47410..a3313e853e5e 100644
--- a/arch/powerpc/include/asm/nohash/64/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/64/pgtable.h
@@ -313,6 +313,12 @@ extern int __meminit vmemmap_create_mapping(unsigned long start,
 					    unsigned long phys);
 extern void vmemmap_remove_mapping(unsigned long start,
 				   unsigned long page_size);
+void __patch_exception(int exc, unsigned long addr);
+#define patch_exception(exc, name) do { \
+	extern unsigned int name; \
+	__patch_exception((exc), (unsigned long)&name); \
+} while (0)
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_NOHASH_64_PGTABLE_H */
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 2d878e67df3f..17e6443eb6c8 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -370,22 +370,6 @@ int translate_branch(ppc_inst_t *instr, const u32 *dest, const u32 *src)
 	return 1;
 }
 
-#ifdef CONFIG_PPC_BOOK3E_64
-void __patch_exception(int exc, unsigned long addr)
-{
-	extern unsigned int interrupt_base_book3e;
-	unsigned int *ibase = &interrupt_base_book3e;
-
-	/* Our exceptions vectors start with a NOP and -then- a branch
-	 * to deal with single stepping from userspace which stops on
-	 * the second instruction. Thus we need to patch the second
-	 * instruction of the exception, not the first one
-	 */
-
-	patch_branch(ibase + (exc / 4) + 1, addr, 0);
-}
-#endif
-
 #ifdef CONFIG_CODE_PATCHING_SELFTEST
 
 static int instr_is_branch_to_addr(const u32 *instr, unsigned long addr)
diff --git a/arch/powerpc/mm/nohash/book3e_pgtable.c b/arch/powerpc/mm/nohash/book3e_pgtable.c
index 77884e24281d..7b6db97c2bdc 100644
--- a/arch/powerpc/mm/nohash/book3e_pgtable.c
+++ b/arch/powerpc/mm/nohash/book3e_pgtable.c
@@ -10,6 +10,7 @@
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
 #include <asm/dma.h>
+#include <asm/code-patching.h>
 
 #include <mm/mmu_decl.h>
 
@@ -115,3 +116,16 @@ int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
 	smp_wmb();
 	return 0;
 }
+
+void __patch_exception(int exc, unsigned long addr)
+{
+	unsigned int *ibase = &interrupt_base_book3e;
+
+	/* Our exceptions vectors start with a NOP and -then- a branch
+	 * to deal with single stepping from userspace which stops on
+	 * the second instruction. Thus we need to patch the second
+	 * instruction of the exception, not the first one
+	 */
+
+	patch_branch(ibase + (exc / 4) + 1, addr, 0);
+}
-- 
2.33.1


^ permalink raw reply related

* Re: [PATCH v6 17/18] powerpc/64s: Move hash MMU support code under CONFIG_PPC_64S_HASH_MMU
From: Fabiano Rosas @ 2021-12-02 13:30 UTC (permalink / raw)
  To: Nicholas Piggin, linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20211201144153.2456614-18-npiggin@gmail.com>

Nicholas Piggin <npiggin@gmail.com> writes:

> Compiling out hash support code when CONFIG_PPC_64S_HASH_MMU=n saves
> 128kB kernel image size (90kB text) on powernv_defconfig minus KVM,
> 350kB on pseries_defconfig minus KVM, 40kB on a tiny config.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>

Tested this series on a P9. Tried to force some invalid configs with KVM
and it held up. Also built all defconfigs from make help.

Tested-by: Fabiano Rosas <farosas@linux.ibm.com>

> ---
>  arch/powerpc/Kconfig                          |  2 +-
>  arch/powerpc/include/asm/book3s/64/mmu.h      | 21 ++++++++++--
>  .../include/asm/book3s/64/tlbflush-hash.h     |  6 ++++
>  arch/powerpc/include/asm/book3s/pgtable.h     |  4 +++
>  arch/powerpc/include/asm/mmu_context.h        |  2 ++
>  arch/powerpc/include/asm/paca.h               |  8 +++++
>  arch/powerpc/kernel/asm-offsets.c             |  2 ++
>  arch/powerpc/kernel/entry_64.S                |  4 +--
>  arch/powerpc/kernel/exceptions-64s.S          | 16 ++++++++++
>  arch/powerpc/kernel/mce.c                     |  2 +-
>  arch/powerpc/kernel/mce_power.c               | 10 ++++--
>  arch/powerpc/kernel/paca.c                    | 18 ++++-------
>  arch/powerpc/kernel/process.c                 | 13 ++++----
>  arch/powerpc/kernel/prom.c                    |  2 ++
>  arch/powerpc/kernel/setup_64.c                |  5 +++
>  arch/powerpc/kexec/core_64.c                  |  4 +--
>  arch/powerpc/kexec/ranges.c                   |  4 +++
>  arch/powerpc/mm/book3s64/Makefile             | 15 +++++----
>  arch/powerpc/mm/book3s64/hugetlbpage.c        |  2 ++
>  arch/powerpc/mm/book3s64/mmu_context.c        | 32 +++++++++++++++----
>  arch/powerpc/mm/book3s64/pgtable.c            |  2 +-
>  arch/powerpc/mm/book3s64/radix_pgtable.c      |  4 +++
>  arch/powerpc/mm/copro_fault.c                 |  2 ++
>  arch/powerpc/mm/ptdump/Makefile               |  2 +-
>  arch/powerpc/platforms/powernv/idle.c         |  2 ++
>  arch/powerpc/platforms/powernv/setup.c        |  2 ++
>  arch/powerpc/platforms/pseries/lpar.c         | 11 +++++--
>  arch/powerpc/platforms/pseries/lparcfg.c      |  2 +-
>  arch/powerpc/platforms/pseries/mobility.c     |  6 ++++
>  arch/powerpc/platforms/pseries/ras.c          |  2 ++
>  arch/powerpc/platforms/pseries/reconfig.c     |  2 ++
>  arch/powerpc/platforms/pseries/setup.c        |  6 ++--
>  arch/powerpc/xmon/xmon.c                      |  8 +++--
>  drivers/misc/lkdtm/core.c                     |  2 +-
>  34 files changed, 173 insertions(+), 52 deletions(-)
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 1fa336ec8faf..fb48823ccd62 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -129,7 +129,7 @@ config PPC
>  	select ARCH_HAS_KCOV
>  	select ARCH_HAS_MEMBARRIER_CALLBACKS
>  	select ARCH_HAS_MEMBARRIER_SYNC_CORE
> -	select ARCH_HAS_MEMREMAP_COMPAT_ALIGN	if PPC_BOOK3S_64
> +	select ARCH_HAS_MEMREMAP_COMPAT_ALIGN	if PPC_64S_HASH_MMU
>  	select ARCH_HAS_MMIOWB			if PPC64
>  	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
>  	select ARCH_HAS_PHYS_TO_DMA
> diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
> index 015d7d972d16..c480d21a146c 100644
> --- a/arch/powerpc/include/asm/book3s/64/mmu.h
> +++ b/arch/powerpc/include/asm/book3s/64/mmu.h
> @@ -104,7 +104,9 @@ typedef struct {
>  		 * from EA and new context ids to build the new VAs.
>  		 */
>  		mm_context_id_t id;
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  		mm_context_id_t extended_id[TASK_SIZE_USER64/TASK_CONTEXT_SIZE];
> +#endif
>  	};
>
>  	/* Number of bits in the mm_cpumask */
> @@ -116,7 +118,9 @@ typedef struct {
>  	/* Number of user space windows opened in process mm_context */
>  	atomic_t vas_windows;
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	struct hash_mm_context *hash_context;
> +#endif
>
>  	void __user *vdso;
>  	/*
> @@ -139,6 +143,7 @@ typedef struct {
>  #endif
>  } mm_context_t;
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  static inline u16 mm_ctx_user_psize(mm_context_t *ctx)
>  {
>  	return ctx->hash_context->user_psize;
> @@ -199,8 +204,15 @@ static inline struct subpage_prot_table *mm_ctx_subpage_prot(mm_context_t *ctx)
>  extern int mmu_linear_psize;
>  extern int mmu_virtual_psize;
>  extern int mmu_vmalloc_psize;
> -extern int mmu_vmemmap_psize;
>  extern int mmu_io_psize;
> +#else /* CONFIG_PPC_64S_HASH_MMU */
> +#ifdef CONFIG_PPC_64K_PAGES
> +#define mmu_virtual_psize MMU_PAGE_64K
> +#else
> +#define mmu_virtual_psize MMU_PAGE_4K
> +#endif
> +#endif
> +extern int mmu_vmemmap_psize;
>
>  /* MMU initialization */
>  void mmu_early_init_devtree(void);
> @@ -239,8 +251,9 @@ static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
>  	 * know which translations we will pick. Hence go with hash
>  	 * restrictions.
>  	 */
> -	return hash__setup_initial_memory_limit(first_memblock_base,
> -					   first_memblock_size);
> +	if (!radix_enabled())
> +		hash__setup_initial_memory_limit(first_memblock_base,
> +						 first_memblock_size);
>  }
>
>  #ifdef CONFIG_PPC_PSERIES
> @@ -261,6 +274,7 @@ static inline void radix_init_pseries(void) { }
>  void cleanup_cpu_mmu_context(void);
>  #endif
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  static inline int get_user_context(mm_context_t *ctx, unsigned long ea)
>  {
>  	int index = ea >> MAX_EA_BITS_PER_CONTEXT;
> @@ -280,6 +294,7 @@ static inline unsigned long get_user_vsid(mm_context_t *ctx,
>
>  	return get_vsid(context, ea, ssize);
>  }
> +#endif
>
>  #endif /* __ASSEMBLY__ */
>  #endif /* _ASM_POWERPC_BOOK3S_64_MMU_H_ */
> diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
> index 3b95769739c7..8b762f282190 100644
> --- a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
> +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
> @@ -112,8 +112,14 @@ static inline void hash__flush_tlb_kernel_range(unsigned long start,
>
>  struct mmu_gather;
>  extern void hash__tlb_flush(struct mmu_gather *tlb);
> +void flush_tlb_pmd_range(struct mm_struct *mm, pmd_t *pmd, unsigned long addr);
> +
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  /* Private function for use by PCI IO mapping code */
>  extern void __flush_hash_table_range(unsigned long start, unsigned long end);
>  extern void flush_tlb_pmd_range(struct mm_struct *mm, pmd_t *pmd,
>  				unsigned long addr);
> +#else
> +static inline void __flush_hash_table_range(unsigned long start, unsigned long end) { }
> +#endif
>  #endif /*  _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H */
> diff --git a/arch/powerpc/include/asm/book3s/pgtable.h b/arch/powerpc/include/asm/book3s/pgtable.h
> index ad130e15a126..e8269434ecbe 100644
> --- a/arch/powerpc/include/asm/book3s/pgtable.h
> +++ b/arch/powerpc/include/asm/book3s/pgtable.h
> @@ -25,6 +25,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
>  				     unsigned long size, pgprot_t vma_prot);
>  #define __HAVE_PHYS_MEM_ACCESS_PROT
>
> +#if defined(CONFIG_PPC32) || defined(CONFIG_PPC_64S_HASH_MMU)
>  /*
>   * This gets called at the end of handling a page fault, when
>   * the kernel has put a new PTE into the page table for the process.
> @@ -35,6 +36,9 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
>   * waiting for the inevitable extra hash-table miss exception.
>   */
>  void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep);
> +#else
> +static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) {}
> +#endif
>
>  #endif /* __ASSEMBLY__ */
>  #endif
> diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h
> index 9ba6b585337f..e46394d27785 100644
> --- a/arch/powerpc/include/asm/mmu_context.h
> +++ b/arch/powerpc/include/asm/mmu_context.h
> @@ -75,6 +75,7 @@ extern void hash__reserve_context_id(int id);
>  extern void __destroy_context(int context_id);
>  static inline void mmu_context_init(void) { }
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  static inline int alloc_extended_context(struct mm_struct *mm,
>  					 unsigned long ea)
>  {
> @@ -100,6 +101,7 @@ static inline bool need_extra_context(struct mm_struct *mm, unsigned long ea)
>  		return true;
>  	return false;
>  }
> +#endif
>
>  #else
>  extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
> diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
> index dc05a862e72a..295573a82c66 100644
> --- a/arch/powerpc/include/asm/paca.h
> +++ b/arch/powerpc/include/asm/paca.h
> @@ -97,7 +97,9 @@ struct paca_struct {
>  					/* this becomes non-zero. */
>  	u8 kexec_state;		/* set when kexec down has irqs off */
>  #ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	struct slb_shadow *slb_shadow_ptr;
> +#endif
>  	struct dtl_entry *dispatch_log;
>  	struct dtl_entry *dispatch_log_end;
>  #endif
> @@ -110,6 +112,7 @@ struct paca_struct {
>  	/* used for most interrupts/exceptions */
>  	u64 exgen[EX_SIZE] __attribute__((aligned(0x80)));
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	/* SLB related definitions */
>  	u16 vmalloc_sllp;
>  	u8 slb_cache_ptr;
> @@ -120,6 +123,7 @@ struct paca_struct {
>  	u32 slb_used_bitmap;		/* Bitmaps for first 32 SLB entries. */
>  	u32 slb_kern_bitmap;
>  	u32 slb_cache[SLB_CACHE_ENTRIES];
> +#endif
>  #endif /* CONFIG_PPC_BOOK3S_64 */
>
>  #ifdef CONFIG_PPC_BOOK3E
> @@ -149,6 +153,7 @@ struct paca_struct {
>  #endif /* CONFIG_PPC_BOOK3E */
>
>  #ifdef CONFIG_PPC_BOOK3S
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  #ifdef CONFIG_PPC_MM_SLICES
>  	unsigned char mm_ctx_low_slices_psize[BITS_PER_LONG / BITS_PER_BYTE];
>  	unsigned char mm_ctx_high_slices_psize[SLICE_ARRAY_SIZE];
> @@ -156,6 +161,7 @@ struct paca_struct {
>  	u16 mm_ctx_user_psize;
>  	u16 mm_ctx_sllp;
>  #endif
> +#endif
>  #endif
>
>  	/*
> @@ -268,9 +274,11 @@ struct paca_struct {
>  #endif /* CONFIG_PPC_PSERIES */
>
>  #ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	/* Capture SLB related old contents in MCE handler. */
>  	struct slb_entry *mce_faulty_slbs;
>  	u16 slb_save_cache_ptr;
> +#endif
>  #endif /* CONFIG_PPC_BOOK3S_64 */
>  #ifdef CONFIG_STACKPROTECTOR
>  	unsigned long canary;
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index cc05522f50bf..b823f484c640 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -218,10 +218,12 @@ int main(void)
>  	OFFSET(PACA_EXGEN, paca_struct, exgen);
>  	OFFSET(PACA_EXMC, paca_struct, exmc);
>  	OFFSET(PACA_EXNMI, paca_struct, exnmi);
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	OFFSET(PACA_SLBSHADOWPTR, paca_struct, slb_shadow_ptr);
>  	OFFSET(SLBSHADOW_STACKVSID, slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid);
>  	OFFSET(SLBSHADOW_STACKESID, slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid);
>  	OFFSET(SLBSHADOW_SAVEAREA, slb_shadow, save_area);
> +#endif
>  	OFFSET(LPPACA_PMCINUSE, lppaca, pmcregs_in_use);
>  #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
>  	OFFSET(PACA_PMCINUSE, paca_struct, pmcregs_in_use);
> diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
> index 70cff7b49e17..9581906b5ee9 100644
> --- a/arch/powerpc/kernel/entry_64.S
> +++ b/arch/powerpc/kernel/entry_64.S
> @@ -180,7 +180,7 @@ _GLOBAL(_switch)
>  #endif
>
>  	ld	r8,KSP(r4)	/* new stack pointer */
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  BEGIN_MMU_FTR_SECTION
>  	b	2f
>  END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
> @@ -232,7 +232,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
>  	slbmte	r7,r0
>  	isync
>  2:
> -#endif /* CONFIG_PPC_BOOK3S_64 */
> +#endif /* CONFIG_PPC_64S_HASH_MMU */
>
>  	clrrdi	r7, r8, THREAD_SHIFT	/* base of new stack */
>  	/* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
> index 046c99e31d01..65b695e9401e 100644
> --- a/arch/powerpc/kernel/exceptions-64s.S
> +++ b/arch/powerpc/kernel/exceptions-64s.S
> @@ -1369,11 +1369,15 @@ EXC_COMMON_BEGIN(data_access_common)
>  	addi	r3,r1,STACK_FRAME_OVERHEAD
>  	andis.	r0,r4,DSISR_DABRMATCH@h
>  	bne-	1f
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  BEGIN_MMU_FTR_SECTION
>  	bl	do_hash_fault
>  MMU_FTR_SECTION_ELSE
>  	bl	do_page_fault
>  ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
> +#else
> +	bl	do_page_fault
> +#endif
>  	b	interrupt_return_srr
>
>  1:	bl	do_break
> @@ -1416,6 +1420,7 @@ EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80)
>  EXC_VIRT_END(data_access_slb, 0x4380, 0x80)
>  EXC_COMMON_BEGIN(data_access_slb_common)
>  	GEN_COMMON data_access_slb
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  BEGIN_MMU_FTR_SECTION
>  	/* HPT case, do SLB fault */
>  	addi	r3,r1,STACK_FRAME_OVERHEAD
> @@ -1428,6 +1433,9 @@ MMU_FTR_SECTION_ELSE
>  	/* Radix case, access is outside page table range */
>  	li	r3,-EFAULT
>  ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
> +#else
> +	li	r3,-EFAULT
> +#endif
>  	std	r3,RESULT(r1)
>  	addi	r3,r1,STACK_FRAME_OVERHEAD
>  	bl	do_bad_segment_interrupt
> @@ -1462,11 +1470,15 @@ EXC_VIRT_END(instruction_access, 0x4400, 0x80)
>  EXC_COMMON_BEGIN(instruction_access_common)
>  	GEN_COMMON instruction_access
>  	addi	r3,r1,STACK_FRAME_OVERHEAD
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  BEGIN_MMU_FTR_SECTION
>  	bl	do_hash_fault
>  MMU_FTR_SECTION_ELSE
>  	bl	do_page_fault
>  ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
> +#else
> +	bl	do_page_fault
> +#endif
>  	b	interrupt_return_srr
>
>
> @@ -1496,6 +1508,7 @@ EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80)
>  EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80)
>  EXC_COMMON_BEGIN(instruction_access_slb_common)
>  	GEN_COMMON instruction_access_slb
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  BEGIN_MMU_FTR_SECTION
>  	/* HPT case, do SLB fault */
>  	addi	r3,r1,STACK_FRAME_OVERHEAD
> @@ -1508,6 +1521,9 @@ MMU_FTR_SECTION_ELSE
>  	/* Radix case, access is outside page table range */
>  	li	r3,-EFAULT
>  ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
> +#else
> +	li	r3,-EFAULT
> +#endif
>  	std	r3,RESULT(r1)
>  	addi	r3,r1,STACK_FRAME_OVERHEAD
>  	bl	do_bad_segment_interrupt
> diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
> index fd829f7f25a4..2503dd4713b9 100644
> --- a/arch/powerpc/kernel/mce.c
> +++ b/arch/powerpc/kernel/mce.c
> @@ -586,7 +586,7 @@ void machine_check_print_event_info(struct machine_check_event *evt,
>  		mc_error_class[evt->error_class] : "Unknown";
>  	printk("%sMCE: CPU%d: %s\n", level, evt->cpu, subtype);
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	/* Display faulty slb contents for SLB errors. */
>  	if (evt->error_type == MCE_ERROR_TYPE_SLB && !in_guest)
>  		slb_dump_contents(local_paca->mce_faulty_slbs);
> diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
> index cf5263b648fc..a48ff18d6d65 100644
> --- a/arch/powerpc/kernel/mce_power.c
> +++ b/arch/powerpc/kernel/mce_power.c
> @@ -77,7 +77,7 @@ static bool mce_in_guest(void)
>  }
>
>  /* flush SLBs and reload */
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  void flush_and_reload_slb(void)
>  {
>  	if (early_radix_enabled())
> @@ -99,7 +99,7 @@ void flush_and_reload_slb(void)
>
>  void flush_erat(void)
>  {
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) {
>  		flush_and_reload_slb();
>  		return;
> @@ -114,7 +114,7 @@ void flush_erat(void)
>
>  static int mce_flush(int what)
>  {
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (what == MCE_FLUSH_SLB) {
>  		flush_and_reload_slb();
>  		return 1;
> @@ -499,8 +499,10 @@ static int mce_handle_ierror(struct pt_regs *regs, unsigned long srr1,
>  			/* attempt to correct the error */
>  			switch (table[i].error_type) {
>  			case MCE_ERROR_TYPE_SLB:
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  				if (local_paca->in_mce == 1)
>  					slb_save_contents(local_paca->mce_faulty_slbs);
> +#endif
>  				handled = mce_flush(MCE_FLUSH_SLB);
>  				break;
>  			case MCE_ERROR_TYPE_ERAT:
> @@ -588,8 +590,10 @@ static int mce_handle_derror(struct pt_regs *regs,
>  			/* attempt to correct the error */
>  			switch (table[i].error_type) {
>  			case MCE_ERROR_TYPE_SLB:
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  				if (local_paca->in_mce == 1)
>  					slb_save_contents(local_paca->mce_faulty_slbs);
> +#endif
>  				if (mce_flush(MCE_FLUSH_SLB))
>  					handled = 1;
>  				break;
> diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
> index 4208b4044d12..39da688a9455 100644
> --- a/arch/powerpc/kernel/paca.c
> +++ b/arch/powerpc/kernel/paca.c
> @@ -139,8 +139,7 @@ static struct lppaca * __init new_lppaca(int cpu, unsigned long limit)
>  }
>  #endif /* CONFIG_PPC_PSERIES */
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> -
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  /*
>   * 3 persistent SLBs are allocated here.  The buffer will be zero
>   * initially, hence will all be invaild until we actually write them.
> @@ -169,8 +168,7 @@ static struct slb_shadow * __init new_slb_shadow(int cpu, unsigned long limit)
>
>  	return s;
>  }
> -
> -#endif /* CONFIG_PPC_BOOK3S_64 */
> +#endif /* CONFIG_PPC_64S_HASH_MMU */
>
>  #ifdef CONFIG_PPC_PSERIES
>  /**
> @@ -226,7 +224,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
>  	new_paca->kexec_state = KEXEC_STATE_NONE;
>  	new_paca->__current = &init_task;
>  	new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	new_paca->slb_shadow_ptr = NULL;
>  #endif
>
> @@ -307,7 +305,7 @@ void __init allocate_paca(int cpu)
>  #ifdef CONFIG_PPC_PSERIES
>  	paca->lppaca_ptr = new_lppaca(cpu, limit);
>  #endif
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	paca->slb_shadow_ptr = new_slb_shadow(cpu, limit);
>  #endif
>  #ifdef CONFIG_PPC_PSERIES
> @@ -328,7 +326,7 @@ void __init free_unused_pacas(void)
>  	paca_nr_cpu_ids = nr_cpu_ids;
>  	paca_ptrs_size = new_ptrs_size;
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (early_radix_enabled()) {
>  		/* Ugly fixup, see new_slb_shadow() */
>  		memblock_phys_free(__pa(paca_ptrs[boot_cpuid]->slb_shadow_ptr),
> @@ -341,9 +339,9 @@ void __init free_unused_pacas(void)
>  			paca_ptrs_size + paca_struct_size, nr_cpu_ids);
>  }
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  void copy_mm_to_paca(struct mm_struct *mm)
>  {
> -#ifdef CONFIG_PPC_BOOK3S
>  	mm_context_t *context = &mm->context;
>
>  #ifdef CONFIG_PPC_MM_SLICES
> @@ -356,7 +354,5 @@ void copy_mm_to_paca(struct mm_struct *mm)
>  	get_paca()->mm_ctx_user_psize = context->user_psize;
>  	get_paca()->mm_ctx_sllp = context->sllp;
>  #endif
> -#else /* !CONFIG_PPC_BOOK3S */
> -	return;
> -#endif
>  }
> +#endif /* CONFIG_PPC_64S_HASH_MMU */
> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
> index 5d2333d2a283..a64cfbb85ca2 100644
> --- a/arch/powerpc/kernel/process.c
> +++ b/arch/powerpc/kernel/process.c
> @@ -1240,7 +1240,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
>  {
>  	struct thread_struct *new_thread, *old_thread;
>  	struct task_struct *last;
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	struct ppc64_tlb_batch *batch;
>  #endif
>
> @@ -1249,7 +1249,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
>
>  	WARN_ON(!irqs_disabled());
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	batch = this_cpu_ptr(&ppc64_tlb_batch);
>  	if (batch->active) {
>  		current_thread_info()->local_flags |= _TLF_LAZY_MMU;
> @@ -1328,6 +1328,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
>  	 */
>
>  #ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	/*
>  	 * This applies to a process that was context switched while inside
>  	 * arch_enter_lazy_mmu_mode(), to re-activate the batch that was
> @@ -1339,6 +1340,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
>  		batch = this_cpu_ptr(&ppc64_tlb_batch);
>  		batch->active = 1;
>  	}
> +#endif
>
>  	/*
>  	 * Math facilities are masked out of the child MSR in copy_thread.
> @@ -1689,7 +1691,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
>
>  static void setup_ksp_vsid(struct task_struct *p, unsigned long sp)
>  {
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	unsigned long sp_vsid;
>  	unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
>
> @@ -2333,10 +2335,9 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
>  	 * the heap, we can put it above 1TB so it is backed by a 1TB
>  	 * segment. Otherwise the heap will be in the bottom 1TB
>  	 * which always uses 256MB segments and this may result in a
> -	 * performance penalty. We don't need to worry about radix. For
> -	 * radix, mmu_highuser_ssize remains unchanged from 256MB.
> +	 * performance penalty.
>  	 */
> -	if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
> +	if (!radix_enabled() && !is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
>  		base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T);
>  #endif
>
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index 2e67588f6f6e..2197404cdcc4 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -234,6 +234,7 @@ static void __init check_cpu_pa_features(unsigned long node)
>  #ifdef CONFIG_PPC_BOOK3S_64
>  static void __init init_mmu_slb_size(unsigned long node)
>  {
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	const __be32 *slb_size_ptr;
>
>  	slb_size_ptr = of_get_flat_dt_prop(node, "slb-size", NULL) ? :
> @@ -241,6 +242,7 @@ static void __init init_mmu_slb_size(unsigned long node)
>
>  	if (slb_size_ptr)
>  		mmu_slb_size = be32_to_cpup(slb_size_ptr);
> +#endif
>  }
>  #else
>  #define init_mmu_slb_size(node) do { } while(0)
> diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
> index 9a493796ce66..22647bb82198 100644
> --- a/arch/powerpc/kernel/setup_64.c
> +++ b/arch/powerpc/kernel/setup_64.c
> @@ -887,6 +887,8 @@ void __init setup_per_cpu_areas(void)
>  	} else if (radix_enabled()) {
>  		atom_size = PAGE_SIZE;
>  	} else {
> +#ifdef CONFIG_PPC_64S_HASH_MMU
> +
>  		/*
>  		 * Linear mapping is one of 4K, 1M and 16M.  For 4K, no need
>  		 * to group units.  For larger mappings, use 1M atom which
> @@ -896,6 +898,9 @@ void __init setup_per_cpu_areas(void)
>  			atom_size = PAGE_SIZE;
>  		else
>  			atom_size = SZ_1M;
> +#else
> +		BUILD_BUG(); // radix_enabled() should be constant true
> +#endif
>  	}
>
>  	if (pcpu_chosen_fc != PCPU_FC_PAGE) {
> diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c
> index 66678518b938..635b5fc30b53 100644
> --- a/arch/powerpc/kexec/core_64.c
> +++ b/arch/powerpc/kexec/core_64.c
> @@ -378,7 +378,7 @@ void default_machine_kexec(struct kimage *image)
>  	/* NOTREACHED */
>  }
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  /* Values we need to export to the second kernel via the device tree. */
>  static unsigned long htab_base;
>  static unsigned long htab_size;
> @@ -420,4 +420,4 @@ static int __init export_htab_values(void)
>  	return 0;
>  }
>  late_initcall(export_htab_values);
> -#endif /* CONFIG_PPC_BOOK3S_64 */
> +#endif /* CONFIG_PPC_64S_HASH_MMU */
> diff --git a/arch/powerpc/kexec/ranges.c b/arch/powerpc/kexec/ranges.c
> index 6b81c852feab..92d831621fa0 100644
> --- a/arch/powerpc/kexec/ranges.c
> +++ b/arch/powerpc/kexec/ranges.c
> @@ -306,10 +306,14 @@ int add_initrd_mem_range(struct crash_mem **mem_ranges)
>   */
>  int add_htab_mem_range(struct crash_mem **mem_ranges)
>  {
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (!htab_address)
>  		return 0;
>
>  	return add_mem_range(mem_ranges, __pa(htab_address), htab_size_bytes);
> +#else
> +	return 0;
> +#endif
>  }
>  #endif
>
> diff --git a/arch/powerpc/mm/book3s64/Makefile b/arch/powerpc/mm/book3s64/Makefile
> index 501efadb287f..2d50cac499c5 100644
> --- a/arch/powerpc/mm/book3s64/Makefile
> +++ b/arch/powerpc/mm/book3s64/Makefile
> @@ -2,20 +2,23 @@
>
>  ccflags-y	:= $(NO_MINIMAL_TOC)
>
> +obj-y				+= mmu_context.o pgtable.o trace.o
> +ifdef CONFIG_PPC_64S_HASH_MMU
>  CFLAGS_REMOVE_slb.o = $(CC_FLAGS_FTRACE)
> -
> -obj-y				+= hash_pgtable.o hash_utils.o slb.o \
> -				   mmu_context.o pgtable.o hash_tlb.o trace.o
> +obj-y				+= hash_pgtable.o hash_utils.o hash_tlb.o slb.o
>  obj-$(CONFIG_PPC_HASH_MMU_NATIVE)	+= hash_native.o
> -obj-$(CONFIG_PPC_RADIX_MMU)	+= radix_pgtable.o radix_tlb.o
>  obj-$(CONFIG_PPC_4K_PAGES)	+= hash_4k.o
>  obj-$(CONFIG_PPC_64K_PAGES)	+= hash_64k.o
> +obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += hash_hugepage.o
> +obj-$(CONFIG_PPC_SUBPAGE_PROT)	+= subpage_prot.o
> +endif
> +
>  obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
> +
> +obj-$(CONFIG_PPC_RADIX_MMU)	+= radix_pgtable.o radix_tlb.o
>  ifdef CONFIG_HUGETLB_PAGE
>  obj-$(CONFIG_PPC_RADIX_MMU)	+= radix_hugetlbpage.o
>  endif
> -obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += hash_hugepage.o
> -obj-$(CONFIG_PPC_SUBPAGE_PROT)	+= subpage_prot.o
>  obj-$(CONFIG_SPAPR_TCE_IOMMU)	+= iommu_api.o
>  obj-$(CONFIG_PPC_PKEY)	+= pkeys.o
>
> diff --git a/arch/powerpc/mm/book3s64/hugetlbpage.c b/arch/powerpc/mm/book3s64/hugetlbpage.c
> index a688e1324ae5..95b2a283fd6e 100644
> --- a/arch/powerpc/mm/book3s64/hugetlbpage.c
> +++ b/arch/powerpc/mm/book3s64/hugetlbpage.c
> @@ -16,6 +16,7 @@
>  unsigned int hpage_shift;
>  EXPORT_SYMBOL(hpage_shift);
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
>  		     pte_t *ptep, unsigned long trap, unsigned long flags,
>  		     int ssize, unsigned int shift, unsigned int mmu_psize)
> @@ -122,6 +123,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
>  	*ptep = __pte(new_pte & ~H_PAGE_BUSY);
>  	return 0;
>  }
> +#endif
>
>  pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma,
>  				  unsigned long addr, pte_t *ptep)
> diff --git a/arch/powerpc/mm/book3s64/mmu_context.c b/arch/powerpc/mm/book3s64/mmu_context.c
> index c10fc8a72fb3..24aa953c9311 100644
> --- a/arch/powerpc/mm/book3s64/mmu_context.c
> +++ b/arch/powerpc/mm/book3s64/mmu_context.c
> @@ -31,6 +31,7 @@ static int alloc_context_id(int min_id, int max_id)
>  	return ida_alloc_range(&mmu_context_ida, min_id, max_id, GFP_KERNEL);
>  }
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  void hash__reserve_context_id(int id)
>  {
>  	int result = ida_alloc_range(&mmu_context_ida, id, id, GFP_KERNEL);
> @@ -50,7 +51,9 @@ int hash__alloc_context_id(void)
>  	return alloc_context_id(MIN_USER_CONTEXT, max);
>  }
>  EXPORT_SYMBOL_GPL(hash__alloc_context_id);
> +#endif
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  static int realloc_context_ids(mm_context_t *ctx)
>  {
>  	int i, id;
> @@ -150,6 +153,13 @@ void hash__setup_new_exec(void)
>
>  	slb_setup_new_exec();
>  }
> +#else
> +static inline int hash__init_new_context(struct mm_struct *mm)
> +{
> +	BUILD_BUG();
> +	return 0;
> +}
> +#endif
>
>  static int radix__init_new_context(struct mm_struct *mm)
>  {
> @@ -175,7 +185,9 @@ static int radix__init_new_context(struct mm_struct *mm)
>  	 */
>  	asm volatile("ptesync;isync" : : : "memory");
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	mm->context.hash_context = NULL;
> +#endif
>
>  	return index;
>  }
> @@ -213,14 +225,22 @@ EXPORT_SYMBOL_GPL(__destroy_context);
>
>  static void destroy_contexts(mm_context_t *ctx)
>  {
> -	int index, context_id;
> +	if (radix_enabled()) {
> +		ida_free(&mmu_context_ida, ctx->id);
> +	} else {
> +#ifdef CONFIG_PPC_64S_HASH_MMU
> +		int index, context_id;
>
> -	for (index = 0; index < ARRAY_SIZE(ctx->extended_id); index++) {
> -		context_id = ctx->extended_id[index];
> -		if (context_id)
> -			ida_free(&mmu_context_ida, context_id);
> +		for (index = 0; index < ARRAY_SIZE(ctx->extended_id); index++) {
> +			context_id = ctx->extended_id[index];
> +			if (context_id)
> +				ida_free(&mmu_context_ida, context_id);
> +		}
> +		kfree(ctx->hash_context);
> +#else
> +		BUILD_BUG(); // radix_enabled() should be constant true
> +#endif
>  	}
> -	kfree(ctx->hash_context);
>  }
>
>  static void pmd_frag_destroy(void *pmd_frag)
> diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
> index 4d97d1525d49..d765d972566b 100644
> --- a/arch/powerpc/mm/book3s64/pgtable.c
> +++ b/arch/powerpc/mm/book3s64/pgtable.c
> @@ -534,7 +534,7 @@ static int __init pgtable_debugfs_setup(void)
>  }
>  arch_initcall(pgtable_debugfs_setup);
>
> -#ifdef CONFIG_ZONE_DEVICE
> +#if defined(CONFIG_ZONE_DEVICE) && defined(ARCH_HAS_MEMREMAP_COMPAT_ALIGN)
>  /*
>   * Override the generic version in mm/memremap.c.
>   *
> diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c
> index 77820036c722..99dbee114539 100644
> --- a/arch/powerpc/mm/book3s64/radix_pgtable.c
> +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c
> @@ -334,8 +334,10 @@ static void __init radix_init_pgtable(void)
>  	phys_addr_t start, end;
>  	u64 i;
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	/* We don't support slb for radix */
>  	mmu_slb_size = 0;
> +#endif
>
>  	/*
>  	 * Create the linear mapping
> @@ -576,6 +578,7 @@ void __init radix__early_init_mmu(void)
>  {
>  	unsigned long lpcr;
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  #ifdef CONFIG_PPC_64K_PAGES
>  	/* PAGE_SIZE mappings */
>  	mmu_virtual_psize = MMU_PAGE_64K;
> @@ -592,6 +595,7 @@ void __init radix__early_init_mmu(void)
>  		mmu_vmemmap_psize = MMU_PAGE_2M;
>  	} else
>  		mmu_vmemmap_psize = mmu_virtual_psize;
> +#endif
>  #endif
>  	/*
>  	 * initialize page table size
> diff --git a/arch/powerpc/mm/copro_fault.c b/arch/powerpc/mm/copro_fault.c
> index 8acd00178956..c1cb21a00884 100644
> --- a/arch/powerpc/mm/copro_fault.c
> +++ b/arch/powerpc/mm/copro_fault.c
> @@ -82,6 +82,7 @@ int copro_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
>  }
>  EXPORT_SYMBOL_GPL(copro_handle_mm_fault);
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
>  {
>  	u64 vsid, vsidkey;
> @@ -146,3 +147,4 @@ void copro_flush_all_slbs(struct mm_struct *mm)
>  	cxl_slbia(mm);
>  }
>  EXPORT_SYMBOL_GPL(copro_flush_all_slbs);
> +#endif
> diff --git a/arch/powerpc/mm/ptdump/Makefile b/arch/powerpc/mm/ptdump/Makefile
> index 4050cbb55acf..b533caaf0910 100644
> --- a/arch/powerpc/mm/ptdump/Makefile
> +++ b/arch/powerpc/mm/ptdump/Makefile
> @@ -10,5 +10,5 @@ obj-$(CONFIG_PPC_BOOK3S_64)	+= book3s64.o
>
>  ifdef CONFIG_PTDUMP_DEBUGFS
>  obj-$(CONFIG_PPC_BOOK3S_32)	+= bats.o segment_regs.o
> -obj-$(CONFIG_PPC_BOOK3S_64)	+= hashpagetable.o
> +obj-$(CONFIG_PPC_64S_HASH_MMU)	+= hashpagetable.o
>  endif
> diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
> index 3bc84e2fe064..f0edfe6c1598 100644
> --- a/arch/powerpc/platforms/powernv/idle.c
> +++ b/arch/powerpc/platforms/powernv/idle.c
> @@ -491,12 +491,14 @@ static unsigned long power7_idle_insn(unsigned long type)
>
>  	mtspr(SPRN_SPRG3,	local_paca->sprg_vdso);
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	/*
>  	 * The SLB has to be restored here, but it sometimes still
>  	 * contains entries, so the __ variant must be used to prevent
>  	 * multi hits.
>  	 */
>  	__slb_restore_bolted_realmode();
> +#endif
>
>  	return srr1;
>  }
> diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
> index 5ef6b8afb3d0..f37d6524a24d 100644
> --- a/arch/powerpc/platforms/powernv/setup.c
> +++ b/arch/powerpc/platforms/powernv/setup.c
> @@ -211,6 +211,7 @@ static void __init pnv_init(void)
>  #endif
>  		add_preferred_console("hvc", 0, NULL);
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (!radix_enabled()) {
>  		size_t size = sizeof(struct slb_entry) * mmu_slb_size;
>  		int i;
> @@ -223,6 +224,7 @@ static void __init pnv_init(void)
>  						cpu_to_node(i));
>  		}
>  	}
> +#endif
>  }
>
>  static void __init pnv_init_IRQ(void)
> diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
> index 06d6a824c0dc..fac5d86777db 100644
> --- a/arch/powerpc/platforms/pseries/lpar.c
> +++ b/arch/powerpc/platforms/pseries/lpar.c
> @@ -58,6 +58,7 @@ EXPORT_SYMBOL(plpar_hcall);
>  EXPORT_SYMBOL(plpar_hcall9);
>  EXPORT_SYMBOL(plpar_hcall_norets);
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  /*
>   * H_BLOCK_REMOVE supported block size for this page size in segment who's base
>   * page size is that page size.
> @@ -66,6 +67,7 @@ EXPORT_SYMBOL(plpar_hcall_norets);
>   * page size.
>   */
>  static int hblkrm_size[MMU_PAGE_COUNT][MMU_PAGE_COUNT] __ro_after_init;
> +#endif
>
>  /*
>   * Due to the involved complexity, and that the current hypervisor is only
> @@ -689,7 +691,7 @@ void vpa_init(int cpu)
>  		return;
>  	}
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	/*
>  	 * PAPR says this feature is SLB-Buffer but firmware never
>  	 * reports that.  All SPLPAR support SLB shadow buffer.
> @@ -702,7 +704,7 @@ void vpa_init(int cpu)
>  			       "cpu %d (hw %d) of area %lx failed with %ld\n",
>  			       cpu, hwcpu, addr, ret);
>  	}
> -#endif /* CONFIG_PPC_BOOK3S_64 */
> +#endif /* CONFIG_PPC_64S_HASH_MMU */
>
>  	/*
>  	 * Register dispatch trace log, if one has been allocated.
> @@ -740,6 +742,8 @@ static int pseries_lpar_register_process_table(unsigned long base,
>  	return rc;
>  }
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
> +
>  static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
>  				     unsigned long vpn, unsigned long pa,
>  				     unsigned long rflags, unsigned long vflags,
> @@ -1730,6 +1734,7 @@ void __init hpte_init_pseries(void)
>  	if (cpu_has_feature(CPU_FTR_ARCH_300))
>  		pseries_lpar_register_process_table(0, 0, 0);
>  }
> +#endif /* CONFIG_PPC_64S_HASH_MMU */
>
>  #ifdef CONFIG_PPC_RADIX_MMU
>  void radix_init_pseries(void)
> @@ -1932,6 +1937,7 @@ int h_get_mpp_x(struct hvcall_mpp_x_data *mpp_x_data)
>  	return rc;
>  }
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  static unsigned long vsid_unscramble(unsigned long vsid, int ssize)
>  {
>  	unsigned long protovsid;
> @@ -1992,6 +1998,7 @@ static int __init reserve_vrma_context_id(void)
>  	return 0;
>  }
>  machine_device_initcall(pseries, reserve_vrma_context_id);
> +#endif
>
>  #ifdef CONFIG_DEBUG_FS
>  /* debugfs file interface for vpa data */
> diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c
> index 3354c00914fa..c7940fcfc911 100644
> --- a/arch/powerpc/platforms/pseries/lparcfg.c
> +++ b/arch/powerpc/platforms/pseries/lparcfg.c
> @@ -531,7 +531,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
>  	seq_printf(m, "shared_processor_mode=%d\n",
>  		   lppaca_shared_proc(get_lppaca()));
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (!radix_enabled())
>  		seq_printf(m, "slb_size=%d\n", mmu_slb_size);
>  #endif
> diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
> index 210a37a065fb..21b706bcea76 100644
> --- a/arch/powerpc/platforms/pseries/mobility.c
> +++ b/arch/powerpc/platforms/pseries/mobility.c
> @@ -451,11 +451,15 @@ static void prod_others(void)
>
>  static u16 clamp_slb_size(void)
>  {
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	u16 prev = mmu_slb_size;
>
>  	slb_set_size(SLB_MIN_SIZE);
>
>  	return prev;
> +#else
> +	return 0;
> +#endif
>  }
>
>  static int do_suspend(void)
> @@ -480,7 +484,9 @@ static int do_suspend(void)
>  	ret = rtas_ibm_suspend_me(&status);
>  	if (ret != 0) {
>  		pr_err("ibm,suspend-me error: %d\n", status);
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  		slb_set_size(saved_slb_size);
> +#endif
>  	}
>
>  	return ret;
> diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
> index 56092dccfdb8..74c9b1b5bc66 100644
> --- a/arch/powerpc/platforms/pseries/ras.c
> +++ b/arch/powerpc/platforms/pseries/ras.c
> @@ -526,6 +526,7 @@ static int mce_handle_err_realmode(int disposition, u8 error_type)
>  			disposition = RTAS_DISP_FULLY_RECOVERED;
>  			break;
>  		case	MC_ERROR_TYPE_SLB:
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  			/*
>  			 * Store the old slb content in paca before flushing.
>  			 * Print this when we go to virtual mode.
> @@ -538,6 +539,7 @@ static int mce_handle_err_realmode(int disposition, u8 error_type)
>  				slb_save_contents(local_paca->mce_faulty_slbs);
>  			flush_and_reload_slb();
>  			disposition = RTAS_DISP_FULLY_RECOVERED;
> +#endif
>  			break;
>  		default:
>  			break;
> diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
> index 7f7369fec46b..80dae18d6621 100644
> --- a/arch/powerpc/platforms/pseries/reconfig.c
> +++ b/arch/powerpc/platforms/pseries/reconfig.c
> @@ -337,8 +337,10 @@ static int do_update_property(char *buf, size_t bufsize)
>  	if (!newprop)
>  		return -ENOMEM;
>
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
>  		slb_set_size(*(int *)value);
> +#endif
>
>  	return of_update_property(np, newprop);
>  }
> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
> index 8a62af5b9c24..7f69237d4fa4 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -112,7 +112,7 @@ static void __init fwnmi_init(void)
>  	u8 *mce_data_buf;
>  	unsigned int i;
>  	int nr_cpus = num_possible_cpus();
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	struct slb_entry *slb_ptr;
>  	size_t size;
>  #endif
> @@ -152,7 +152,7 @@ static void __init fwnmi_init(void)
>  						(RTAS_ERROR_LOG_MAX * i);
>  	}
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (!radix_enabled()) {
>  		/* Allocate per cpu area to save old slb contents during MCE */
>  		size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus;
> @@ -801,7 +801,9 @@ static void __init pSeries_setup_arch(void)
>  	fwnmi_init();
>
>  	pseries_setup_security_mitigations();
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	pseries_lpar_read_hblkrm_characteristics();
> +#endif
>
>  	/* By default, only probe PCI (can be overridden by rtas_pci) */
>  	pci_add_flags(PCI_PROBE_ONLY);
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 3b2be65a32f2..46dd292a4694 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -1159,7 +1159,7 @@ cmds(struct pt_regs *excp)
>  		case 'P':
>  			show_tasks();
>  			break;
> -#ifdef CONFIG_PPC_BOOK3S
> +#if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_64S_HASH_MMU)
>  		case 'u':
>  			dump_segments();
>  			break;
> @@ -2614,7 +2614,7 @@ static void dump_tracing(void)
>  static void dump_one_paca(int cpu)
>  {
>  	struct paca_struct *p;
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	int i = 0;
>  #endif
>
> @@ -2656,6 +2656,7 @@ static void dump_one_paca(int cpu)
>  	DUMP(p, cpu_start, "%#-*x");
>  	DUMP(p, kexec_state, "%#-*x");
>  #ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	if (!early_radix_enabled()) {
>  		for (i = 0; i < SLB_NUM_BOLTED; i++) {
>  			u64 esid, vsid;
> @@ -2683,6 +2684,7 @@ static void dump_one_paca(int cpu)
>  				       22, "slb_cache", i, p->slb_cache[i]);
>  		}
>  	}
> +#endif
>
>  	DUMP(p, rfi_flush_fallback_area, "%-*px");
>  #endif
> @@ -3746,7 +3748,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
>  	printf("%s", after);
>  }
>
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  void dump_segments(void)
>  {
>  	int i;
> diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
> index 609d9ee2acc0..82fb276f7e09 100644
> --- a/drivers/misc/lkdtm/core.c
> +++ b/drivers/misc/lkdtm/core.c
> @@ -182,7 +182,7 @@ static const struct crashtype crashtypes[] = {
>  	CRASHTYPE(FORTIFIED_SUBOBJECT),
>  	CRASHTYPE(FORTIFIED_STRSCPY),
>  	CRASHTYPE(DOUBLE_FAULT),
> -#ifdef CONFIG_PPC_BOOK3S_64
> +#ifdef CONFIG_PPC_64S_HASH_MMU
>  	CRASHTYPE(PPC_SLB_MULTIHIT),
>  #endif
>  };

^ permalink raw reply

* Re: [patch 11/22] x86/hyperv: Refactor hv_msi_domain_free_irqs()
From: Wei Liu @ 2021-12-02 14:36 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-hyperv, linux-mips, Paul Mackerras, sparclinux, Wei Liu,
	Ashok Raj, Marc Zygnier, x86, Christian Borntraeger,
	Bjorn Helgaas, Jason Gunthorpe, linux-pci, xen-devel, ath11k,
	Kevin Tian, Heiko Carstens, Alex Williamson, Megha Dey,
	Juergen Gross, Thomas Bogendoerfer, Greg Kroah-Hartman, LKML,
	linuxppc-dev
In-Reply-To: <20211126223824.737214551@linutronix.de>

On Sat, Nov 27, 2021 at 02:18:51AM +0100, Thomas Gleixner wrote:
> No point in looking up things over and over. Just look up the associated
> irq data and work from there.
> 
> No functional change.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: Wei Liu <wei.liu@kernel.org>

^ permalink raw reply

* RE: [PATCH v2 3/3] soc: fsl: Replace kernel.h with the necessary inclusions
From: Leo Li @ 2021-12-02 20:01 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, Qiang Zhao
In-Reply-To: <YaiS2iHCrGkXgTdX@smile.fi.intel.com>



> -----Original Message-----
> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Sent: Thursday, December 2, 2021 3:33 AM
> To: Leo Li <leoyang.li@nxp.com>
> Cc: linuxppc-dev@lists.ozlabs.org; linux-kernel@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; Qiang Zhao <qiang.zhao@nxp.com>
> Subject: Re: [PATCH v2 3/3] soc: fsl: Replace kernel.h with the necessary
> inclusions
> 
> On Wed, Dec 01, 2021 at 01:41:16PM -0600, Li Yang wrote:
> > On Tue, Nov 23, 2021 at 10:32 AM Andy Shevchenko
> > <andriy.shevchenko@linux.intel.com> wrote:
> > >
> > > On Tue, Nov 16, 2021 at 11:38:01AM +0200, Andy Shevchenko wrote:
> > > > On Mon, Nov 15, 2021 at 10:24:36PM +0000, Leo Li wrote:
> > > > > > From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > > > > > Sent: Monday, November 15, 2021 5:30 AM On Wed, Nov 10, 2021
> > > > > > at 12:59:52PM +0200, Andy Shevchenko wrote:
> > > >
> > > > ...
> > > >
> > > > > > > v2: updated Cc list based on previous changes to MAINTAINERS
> > > > > >
> > > > > > Any comments on this, please?
> > > > > >
> > > > > > I really want to decrease amount of kernel.h usage in the common
> headers.
> > > > > > So others won't copy'n'paste bad example.
> > > > >
> > > > > There seems to be no problem with the patch although I didn't get
> time to really compile with it applied.
> > > > >
> > > > > Will pick them up later after build test.
> > > >
> > > > Thank you!
> > > >
> > > > Note, it has two fixes against MAINTAINERS which may be sent, I
> > > > believe, sooner than later to Linus.
> > >
> > > Any new so far?
> >
> > The build test is good.  I have applied it for next.  Thanks.
> 
> Thanks, what about MAINTAINERS updates? I don't see them neither in next
> nor in your tree.

I am ok with these MAINTAINERS updates.  I thought you want to send them directly to Linus.  I can take them if you like.

Regards,
Leo

^ permalink raw reply

* RE: bug: usb: gadget: FSL_UDC_CORE Corrupted request list leads to unrecoverable loop.
From: Leo Li @ 2021-12-02 20:35 UTC (permalink / raw)
  To: jocke@infinera.com, regressions@leemhuis.info,
	Eugene_Bordenkircher@selinc.com, linux-usb@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org
  Cc: gregkh@linuxfoundation.org, balbi@kernel.org
In-Reply-To: <527ebc333daa2a1d513ea217e5beb61a5acea3fb.camel@infinera.com>



> -----Original Message-----
> From: Joakim Tjernlund <Joakim.Tjernlund@infinera.com>
> Sent: Wednesday, December 1, 2021 8:19 AM
> To: regressions@leemhuis.info; Leo Li <leoyang.li@nxp.com>;
> Eugene_Bordenkircher@selinc.com; linux-usb@vger.kernel.org; linuxppc-
> dev@lists.ozlabs.org
> Cc: gregkh@linuxfoundation.org; balbi@kernel.org
> Subject: Re: bug: usb: gadget: FSL_UDC_CORE Corrupted request list leads to
> unrecoverable loop.
> 
> On Tue, 2021-11-30 at 12:56 +0100, Joakim Tjernlund wrote:
> > On Mon, 2021-11-29 at 23:48 +0000, Eugene Bordenkircher wrote:
> > > Agreed,
> > >
> > > We are happy pick up the torch on this, but I'd like to try and hear from
> Joakim first before we do.  The patch set is his, so I'd like to give him the
> opportunity.  I think he's the only one that can add a truly proper description
> as well because he mentioned that this includes a "few more fixes" than just
> the one we ran into.  I'd rather hear from him than try to reverse engineer
> what was being addressed.
> > >
> > > Joakim, if you are still watching the thread, would you like to take a stab
> at it?  If I don't hear from you in a couple days, we'll pick up the torch and do
> what we can.
> > >
> >
> > I am far away from this now and still on 4.19. I don't mind if you tweak
> tweak the patches for better "upstreamability"
> 
> Even better would be to migrate to the chipidea driver, I am told just a few
> tweaks are needed but this is probably something NXP should do as they
> have access to other SOC's using chipidea.

I agree with this direction but the problem was with bandwidth.  As this controller was only used on legacy platforms, it is harder to justify new effort on it now.

Regards,
Leo


^ permalink raw reply

* [PATCH] soc/fsl/qman: test: Make use of the helper function kthread_run_on_cpu()
From: Cai Huoqing @ 2021-12-02 14:07 UTC (permalink / raw)
  To: cai.huoqing; +Cc: linuxppc-dev, linux-kernel, linux-arm-kernel, Li Yang

Replace kthread_create/kthread_bind/wake_up_process() with
kthread_run_on_cpu() to simplify the code.

Signed-off-by: Cai Huoqing <cai.huoqing@linux.dev>
---
 drivers/soc/fsl/qbman/qman_test_stash.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/fsl/qbman/qman_test_stash.c b/drivers/soc/fsl/qbman/qman_test_stash.c
index b7e8e5ec884c..7ab259cb139e 100644
--- a/drivers/soc/fsl/qbman/qman_test_stash.c
+++ b/drivers/soc/fsl/qbman/qman_test_stash.c
@@ -108,14 +108,12 @@ static int on_all_cpus(int (*fn)(void))
 			.fn = fn,
 			.started = ATOMIC_INIT(0)
 		};
-		struct task_struct *k = kthread_create(bstrap_fn, &bstrap,
-			"hotpotato%d", cpu);
+		struct task_struct *k = kthread_run_on_cpu(bstrap_fn, &bstrap,
+							   cpu, "hotpotato/%u");
 		int ret;
 
 		if (IS_ERR(k))
 			return -ENOMEM;
-		kthread_bind(k, cpu);
-		wake_up_process(k);
 		/*
 		 * If we call kthread_stop() before the "wake up" has had an
 		 * effect, then the thread may exit with -EINTR without ever
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH v2 3/3] soc: fsl: Replace kernel.h with the necessary inclusions
From: Andy Shevchenko @ 2021-12-02 21:26 UTC (permalink / raw)
  To: Leo Li
  Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, Qiang Zhao
In-Reply-To: <AS8PR04MB894640E4FF4EB7D01604049E8F699@AS8PR04MB8946.eurprd04.prod.outlook.com>

On Thu, Dec 02, 2021 at 08:01:54PM +0000, Leo Li wrote:
> > From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Sent: Thursday, December 2, 2021 3:33 AM
> > On Wed, Dec 01, 2021 at 01:41:16PM -0600, Li Yang wrote:
> > > On Tue, Nov 23, 2021 at 10:32 AM Andy Shevchenko
> > > <andriy.shevchenko@linux.intel.com> wrote:

...

> > > The build test is good.  I have applied it for next.  Thanks.
> > 
> > Thanks, what about MAINTAINERS updates? I don't see them neither in next
> > nor in your tree.
> 
> I am ok with these MAINTAINERS updates.  I thought you want to send them directly to Linus.  I can take them if you like.

I was just pointing out that it would be good that you (as a maintainer of SOC
FSL) have them applied and pushed for the current cycle, but they are not code
fixes anyway, so it's not critical.

TL;DR: Yes, please take them, thanks!

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH v2 3/3] soc: fsl: Replace kernel.h with the necessary inclusions
From: Li Yang @ 2021-12-02 22:28 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, Qiang Zhao
In-Reply-To: <Yak6Co4lO761HmWG@smile.fi.intel.com>

On Thu, Dec 2, 2021 at 3:30 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> On Thu, Dec 02, 2021 at 08:01:54PM +0000, Leo Li wrote:
> > > From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > > Sent: Thursday, December 2, 2021 3:33 AM
> > > On Wed, Dec 01, 2021 at 01:41:16PM -0600, Li Yang wrote:
> > > > On Tue, Nov 23, 2021 at 10:32 AM Andy Shevchenko
> > > > <andriy.shevchenko@linux.intel.com> wrote:
>
> ...
>
> > > > The build test is good.  I have applied it for next.  Thanks.
> > >
> > > Thanks, what about MAINTAINERS updates? I don't see them neither in next
> > > nor in your tree.
> >
> > I am ok with these MAINTAINERS updates.  I thought you want to send them directly to Linus.  I can take them if you like.
>
> I was just pointing out that it would be good that you (as a maintainer of SOC
> FSL) have them applied and pushed for the current cycle, but they are not code
> fixes anyway, so it's not critical.
>
> TL;DR: Yes, please take them, thanks!

Got it.  Both applied for next.  Thanks.

Regards,
Leo

^ permalink raw reply

* Re: bug: usb: gadget: FSL_UDC_CORE Corrupted request list leads to unrecoverable loop.
From: Joakim Tjernlund @ 2021-12-02 22:45 UTC (permalink / raw)
  To: regressions@leemhuis.info, leoyang.li@nxp.com,
	Eugene_Bordenkircher@selinc.com, linux-usb@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org
  Cc: gregkh@linuxfoundation.org, balbi@kernel.org
In-Reply-To: <AS8PR04MB894614C61E57A80EB4FF7C758F699@AS8PR04MB8946.eurprd04.prod.outlook.com>

On Thu, 2021-12-02 at 20:35 +0000, Leo Li wrote:
> 
> > -----Original Message-----
> > From: Joakim Tjernlund <Joakim.Tjernlund@infinera.com>
> > Sent: Wednesday, December 1, 2021 8:19 AM
> > To: regressions@leemhuis.info; Leo Li <leoyang.li@nxp.com>;
> > Eugene_Bordenkircher@selinc.com; linux-usb@vger.kernel.org; linuxppc-
> > dev@lists.ozlabs.org
> > Cc: gregkh@linuxfoundation.org; balbi@kernel.org
> > Subject: Re: bug: usb: gadget: FSL_UDC_CORE Corrupted request list leads to
> > unrecoverable loop.
> > 
> > On Tue, 2021-11-30 at 12:56 +0100, Joakim Tjernlund wrote:
> > > On Mon, 2021-11-29 at 23:48 +0000, Eugene Bordenkircher wrote:
> > > > Agreed,
> > > > 
> > > > We are happy pick up the torch on this, but I'd like to try and hear from
> > Joakim first before we do.  The patch set is his, so I'd like to give him the
> > opportunity.  I think he's the only one that can add a truly proper description
> > as well because he mentioned that this includes a "few more fixes" than just
> > the one we ran into.  I'd rather hear from him than try to reverse engineer
> > what was being addressed.
> > > > 
> > > > Joakim, if you are still watching the thread, would you like to take a stab
> > at it?  If I don't hear from you in a couple days, we'll pick up the torch and do
> > what we can.
> > > > 
> > > 
> > > I am far away from this now and still on 4.19. I don't mind if you tweak
> > tweak the patches for better "upstreamability"
> > 
> > Even better would be to migrate to the chipidea driver, I am told just a few
> > tweaks are needed but this is probably something NXP should do as they
> > have access to other SOC's using chipidea.
> 
> I agree with this direction but the problem was with bandwidth.  As this controller was only used on legacy platforms, it is harder to justify new effort on it now.
> 

Legacy? All PPC is legacy and not supported now? 

  Jocke

^ permalink raw reply

* Re: [PATCH] of: unmap memory regions in /memreserve node
From: Michael Ellerman @ 2021-12-03  1:11 UTC (permalink / raw)
  To: Mark Rutland, Rob Herring
  Cc: devicetree, linuxppc-dev, Frank Rowand, Calvin Zhang,
	linux-kernel
In-Reply-To: <YaiRAD40xCK7u3Hl@FVFF77S0Q05N>

Mark Rutland <mark.rutland@arm.com> writes:
> On Tue, Nov 30, 2021 at 04:43:31PM -0600, Rob Herring wrote:
>> +linuxppc-dev
 
Sorry missed this until now ...

>> On Wed, Nov 24, 2021 at 09:33:47PM +0800, Calvin Zhang wrote:
>> > Reserved memory regions in /memreserve node aren't and shouldn't
>> > be referenced elsewhere. So mark them no-map to skip direct mapping
>> > for them.
>> 
>> I suspect this has a high chance of breaking some platform. There's no 
>> rule a region can't be accessed.
>
> The subtlety is that the region shouldn't be explicitly accessed (e.g.
> modified),

I think "modified" is the key there, reserved means Linux doesn't use
the range for its own data, but may still read from whatever is in the
range.

On some platforms the initrd will be marked as reserved, which Linux
obviously needs to read from.

> but the OS is permitted to have the region mapped. In ePAPR this is
> described as:
>
>    This requirement is necessary because the client program is permitted to map
>    memory with storage attributes specified as not Write Through Required, not
>    Caching Inhibited, and Memory Coherence Required (i.e., WIMG = 0b001x), and
>    VLE=0 where supported. The client program may use large virtual pages that
>    contain reserved memory. However, the client program may not modify reserved
>    memory, so the boot program may perform accesses to reserved memory as Write
>    Through Required where conflicting values for this storage attribute are
>    architecturally permissible.
>
> Historically arm64 relied upon this for spin-table to work, and I *think* we
> might not need that any more I agree that there's a high chance this will break
> something (especially on 16K or 64K page size kernels), so I'd prefer to leave
> it as-is.

Yeah I agree. On powerpc we still use large pages for the linear mapping
(direct map), so reserved regions will be incidentally mapped as
described above.

> If someone requires no-map behaviour, they should use a /reserved-memory entry
> with a no-map property, which will work today and document their requirement
> explicitly.

+1.

cheers

^ permalink raw reply

* [PATCH V2 2/2] tools/perf: Update global/local variants for p_stage_cyc in powerpc
From: Athira Rajeev @ 2021-12-03  2:20 UTC (permalink / raw)
  To: acme, jolsa
  Cc: maddy, rnsastry, linux-perf-users, kjain, namhyung, linuxppc-dev
In-Reply-To: <20211203022038.48240-1-atrajeev@linux.vnet.ibm.com>

Update the arch_support_sort_key() function in powerpc
to enable presenting local and global variants of sort
key: p_stage_cyc. Update the "se_header" strings for
these in arch_perf_header_entry() function along with
instruction latency.

Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Reported-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/arch/powerpc/util/event.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/perf/arch/powerpc/util/event.c b/tools/perf/arch/powerpc/util/event.c
index 3bf441257466..cf430a4c55b9 100644
--- a/tools/perf/arch/powerpc/util/event.c
+++ b/tools/perf/arch/powerpc/util/event.c
@@ -40,8 +40,12 @@ const char *arch_perf_header_entry(const char *se_header)
 {
 	if (!strcmp(se_header, "Local INSTR Latency"))
 		return "Finish Cyc";
-	else if (!strcmp(se_header, "Pipeline Stage Cycle"))
+	else if (!strcmp(se_header, "INSTR Latency"))
+		return "Global Finish_cyc";
+	else if (!strcmp(se_header, "Local Pipeline Stage Cycle"))
 		return "Dispatch Cyc";
+	else if (!strcmp(se_header, "Pipeline Stage Cycle"))
+		return "Global Dispatch_cyc";
 	return se_header;
 }
 
@@ -49,5 +53,7 @@ int arch_support_sort_key(const char *sort_key)
 {
 	if (!strcmp(sort_key, "p_stage_cyc"))
 		return 1;
+	if (!strcmp(sort_key, "local_p_stage_cyc"))
+		return 1;
 	return 0;
 }
-- 
2.33.0


^ permalink raw reply related

* [PATCH V2 1/2] tools/perf: Include global and local variants for p_stage_cyc sort key
From: Athira Rajeev @ 2021-12-03  2:20 UTC (permalink / raw)
  To: acme, jolsa
  Cc: maddy, rnsastry, linux-perf-users, kjain, namhyung, linuxppc-dev

Sort key p_stage_cyc is used to present the latency
cycles spend in pipeline stages. perf tool has local
p_stage_cyc sort key to display this info. There is no
global variant available for this sort key. local variant
shows latency in a sinlge sample, whereas, global value
will be useful to present the total latency (sum of
latencies) in the hist entry. It represents latency
number multiplied by the number of samples.

Add global (p_stage_cyc) and local variant
(local_p_stage_cyc) for this sort key. Use the
local_p_stage_cyc as default option for "mem" sort mode.
Also add this to list of dynamic sort keys and made the
"dynamic_headers" and "arch_specific_sort_keys" as static.

Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Reported-by: Namhyung Kim <namhyung@kernel.org>
---
Changelog:
v1 -> v2:
 Addressed review comments from Jiri by making the
 "dynamic_headers" and "arch_specific_sort_keys"
 as static.

 tools/perf/util/hist.c |  4 +++-
 tools/perf/util/hist.h |  3 ++-
 tools/perf/util/sort.c | 34 +++++++++++++++++++++++++---------
 tools/perf/util/sort.h |  3 ++-
 4 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b776465e04ef..0a8033b09e28 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -211,7 +211,9 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
 	hists__new_col_len(hists, HISTC_MEM_BLOCKED, 10);
 	hists__new_col_len(hists, HISTC_LOCAL_INS_LAT, 13);
 	hists__new_col_len(hists, HISTC_GLOBAL_INS_LAT, 13);
-	hists__new_col_len(hists, HISTC_P_STAGE_CYC, 13);
+	hists__new_col_len(hists, HISTC_LOCAL_P_STAGE_CYC, 13);
+	hists__new_col_len(hists, HISTC_GLOBAL_P_STAGE_CYC, 13);
+
 	if (symbol_conf.nanosecs)
 		hists__new_col_len(hists, HISTC_TIME, 16);
 	else
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 621f35ae1efa..2a15e22fb89c 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -75,7 +75,8 @@ enum hist_column {
 	HISTC_MEM_BLOCKED,
 	HISTC_LOCAL_INS_LAT,
 	HISTC_GLOBAL_INS_LAT,
-	HISTC_P_STAGE_CYC,
+	HISTC_LOCAL_P_STAGE_CYC,
+	HISTC_GLOBAL_P_STAGE_CYC,
 	HISTC_NR_COLS, /* Last entry */
 };
 
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index a111065b484e..e417e47f51b9 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -37,7 +37,7 @@ const char	default_parent_pattern[] = "^sys_|^do_page_fault";
 const char	*parent_pattern = default_parent_pattern;
 const char	*default_sort_order = "comm,dso,symbol";
 const char	default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles";
-const char	default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked,blocked,local_ins_lat,p_stage_cyc";
+const char	default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked,blocked,local_ins_lat,local_p_stage_cyc";
 const char	default_top_sort_order[] = "dso,symbol";
 const char	default_diff_sort_order[] = "dso,symbol";
 const char	default_tracepoint_sort_order[] = "trace";
@@ -46,8 +46,8 @@ const char	*field_order;
 regex_t		ignore_callees_regex;
 int		have_ignore_callees = 0;
 enum sort_mode	sort__mode = SORT_MODE__NORMAL;
-const char	*dynamic_headers[] = {"local_ins_lat", "p_stage_cyc"};
-const char	*arch_specific_sort_keys[] = {"p_stage_cyc"};
+static const char *const dynamic_headers[] = {"local_ins_lat", "ins_lat", "local_p_stage_cyc", "p_stage_cyc"};
+static const char *const arch_specific_sort_keys[] = {"local_p_stage_cyc", "p_stage_cyc"};
 
 /*
  * Replaces all occurrences of a char used with the:
@@ -1392,22 +1392,37 @@ struct sort_entry sort_global_ins_lat = {
 };
 
 static int64_t
-sort__global_p_stage_cyc_cmp(struct hist_entry *left, struct hist_entry *right)
+sort__p_stage_cyc_cmp(struct hist_entry *left, struct hist_entry *right)
 {
 	return left->p_stage_cyc - right->p_stage_cyc;
 }
 
+static int hist_entry__global_p_stage_cyc_snprintf(struct hist_entry *he, char *bf,
+					size_t size, unsigned int width)
+{
+	return repsep_snprintf(bf, size, "%-*u", width,
+			he->p_stage_cyc * he->stat.nr_events);
+}
+
+
 static int hist_entry__p_stage_cyc_snprintf(struct hist_entry *he, char *bf,
 					size_t size, unsigned int width)
 {
 	return repsep_snprintf(bf, size, "%-*u", width, he->p_stage_cyc);
 }
 
-struct sort_entry sort_p_stage_cyc = {
-	.se_header      = "Pipeline Stage Cycle",
-	.se_cmp         = sort__global_p_stage_cyc_cmp,
+struct sort_entry sort_local_p_stage_cyc = {
+	.se_header      = "Local Pipeline Stage Cycle",
+	.se_cmp         = sort__p_stage_cyc_cmp,
 	.se_snprintf	= hist_entry__p_stage_cyc_snprintf,
-	.se_width_idx	= HISTC_P_STAGE_CYC,
+	.se_width_idx	= HISTC_LOCAL_P_STAGE_CYC,
+};
+
+struct sort_entry sort_global_p_stage_cyc = {
+	.se_header      = "Pipeline Stage Cycle",
+	.se_cmp         = sort__p_stage_cyc_cmp,
+	.se_snprintf    = hist_entry__global_p_stage_cyc_snprintf,
+	.se_width_idx   = HISTC_GLOBAL_P_STAGE_CYC,
 };
 
 struct sort_entry sort_mem_daddr_sym = {
@@ -1858,7 +1873,8 @@ static struct sort_dimension common_sort_dimensions[] = {
 	DIM(SORT_CODE_PAGE_SIZE, "code_page_size", sort_code_page_size),
 	DIM(SORT_LOCAL_INS_LAT, "local_ins_lat", sort_local_ins_lat),
 	DIM(SORT_GLOBAL_INS_LAT, "ins_lat", sort_global_ins_lat),
-	DIM(SORT_PIPELINE_STAGE_CYC, "p_stage_cyc", sort_p_stage_cyc),
+	DIM(SORT_LOCAL_PIPELINE_STAGE_CYC, "local_p_stage_cyc", sort_local_p_stage_cyc),
+	DIM(SORT_GLOBAL_PIPELINE_STAGE_CYC, "p_stage_cyc", sort_global_p_stage_cyc),
 };
 
 #undef DIM
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 7b7145501933..f994261888e1 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -235,7 +235,8 @@ enum sort_type {
 	SORT_CODE_PAGE_SIZE,
 	SORT_LOCAL_INS_LAT,
 	SORT_GLOBAL_INS_LAT,
-	SORT_PIPELINE_STAGE_CYC,
+	SORT_LOCAL_PIPELINE_STAGE_CYC,
+	SORT_GLOBAL_PIPELINE_STAGE_CYC,
 
 	/* branch stack specific sort keys */
 	__SORT_BRANCH_STACK,
-- 
2.33.0


^ permalink raw reply related

* Re: [PATCH] powerpc/32s: Allocate one 256k IBAT instead of two consecutives 128k IBATs
From: Michael Ellerman @ 2021-12-03  3:55 UTC (permalink / raw)
  To: Christophe Leroy, Benjamin Herrenschmidt, Paul Mackerras
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <ab58b296832b0ec650e2203200e060adbcb2677d.1637930421.git.christophe.leroy@csgroup.eu>

Christophe Leroy <christophe.leroy@csgroup.eu> writes:
> Today we have the following IBATs allocated:
>
> 	---[ Instruction Block Address Translation ]---
> 	0: 0xc0000000-0xc03fffff 0x00000000         4M Kernel   x     m
> 	1: 0xc0400000-0xc05fffff 0x00400000         2M Kernel   x     m
> 	2: 0xc0600000-0xc06fffff 0x00600000         1M Kernel   x     m
> 	3: 0xc0700000-0xc077ffff 0x00700000       512K Kernel   x     m
> 	4: 0xc0780000-0xc079ffff 0x00780000       128K Kernel   x     m
> 	5: 0xc07a0000-0xc07bffff 0x007a0000       128K Kernel   x     m
> 	6:         -
> 	7:         -
>
> The two 128K should be a single 256K instead.
>
> When _etext is not aligned to 128Kbytes, the system will allocate
> all necessary BATs to the lower 128Kbytes boundary, then allocate
> an additional 128Kbytes BAT for the remaining block.
>
> Instead, align the top to 128Kbytes so that the function directly
> allocates a 256Mbytes last block:
                 ^

I think that's meant to be 256Kbytes, I changed it when committing.

> 	---[ Instruction Block Address Translation ]---
> 	0: 0xc0000000-0xc03fffff 0x00000000         4M Kernel   x     m
> 	1: 0xc0400000-0xc05fffff 0x00400000         2M Kernel   x     m
> 	2: 0xc0600000-0xc06fffff 0x00600000         1M Kernel   x     m
> 	3: 0xc0700000-0xc077ffff 0x00700000       512K Kernel   x     m
> 	4: 0xc0780000-0xc07bffff 0x00780000       256K Kernel   x     m
> 	5:         -
> 	6:         -
> 	7:         -
>
> Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>


cheers

^ permalink raw reply

* [RFC PATCH 11/14] powerpc/crash_dump: Use the new interface copy_oldmem_page_buf
From: Amit Daniel Kachhap @ 2021-12-03 10:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: Kevin Brodsky, kexec, Amit Daniel Kachhap, Paul Mackerras,
	linux-fsdevel, Vincenzo Frascino, linuxppc, Christoph Hellwig
In-Reply-To: <20211203104231.17597-1-amit.kachhap@arm.com>

The current interface copy_oldmem_page() passes user pointer without
__user annotation and hence does unnecessary user/kernel pointer
conversions during its implementation.

Use the interface copy_oldmem_page_buf() to avoid this issue.

Cc: Michael Ellerman <mpe@ellerman.id.au>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc <linuxppc-dev@lists.ozlabs.org>
Signed-off-by: Amit Daniel Kachhap <amit.kachhap@arm.com>
---
 arch/powerpc/kernel/crash_dump.c | 33 ++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 5693e1c67c2b..a1c8a3a11694 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -68,33 +68,34 @@ void __init setup_kdump_trampoline(void)
 }
 #endif /* CONFIG_NONSTATIC_KERNEL */
 
-static size_t copy_oldmem_vaddr(void *vaddr, char *buf, size_t csize,
-                               unsigned long offset, int userbuf)
+static size_t copy_oldmem_vaddr(void *vaddr, char __user *ubuf, char *kbuf,
+				size_t csize, unsigned long offset)
 {
-	if (userbuf) {
-		if (copy_to_user((char __user *)buf, (vaddr + offset), csize))
+	if (ubuf) {
+		if (copy_to_user(ubuf, (vaddr + offset), csize))
 			return -EFAULT;
 	} else
-		memcpy(buf, (vaddr + offset), csize);
+		memcpy(kbuf, (vaddr + offset), csize);
 
 	return csize;
 }
 
 /**
- * copy_oldmem_page - copy one page from "oldmem"
+ * copy_oldmem_page_buf - copy one page from "oldmem"
  * @pfn: page frame number to be copied
- * @buf: target memory address for the copy; this can be in kernel address
- *      space or user address space (see @userbuf)
+ * @ubuf: target user memory address for the copy; use copy_to_user() if this
+ * address is present
+ * @kbuf: target kernel memory address for the copy; use memcpy() if this
+ * address is present
  * @csize: number of bytes to copy
  * @offset: offset in bytes into the page (based on pfn) to begin the copy
- * @userbuf: if set, @buf is in user address space, use copy_to_user(),
- *      otherwise @buf is in kernel address space, use memcpy().
  *
- * Copy a page from "oldmem". For this page, there is no pte mapped
- * in the current kernel. We stitch up a pte, similar to kmap_atomic.
+ * Copy a page from "oldmem" into buffer pointed by either @ubuf or @kbuf. For
+ * this page, there is no pte mapped in the current kernel. We stitch up a pte,
+ * similar to kmap_atomic.
  */
-ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
-			size_t csize, unsigned long offset, int userbuf)
+ssize_t copy_oldmem_page_buf(unsigned long pfn, char __user *ubuf, char *kbuf,
+			     size_t csize, unsigned long offset)
 {
 	void  *vaddr;
 	phys_addr_t paddr;
@@ -107,10 +108,10 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
 
 	if (memblock_is_region_memory(paddr, csize)) {
 		vaddr = __va(paddr);
-		csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
+		csize = copy_oldmem_vaddr(vaddr, ubuf, kbuf, csize, offset);
 	} else {
 		vaddr = ioremap_cache(paddr, PAGE_SIZE);
-		csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
+		csize = copy_oldmem_vaddr(vaddr, ubuf, kbuf, csize, offset);
 		iounmap(vaddr);
 	}
 
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH] powerpc/85xx: fix oops when CONFIG_FSL_PMC=n
From: Michael Ellerman @ 2021-12-03 11:53 UTC (permalink / raw)
  To: benh, chunkeey, gregkh, hurricos, chenhui.zhao, stable,
	Xiaoming Ni, wangle6, linuxppc-dev, mpe, oss, paulus,
	chenjianguo3, linux-kernel, liuwenliang, Yuantian.Tang,
	paul.gortmaker
In-Reply-To: <20211126041153.16926-1-nixiaoming@huawei.com>

On Fri, 26 Nov 2021 12:11:53 +0800, Xiaoming Ni wrote:
> When CONFIG_FSL_PMC is set to n, no value is assigned to cpu_up_prepare
>  in the mpc85xx_pm_ops structure. As a result, oops is triggered in
>  smp_85xx_start_cpu().
> 
> 	[    0.627233] smp: Bringing up secondary CPUs ...
> 	[    0.681659] kernel tried to execute user page (0) - exploit attempt? (uid: 0)
> 	[    0.766618] BUG: Unable to handle kernel instruction fetch (NULL pointer?)
> 	[    0.848899] Faulting instruction address: 0x00000000
> 	[    0.908273] Oops: Kernel access of bad area, sig: 11 [#1]
> 	...
> 	[    1.758220] NIP [00000000] 0x0
> 	[    1.794688] LR [c0021d2c] smp_85xx_kick_cpu+0xe8/0x568
> 	[    1.856126] Call Trace:
> 	[    1.885295] [c1051da8] [c0021cb8] smp_85xx_kick_cpu+0x74/0x568 (unreliable)
> 	[    1.968633] [c1051de8] [c0011460] __cpu_up+0xc0/0x228
> 	[    2.029038] [c1051e18] [c0031bbc] bringup_cpu+0x30/0x224
> 	[    2.092572] [c1051e48] [c0031f3c] cpu_up.constprop.0+0x180/0x33c
> 	[    2.164443] [c1051e88] [c00322e8] bringup_nonboot_cpus+0x88/0xc8
> 	[    2.236326] [c1051eb8] [c07e67bc] smp_init+0x30/0x78
> 	[    2.295698] [c1051ed8] [c07d9e28] kernel_init_freeable+0x118/0x2a8
> 	[    2.369641] [c1051f18] [c00032d8] kernel_init+0x14/0x124
> 	[    2.433176] [c1051f38] [c0010278] ret_from_kernel_thread+0x14/0x1c
> 
> [...]

Applied to powerpc/fixes.

[1/1] powerpc/85xx: fix oops when CONFIG_FSL_PMC=n
      https://git.kernel.org/powerpc/c/3dc709e518b47386e6af937eaec37bb36539edfd

cheers

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox