Commit be286b86 authored by Rohan McLure's avatar Rohan McLure Committed by Michael Ellerman
Browse files

powerpc: Mark [h]ssr_valid accesses in check_return_regs_valid



Checks to see if the [H]SRR registers have been clobbered by (soft)
NMI interrupts imply the possibility for a data race on the
[h]srr_valid entries in the PACA. Annotate accesses to these fields with
READ_ONCE, removing the need for the barrier.

The diagnostic can use plain-access reads and writes, but annotate with
data_race.

Signed-off-by: default avatarRohan McLure <rmclure@linux.ibm.com>
Reported-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Reviewed-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230510033117.1395895-5-rmclure@linux.ibm.com
parent 6f313632
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -180,8 +180,8 @@ void do_syscall_trace_leave(struct pt_regs *regs);
static inline void set_return_regs_changed(void)
{
#ifdef CONFIG_PPC_BOOK3S_64
	local_paca->hsrr_valid = 0;
	local_paca->srr_valid = 0;
	WRITE_ONCE(local_paca->hsrr_valid, 0);
	WRITE_ONCE(local_paca->srr_valid, 0);
#endif
}

+6 −8
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ static notrace void check_return_regs_valid(struct pt_regs *regs)
	case 0x1600:
	case 0x1800:
		validp = &local_paca->hsrr_valid;
		if (!*validp)
		if (!READ_ONCE(*validp))
			return;

		srr0 = mfspr(SPRN_HSRR0);
@@ -135,7 +135,7 @@ static notrace void check_return_regs_valid(struct pt_regs *regs)
		break;
	default:
		validp = &local_paca->srr_valid;
		if (!*validp)
		if (!READ_ONCE(*validp))
			return;

		srr0 = mfspr(SPRN_SRR0);
@@ -161,19 +161,17 @@ static notrace void check_return_regs_valid(struct pt_regs *regs)
	 * such things will get caught most of the time, statistically
	 * enough to be able to get a warning out.
	 */
	barrier();

	if (!*validp)
	if (!READ_ONCE(*validp))
		return;

	if (!warned) {
		warned = true;
	if (!data_race(warned)) {
		data_race(warned = true);
		printk("%sSRR0 was: %lx should be: %lx\n", h, srr0, regs->nip);
		printk("%sSRR1 was: %lx should be: %lx\n", h, srr1, regs->msr);
		show_regs(regs);
	}

	*validp = 0; /* fixup */
	WRITE_ONCE(*validp, 0); /* fixup */
#endif
}