[RFC,04/12] riscv: Switch back to CSR_STATUS masking when going idle
Commit Message
The WFI instruction makes current core stall until interrupt happens.
In WFI's implementation, core can only be waken up from interrupt
which is both pending in CSR_IP and enabled in CSR_IE. After we switch
to CSR_IE masking for irq disabling, WFI instruction can never resume
execution if CSR_IE is masked.
This commit handles this special case. When WFI instruction is called with
CSR_IE masked, we unmask CSR_IE first and disable irqs in traditional
CSR_STATUS way instead.
Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
---
arch/riscv/include/asm/processor.h | 4 ++++
arch/riscv/kernel/irq.c | 17 +++++++++++++++++
2 files changed, 21 insertions(+)
@@ -111,10 +111,14 @@ extern void start_thread(struct pt_regs *regs,
extern unsigned long __get_wchan(struct task_struct *p);
+#ifndef CONFIG_RISCV_PSEUDO_NMI
static inline void wait_for_interrupt(void)
{
__asm__ __volatile__ ("wfi");
}
+#else
+void wait_for_interrupt(void);
+#endif
struct device_node;
int riscv_of_processor_hartid(struct device_node *node, unsigned long *hartid);
@@ -15,6 +15,23 @@
#include <asm/softirq_stack.h>
#include <asm/stacktrace.h>
+#ifdef CONFIG_RISCV_PSEUDO_NMI
+
+void wait_for_interrupt(void)
+{
+ if (irqs_disabled()) {
+ local_irq_switch_off();
+ local_irq_enable();
+ __asm__ __volatile__ ("wfi");
+ local_irq_disable();
+ local_irq_switch_on();
+ } else {
+ __asm__ __volatile__ ("wfi");
+ }
+}
+
+#endif /* CONFIG_RISCV_PSEUDO_NMI */
+
static struct fwnode_handle *(*__get_intc_node)(void);
void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void))