[PATCH] arm64/alternatives: use subsections for replacement sequences
Alexandru Elisei
alexandru.elisei at arm.com
Thu Jul 9 08:48:51 EDT 2020
Hi Ard,
Thank you so much for your quick reply!
On 7/9/20 1:39 PM, Ard Biesheuvel wrote:
> On Thu, 9 Jul 2020 at 15:31, Ard Biesheuvel <ardb at kernel.org> wrote:
>> On Thu, 9 Jul 2020 at 14:11, Alexandru Elisei <alexandru.elisei at arm.com> wrote:
>>> Hi,
>>>
>> Hi Alex,
>>
>> Apologies for the breakage.
>>
>>
>>> I should post the entire boot log:
>> ...
>>> [ 0.002204] pc : work_pending+0x32c/0x348
>> This suggests that you ended executing directly from the alternatives
>> replacement section that gets appended to the end of work_pending (and
>> therefore gets mistaken for being part of it)
>>
>> It appears that the following code in alternatives.c
>>
>> static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
>> {
>> unsigned long replptr;
>>
>> if (kernel_text_address(pc))
>> return true;
>>
>> returns true inadvertently for the branch in this piece of code in entry.S
>>
>> alternative_if ARM64_HAS_IRQ_PRIO_MASKING
>> ldr x20, [sp, #S_PMR_SAVE]
>> msr_s SYS_ICC_PMR_EL1, x20
>> mrs_s x21, SYS_ICC_CTLR_EL1
>> tbz x21, #6, .L__skip_pmr_sync\@ // Check for ICC_CTLR_EL1.PMHE
>> dsb sy // Ensure priority change is seen by redistributor
>> .L__skip_pmr_sync\@:
>>
>>
>> due to the fact that kernel_text_address() has no way of
>> distinguishing branches inside the subsection from branches that
>> require updating. So the alternatives patching code dutifully updates
>> the tbz opcode and points it to its original target in the subsection.
>>
>> This is going to be rather tricky to fix, unless we special case
>> tbz/cbz branches and other branches with limited range that would
>> never have worked before anyway.
>>
>> For now, better to just revert it and revisit it later.
>>
> ... unless we decide to fix up all branches pointing outside the
> replacement sequence, which is not an entirely unreasonable thing to
> do:
>
> diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
> index d1757ef1b1e7..7c205f9202a3 100644
> --- a/arch/arm64/kernel/alternative.c
> +++ b/arch/arm64/kernel/alternative.c
> @@ -45,18 +45,11 @@
> {
> unsigned long replptr;
>
> - if (kernel_text_address(pc))
> - return true;
> -
> replptr = (unsigned long)ALT_REPL_PTR(alt);
> if (pc >= replptr && pc <= (replptr + alt->alt_len))
> return false;
>
> - /*
> - * Branching into *another* alternate sequence is doomed, and
> - * we're not even trying to fix it up.
> - */
> - BUG();
> + return true;
> }
Both fixes work for me. I've been running some tests on my rockpro64 with your
patch reverted, so that definitely fixes the issue. With the above diff applied, I
was able to boot and run some PMU tests using NMIs.
Thanks,
Alex
More information about the linux-arm-kernel
mailing list