All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5] powerpc/lib: Fix off-by-one in alternate feature patching
@ 2018-04-16 14:39 Michael Ellerman
  2018-04-16 14:39 ` [PATCH 2/5] powerpc/lib: Fix feature fixup test of external branch Michael Ellerman
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Michael Ellerman @ 2018-04-16 14:39 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, aik

When we patch an alternate feature section, we have to adjust any
relative branches that branch out of the alternate section.

But currently we have a bug if we have a branch that points to past
the last instruction of the alternate section, eg:

  FTR_SECTION_ELSE
  1:     b       2f
         or      6,6,6
  2:
  ALT_FTR_SECTION_END(...)
         nop

This will result in a relative branch at 1 with a target that equals
the end of the alternate section.

That branch does not need adjusting when it's moved to the non-else
location. Currently we do adjust it, resulting in a branch that goes
off into the link-time location of the else section, which is junk.

The fix is to not patch branches that have a target == end of the
alternate section.

Fixes: d20fe50a7b3c ("KVM: PPC: Book3S HV: Branch inside feature section")
Fixes: 9b1a735de64c ("powerpc: Add logic to patch alternative feature sections")
Cc: stable@vger.kernel.org # v2.6.27+
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/lib/feature-fixups.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 35f80ab7cbd8..288fe4f0db4e 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -55,7 +55,7 @@ static int patch_alt_instruction(unsigned int *src, unsigned int *dest,
 		unsigned int *target = (unsigned int *)branch_target(src);
 
 		/* Branch within the section doesn't need translating */
-		if (target < alt_start || target >= alt_end) {
+		if (target < alt_start || target > alt_end) {
 			instr = translate_branch(dest, src);
 			if (!instr)
 				return 1;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] powerpc/lib: Fix feature fixup test of external branch
  2018-04-16 14:39 [PATCH 1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman
@ 2018-04-16 14:39 ` Michael Ellerman
  2018-05-16 13:38   ` [2/5] " Michael Ellerman
  2018-04-16 14:39 ` [PATCH 3/5] powerpc/lib: Fix the feature fixup tests to actually work Michael Ellerman
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: Michael Ellerman @ 2018-04-16 14:39 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, aik

The expected case for this test was wrong, the source of the alternate
code sequence is:

  FTR_SECTION_ELSE
  2:	or	2,2,2
  	PPC_LCMPI	r3,1
  	beq	3f
  	blt	2b
  	b	3f
  	b	1b
  ALT_FTR_SECTION_END(0, 1)
  3:	or	1,1,1
  	or	2,2,2
  4:	or	3,3,3

So when it's patched the '3' label should still be on the 'or 1,1,1',
and the 4 label is irrelevant and can be removed.

Fixes: 362e7701fd18 ("powerpc: Add self-tests of the feature fixup code")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/lib/feature-fixups-test.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/lib/feature-fixups-test.S b/arch/powerpc/lib/feature-fixups-test.S
index f4613118132e..12ff0f673956 100644
--- a/arch/powerpc/lib/feature-fixups-test.S
+++ b/arch/powerpc/lib/feature-fixups-test.S
@@ -167,9 +167,9 @@ globl(ftr_fixup_test6_expected)
 	blt	2b
 	b	3f
 	b	1b
-2:	or	1,1,1
+3:	or	1,1,1
 	or	2,2,2
