| From: Michael Ellerman <mpe@ellerman.id.au> |
| Date: Mon, 16 Apr 2018 23:25:19 +1000 |
| Subject: powerpc/lib: Fix off-by-one in alternate feature patching |
| |
| commit b8858581febb050688e276b956796bc4a78299ed upstream. |
| |
| 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") |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| arch/powerpc/lib/feature-fixups.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/arch/powerpc/lib/feature-fixups.c |
| +++ b/arch/powerpc/lib/feature-fixups.c |
| @@ -52,7 +52,7 @@ static int patch_alt_instruction(unsigne |
| 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; |