[PATCH RFC Dovetail 7.1] arm64: irq_pipeline: 7.1 specific adjustments

Florian Bezdeka <[email protected]>
Newsgroups dev.linux.lists.xenomai
Message-ID <[email protected]>
Signed-off-by: Florian Bezdeka <[email protected]>
---

Hi Philippe,

final tests are still running but the local tests are looking good.
The EVL testsuite triggered a WARN_ONCE() - see process.c below - which
caused the systems to hang.

Turned out the arm64 entry code got some refactorings that needed some
adjustments - pipline wise.

I would fold the following into 7.1, so could you please double check?
Thanks!

 arch/arm64/kernel/entry-common.c | 35 ++++++++++++++++++++++++++++----
 arch/arm64/kernel/process.c      |  6 +++---
 include/linux/irq-entry-common.h |  3 +++
 3 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index b0e141266349..97f6d6904a5d 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -166,7 +166,16 @@ static noinstr irqentry_state_t arm64_enter_from_kernel_mode(struct pt_regs *reg
 static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
 					      irqentry_state_t state)
 {
-	local_irq_disable();
+	if (irqs_pipelined()) {
+		hard_local_irq_disable();
+		if (running_inband()) {
+			stall_inband_nocheck();
+			trace_hardirqs_off();
+		}
+	} else {
+		local_irq_disable();
+	}
+
 	irqentry_exit_to_kernel_mode_preempt(regs, state);
 	local_daif_mask();
 	mte_check_tfsr_exit();
@@ -175,7 +184,14 @@ static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
 
 static __always_inline void arm64_syscall_enter_from_user_mode(struct pt_regs *regs)
 {
-	enter_from_user_mode(regs);
+	if (running_inband()) {
+		WARN_ON_ONCE(irq_pipeline_debug() && irqs_disabled());
+		stall_inband_nocheck();
+		enter_from_user_mode(regs);
+		trace_hardirqs_on();
+		unstall_inband_nocheck();
+	}
+
 	mte_disable_tco_entry(current);
 	sme_enter_from_user_mode();
 }
@@ -191,6 +207,7 @@ static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
 		WARN_ON_ONCE(irq_pipeline_debug() && irqs_disabled());
 		stall_inband_nocheck();
 		enter_from_user_mode(regs);
+		rseq_note_user_irq_entry();
 		trace_hardirqs_on();
 		unstall_inband_nocheck();
 	}
@@ -226,8 +243,18 @@ static __always_inline void arm64_syscall_exit_to_user_mode(struct pt_regs *regs
  */
 static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
 {
-	local_irq_disable();
-	irqentry_exit_to_user_mode_prepare(regs);
+	if (irqs_pipelined()) {
+		hard_local_irq_disable();
+		if (running_inband()) {
+			stall_inband_nocheck();
+			trace_hardirqs_off();
+			irqentry_exit_to_user_mode_prepare(regs);
+		}
+	} else {
+		local_irq_disable();
+		irqentry_exit_to_user_mode_prepare(regs);
+	}
+
 	local_daif_mask();
 	sme_exit_to_user_mode();
 	mte_check_tfsr_exit();
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index b1eac5fd75c1..0047d0bdedd9 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -748,8 +748,8 @@ static inline void debug_switch_state(void)
 		unsigned long pmr_expected = GIC_PRIO_IRQOFF;
 		unsigned long pmr_actual = read_sysreg_s(SYS_ICC_PMR_EL1);
 
-		WARN_ONCE(daif_actual != daif_expected ||
-			  pmr_actual != pmr_expected,
+		WARN_ONCE(running_inband() && (daif_actual != daif_expected ||
+			  pmr_actual != pmr_expected),
 			  "Unexpected DAIF + PMR: 0x%lx + 0x%lx (expected 0x%lx + 0x%lx)\n",
 			  daif_actual, pmr_actual,
 			  daif_expected, pmr_expected);
@@ -757,7 +757,7 @@ static inline void debug_switch_state(void)
 		unsigned long daif_expected = DAIF_PROCCTX_NOIRQ;
 		unsigned long daif_actual = read_sysreg(daif);
 
-		WARN_ONCE(daif_actual != daif_expected,
+		WARN_ONCE(running_inband() && daif_actual != daif_expected,
 			  "Unexpected DAIF value: 0x%lx (expected 0x%lx)\n",
 			  daif_actual, daif_expected);
 	}
diff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h
index 58c28b2a8f2b..61a8e129e71f 100644
--- a/include/linux/irq-entry-common.h
+++ b/include/linux/irq-entry-common.h
@@ -600,6 +600,9 @@ irqentry_exit_to_kernel_mode_after_preempt(struct pt_regs *regs, irqentry_state_
 {
 	bool synchronized;
 
+	if (running_oob())
+		return;
+
 	instrumentation_begin();
 	synchronized = irqentry_syncstage(state);
 
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.