-3:	or	3,3,3
+	or	3,3,3
 
 
 #if 0
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] powerpc/lib: Fix the feature fixup tests to actually work
  2018-04-16 14:39 [PATCH 1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman
  2018-04-16 14:39 ` [PATCH 2/5] powerpc/lib: Fix feature fixup test of external branch Michael Ellerman
@ 2018-04-16 14:39 ` Michael Ellerman
  2018-04-16 14:39 ` [PATCH 4/5] powerpc/lib: Rename ftr_fixup_test7 to ftr_fixup_test_too_big Michael Ellerman
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2018-04-16 14:39 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, aik

The code patching code has always been a bit confused about whether
it's best to use void *, unsigned int *, char *, etc. to point to
instructions. In fact in the feature fixups tests we use both unsigned
int[] and u8[] in different places.

Unfortunately the tests that use unsigned int[] calculate the size of
the code blocks using subtraction of those unsigned int pointers, and
then pass the result to memcmp(). This means we're only comparing 1/4
of the bytes we need to, because we need to multiply by
sizeof(unsigned int) to get the number of *bytes*.

The result is that the tests do all the patching and then only compare
some of the resulting code, so patching bugs that only effect that
last 3/4 of the code could slip through undetected. It turns out that
hasn't been happening, although one test had a bad expected case (see
previous commit).

Fix it for now by multiplying the size by 4 in the affected functions.

Fixes: 362e7701fd18 ("powerpc: Add self-tests of the feature fixup code")
Epic-brown-paper-bag-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/lib/feature-fixups.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 288fe4f0db4e..097b45bd9de4 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -285,7 +285,7 @@ static void test_basic_patching(void)
 	extern unsigned int end_ftr_fixup_test1[];
 	extern unsigned int ftr_fixup_test1_orig[];
 	extern unsigned int ftr_fixup_test1_expected[];
-	int size = end_ftr_fixup_test1 - ftr_fixup_test1;
+	int size = 4 * (end_ftr_fixup_test1 - ftr_fixup_test1);
 
 	fixup.value = fixup.mask = 8;
 	fixup.start_off = calc_offset(&fixup, ftr_fixup_test1 + 1);
@@ -317,7 +317,7 @@ static void test_alternative_patching(void)
 	extern unsigned int ftr_fixup_test2_orig[];
 	extern unsigned int ftr_fixup_test2_alt[];
 	extern unsigned int ftr_fixup_test2_expected[];
-	int size = end_ftr_fixup_test2 - ftr_fixup_test2;
+	int size = 4 * (end_ftr_fixup_test2 - ftr_fixup_test2);
 
 	fixup.value = fixup.mask = 0xF;
 	fixup.start_off = calc_offset(&fixup, ftr_fixup_test2 + 1);
@@ -349,7 +349,7 @@ static void test_alternative_case_too_big(void)
 	extern unsigned int end_ftr_fixup_test3[];
 	extern unsigned int ftr_fixup_test3_orig[];
 	extern unsigned int ftr_fixup_test3_alt[];
-	int size = end_ftr_fixup_test3 - ftr_fixup_test3;
+	int size = 4 * (end_ftr_fixup_test3 - ftr_fixup_test3);
 
 	fixup.value = fixup.mask = 0xC;
 	fixup.start_off = calc_offset(&fixup, ftr_fixup_test3 + 1);
@@ -376,7 +376,7 @@ static void test_alternative_case_too_small(void)
 	extern unsigned int ftr_fixup_test4_orig[];
 	extern unsigned int ftr_fixup_test4_alt[];
 	extern unsigned int ftr_fixup_test4_expected[];
-	int size = end_ftr_fixup_test4 - ftr_fixup_test4;
+	int size = 4 * (end_ftr_fixup_test4 - ftr_fixup_test4);
 	unsigned long flag;
 
 	/* Check a high-bit flag */
@@ -410,7 +410,7 @@ static void test_alternative_case_with_branch(void)
 	extern unsigned int ftr_fixup_test5[];
 	extern unsigned int end_ftr_fixup_test5[];
 	extern unsigned int ftr_fixup_test5_expected[];
-	int size = end_ftr_fixup_test5 - ftr_fixup_test5;
+	int size = 4 * (end_ftr_fixup_test5 - ftr_fixup_test5);
 
 	check(memcmp(ftr_fixup_test5, ftr_fixup_test5_expected, size) == 0);
 }
@@ -420,7 +420,7 @@ static void test_alternative_case_with_external_branch(void)
 	extern unsigned int ftr_fixup_test6[];
 	extern unsigned int end_ftr_fixup_test6[];
 	extern unsigned int ftr_fixup_test6_expected[];
-	int size = end_ftr_fixup_test6 - ftr_fixup_test6;
+	int size = 4 * (end_ftr_fixup_test6 - ftr_fixup_test6);
 
 	check(memcmp(ftr_fixup_test6, ftr_fixup_test6_expected, size) == 0);
 }
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] powerpc/lib: Rename ftr_fixup_test7 to ftr_fixup_test_too_big
  2018-04-16 14:39 [PATCH 1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman
  2018-04-16 14:39 ` [PATCH 2/5] powerpc/lib: Fix feature fixup test of external branch Michael Ellerman
  2018-04-16 14:39 ` [PATCH 3/5] powerpc/lib: Fix the feature fixup tests to actually work Michael Ellerman
@ 2018-04-16 14:39 ` Michael Ellerman
  2018-04-16 14:39 ` [PATCH 5/5] powerpc/lib: Add alt patching test of branching past the last instruction Michael Ellerman
  2018-04-17 10:13 ` [1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman
  4 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2018-04-16 14:39 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, aik

We want this to remain the last test (because it's disabled by
default), so give it a non-numbered name so we don't have to renumber
it when adding new tests before it.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/lib/feature-fixups-test.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/lib/feature-fixups-test.S b/arch/powerpc/lib/feature-fixups-test.S
index 12ff0f673956..dd05afcbcde3 100644
--- a/arch/powerpc/lib/feature-fixups-test.S
+++ b/arch/powerpc/lib/feature-fixups-test.S
@@ -176,7 +176,7 @@ globl(ftr_fixup_test6_expected)
 /* Test that if we have a larger else case the assembler spots it and
  * reports an error. #if 0'ed so as not to break the build normally.
  */
-ftr_fixup_test7:
+ftr_fixup_test_too_big:
 	or	1,1,1
 BEGIN_FTR_SECTION
 	or	2,2,2
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] powerpc/lib: Add alt patching test of branching past the last instruction
  2018-04-16 14:39 [PATCH 1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman
                   ` (2 preceding siblings ...)
  2018-04-16 14:39 ` [PATCH 4/5] powerpc/lib: Rename ftr_fixup_test7 to ftr_fixup_test_too_big Michael Ellerman
@ 2018-04-16 14:39 ` Michael Ellerman
  2018-04-17 10:13 ` [1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman
  4 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2018-04-16 14:39 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, aik

Add a test of the relative branch patching logic in the alternate
section feature fixup code. This tests that if we branch past the last
instruction of the alternate section, the branch is not patched.
That's because the assembler will have created a branch that already
points to the first instruction after the patched section, which is
correct and needs no further patching.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/lib/feature-fixups-test.S | 36 ++++++++++++++++++++++++++++++++++
 arch/powerpc/lib/feature-fixups.c      | 11 +++++++++++
 2 files changed, 47 insertions(+)

diff --git a/arch/powerpc/lib/feature-fixups-test.S b/arch/powerpc/lib/feature-fixups-test.S
index dd05afcbcde3..f16cec989506 100644
--- a/arch/powerpc/lib/feature-fixups-test.S
+++ b/arch/powerpc/lib/feature-fixups-test.S
@@ -171,6 +171,42 @@ globl(ftr_fixup_test6_expected)
 	or	2,2,2
 	or	3,3,3
 
+globl(ftr_fixup_test7)
+	or	1,1,1
+BEGIN_FTR_SECTION
+	or	2,2,2
+	or	2,2,2
+	or	2,2,2
+	or	2,2,2
+	or	2,2,2
+	or	2,2,2
+	or	2,2,2
+FTR_SECTION_ELSE
+2:	b	3f
+3:	or	5,5,5
+	beq	3b
+	b	1f
+	or	6,6,6
+	b	2b
+	bdnz	3b
+1:
+ALT_FTR_SECTION_END(0, 1)
+	or	1,1,1
+	or	1,1,1
+
+globl(end_ftr_fixup_test7)
+	nop
+
+globl(ftr_fixup_test7_expected)
+	or	1,1,1
+2:	b	3f
+3:	or	5,5,5
+	beq	3b
+	b	1f
+	or	6,6,6
+	b	2b
+	bdnz	3b
+1:	or	1,1,1
 
 #if 0
 /* Test that if we have a larger else case the assembler spots it and
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 097b45bd9de4..f3e46d4edd72 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -425,6 +425,16 @@ static void test_alternative_case_with_external_branch(void)
 	check(memcmp(ftr_fixup_test6, ftr_fixup_test6_expected, size) == 0);
 }
 
+static void test_alternative_case_with_branch_to_end(void)
+{
+	extern unsigned int ftr_fixup_test7[];
+	extern unsigned int end_ftr_fixup_test7[];
+	extern unsigned int ftr_fixup_test7_expected[];
+	int size = 4 * (end_ftr_fixup_test7 - ftr_fixup_test7);
+
+	check(memcmp(ftr_fixup_test7, ftr_fixup_test7_expected, size) == 0);
+}
+
 static void test_cpu_macros(void)
 {
 	extern u8 ftr_fixup_test_FTR_macros[];
@@ -480,6 +490,7 @@ static int __init test_feature_fixups(void)
 	test_alternative_case_too_small();
 	test_alternative_case_with_branch();
 	test_alternative_case_with_external_branch();
+	test_alternative_case_with_branch_to_end();
 	test_cpu_macros();
 	test_fw_macros();
 	test_lwsync_macros();
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [1/5] powerpc/lib: Fix off-by-one in alternate feature patching
  2018-04-16 14:39 [PATCH 1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman
                   ` (3 preceding siblings ...)
  2018-04-16 14:39 ` [PATCH 5/5] powerpc/lib: Add alt patching test of branching past the last instruction Michael Ellerman
@ 2018-04-17 10:13 ` Michael Ellerman
  4 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2018-04-17 10:13 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev; +Cc: aik, paulus

On Mon, 2018-04-16 at 14:39:01 UTC, Michael Ellerman wrote:
> When we patch an alternate feature section, we have to adjust any
> relative branches that branch out of the alternate section.
> 
> But currently we have a bug if we have a branch that points to past
> the last instruction of the alternate section, eg:
> 
>   FTR_SECTION_ELSE
>   1:     b       2f
>          or      6,6,6
>   2:
>   ALT_FTR_SECTION_END(...)
>          nop
> 
> This will result in a relative branch at 1 with a target that equals
> the end of the alternate section.
> 
> That branch does not need adjusting when it's moved to the non-else
> location. Currently we do adjust it, resulting in a branch that goes
> off into the link-time location of the else section, which is junk.
> 
> The fix is to not patch branches that have a target == end of the
> alternate section.
> 
> Fixes: d20fe50a7b3c ("KVM: PPC: Book3S HV: Branch inside feature section")
> Fixes: 9b1a735de64c ("powerpc: Add logic to patch alternative feature sections")
> Cc: stable@vger.kernel.org # v2.6.27+
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

Applied to powerpc fixes.

https://git.kernel.org/powerpc/c/b8858581febb050688e276b956796b

cheers

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [2/5] powerpc/lib: Fix feature fixup test of external branch
  2018-04-16 14:39 ` [PATCH 2/5] powerpc/lib: Fix feature fixup test of external branch Michael Ellerman
@ 2018-05-16 13:38   ` Michael Ellerman
  0 siblings, 0 replies; 7+ messages in thread
From: Michael Ellerman @ 2018-05-16 13:38 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev; +Cc: aik, paulus

On Mon, 2018-04-16 at 14:39:02 UTC, Michael Ellerman wrote:
> The expected case for this test was wrong, the source of the alternate
> code sequence is:
> 
>   FTR_SECTION_ELSE
>   2:	or	2,2,2
>   	PPC_LCMPI	r3,1
>   	beq	3f
>   	blt	2b
>   	b	3f
>   	b	1b
>   ALT_FTR_SECTION_END(0, 1)
>   3:	or	1,1,1
>   	or	2,2,2
>   4:	or	3,3,3
> 
> So when it's patched the '3' label should still be on the 'or 1,1,1',
> and the 4 label is irrelevant and can be removed.
> 
> Fixes: 362e7701fd18 ("powerpc: Add self-tests of the feature fixup code")
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

Patches 2-5 applied to powerpc next.

https://git.kernel.org/powerpc/c/32810d91325ec76b8ef4df463f8a0e

cheers

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-05-16 13:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-16 14:39 [PATCH 1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman
2018-04-16 14:39 ` [PATCH 2/5] powerpc/lib: Fix feature fixup test of external branch Michael Ellerman
2018-05-16 13:38   ` [2/5] " Michael Ellerman
2018-04-16 14:39 ` [PATCH 3/5] powerpc/lib: Fix the feature fixup tests to actually work Michael Ellerman
2018-04-16 14:39 ` [PATCH 4/5] powerpc/lib: Rename ftr_fixup_test7 to ftr_fixup_test_too_big Michael Ellerman
2018-04-16 14:39 ` [PATCH 5/5] powerpc/lib: Add alt patching test of branching past the last instruction Michael Ellerman
2018-04-17 10:13 ` [1/5] powerpc/lib: Fix off-by-one in alternate feature patching Michael Ellerman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.