Skip to content

Commit cc18264

Browse files
fix(riscv/irqc): align IMSIC handler to AIA specifications
"The RISC-V Advanced Interrupt Architecture" specifications explain in Chapter 3 (pages 26-27) how interrupts should be handled with IMSIC, in particular, interrupt claiming has to be done right after reading the STOPEI register or in the same read instruction with the csrrw instruction. This commit aligns the IMSIC interrupt handler to that specs. Without this change, if an interrupt with higher priority becomes pending while handling a lower one, writing to STOPEI after `interrupts_handle()` executes will claim the higher IRQ, freezing the execution. Signed-off-by: Filippo Fontana <[email protected]>
1 parent 85bc288 commit cc18264

File tree

2 files changed

+28
-24
lines changed

2 files changed

+28
-24
lines changed

src/arch/riscv/inc/arch/csrs.h

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -228,24 +228,31 @@
228228

229229
#ifndef __ASSEMBLER__
230230

231-
#define CSRS_GEN_ACCESSORS_NAMED(csr_name, csr_id) \
232-
static inline unsigned long csrs_##csr_name##_read(void) \
233-
{ \
234-
unsigned long csr_value; \
235-
__asm__ volatile("csrr %0," XSTR(csr_id) : "=r"(csr_value)::"memory"); \
236-
return csr_value; \
237-
} \
238-
static inline void csrs_##csr_name##_write(unsigned long csr_value) \
239-
{ \
240-
__asm__ volatile("csrw " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
241-
} \
242-
static inline void csrs_##csr_name##_set(unsigned long csr_value) \
243-
{ \
244-
__asm__ volatile("csrs " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
245-
} \
246-
static inline void csrs_##csr_name##_clear(unsigned long csr_value) \
247-
{ \
248-
__asm__ volatile("csrc " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
231+
#define CSRS_GEN_ACCESSORS_NAMED(csr_name, csr_id) \
232+
static inline unsigned long csrs_##csr_name##_read(void) \
233+
{ \
234+
unsigned long csr_value; \
235+
__asm__ volatile("csrr %0," XSTR(csr_id) : "=r"(csr_value)::"memory"); \
236+
return csr_value; \
237+
} \
238+
static inline void csrs_##csr_name##_write(unsigned long csr_value) \
239+
{ \
240+
__asm__ volatile("csrw " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
241+
} \
242+
static inline void csrs_##csr_name##_set(unsigned long csr_value) \
243+
{ \
244+
__asm__ volatile("csrs " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
245+
} \
246+
static inline void csrs_##csr_name##_clear(unsigned long csr_value) \
247+
{ \
248+
__asm__ volatile("csrc " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
249+
} \
250+
static inline unsigned long csrs_##csr_name##_swap(unsigned long csr_value) \
251+
{ \
252+
unsigned long reg_val; \
253+
__asm__ volatile("csrrw %0," XSTR(csr_id) ",%1" : "=r"(reg_val) : "rK"(csr_value) \
254+
: "memory"); \
255+
return reg_val; \
249256
}
250257

251258
#define CSRS_GEN_ACCESSORS(csr) CSRS_GEN_ACCESSORS_NAMED(csr, csr)

src/arch/riscv/irqc/aia/imsic.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,11 @@ void imsic_send_msi(cpuid_t target_cpu, irqid_t ipi_id)
8787

8888
void imsic_handle(void)
8989
{
90-
uint32_t intp_identity = (uint32_t)(csrs_stopei_read() >> STOPEI_EEID);
90+
/* Read STOPEI and write to it to claim the interrupt */
91+
uint32_t intp_identity = (uint32_t)(csrs_stopei_swap(0) >> STOPEI_EEID);
9192

9293
if (intp_identity != 0) {
93-
enum irq_res res = interrupts_handle(intp_identity);
94-
if (res == HANDLED_BY_HYP) {
95-
/* Write to STOPEI to clear the interrupt */
96-
csrs_stopei_write(0);
97-
}
94+
interrupts_handle(intp_identity);
9895
};
9996
}
10097

0 commit comments

Comments
 (0)