diff --git a/sys/riscv/include/intr.h b/sys/riscv/include/intr.h index 57d5e5db1b2..bc8c138ad01 100644 --- a/sys/riscv/include/intr.h +++ b/sys/riscv/include/intr.h @@ -60,6 +60,8 @@ enum { IRQ_SOFTWARE, IRQ_TIMER, IRQ_HTIF, + IRQ_COP, /* lowRISC only */ + IRQ_UART, /* lowRISC only */ NIRQS }; diff --git a/sys/riscv/include/riscvreg.h b/sys/riscv/include/riscvreg.h index b411e1824f6..a71ee47e83f 100644 --- a/sys/riscv/include/riscvreg.h +++ b/sys/riscv/include/riscvreg.h @@ -47,7 +47,8 @@ #define ECALL_SEND_IPI 0x07 #define ECALL_CLEAR_IPI 0x08 #define ECALL_HTIF_LOWPUTC 0x09 -#define ECALL_MIE_SET 0x10 +#define ECALL_MIE_SET 0x0a +#define ECALL_IO_IRQ_MASK 0x0b #define EXCP_SHIFT 0 #define EXCP_MASK (0xf << EXCP_SHIFT) @@ -119,6 +120,7 @@ #define NCSRS 4096 #define CSR_IPI 0x783 +#define CSR_IO_IRQ 0x7c0 /* lowRISC only? */ #define XLEN 8 #define INSN_SIZE 4 diff --git a/sys/riscv/riscv/exception.S b/sys/riscv/riscv/exception.S index f1f127a4b6a..54f4c76aadc 100644 --- a/sys/riscv/riscv/exception.S +++ b/sys/riscv/riscv/exception.S @@ -270,18 +270,27 @@ supervisor_trap: machine_interrupt: /* Type of interrupt ? */ csrr t0, mcause - andi t0, t0, 3 + andi t0, t0, EXCP_MASK li t1, 0 beq t1, t0, software_interrupt li t1, 1 beq t1, t0, timer_interrupt li t1, 2 beq t1, t0, htif_interrupt + li t1, 4 + beq t1, t0, io_interrupt /* lowRISC only */ /* not reached */ 1: j 1b +io_interrupt: + /* Disable IO interrupts so we can go to supervisor mode */ + csrwi CSR_IO_IRQ, 0 + + /* Handle the trap in supervisor mode */ + j exit_mrts + software_interrupt: li t0, MIP_MSIP csrc mip, t0 @@ -307,7 +316,7 @@ software_interrupt: j exit 1: - /* Serve a trap in supervisor mode */ + /* Handle the trap in supervisor mode */ j exit_mrts timer_interrupt: @@ -415,6 +424,12 @@ supervisor_call: beq t5, t4, htif_lowputc li t4, ECALL_MIE_SET beq t5, t4, mie_set + li t4, ECALL_IO_IRQ_MASK + beq t5, t4, io_irq_mask + j exit_next_instr + +io_irq_mask: + csrw CSR_IO_IRQ, t6 j exit_next_instr mie_set: diff --git a/sys/riscv/riscv/intr_machdep.c b/sys/riscv/riscv/intr_machdep.c index 5ed109fa519..ad30bf2f991 100644 --- a/sys/riscv/riscv/intr_machdep.c +++ b/sys/riscv/riscv/intr_machdep.c @@ -101,6 +101,9 @@ riscv_mask_irq(void *source) case IRQ_SOFTWARE: csr_clear(sie, SIE_SSIE); break; + case IRQ_UART: + machine_command(ECALL_IO_IRQ_MASK, 0); + break; default: panic("Unknown irq %d\n", irq); } @@ -120,6 +123,9 @@ riscv_unmask_irq(void *source) case IRQ_SOFTWARE: csr_set(sie, SIE_SSIE); break; + case IRQ_UART: + machine_command(ECALL_IO_IRQ_MASK, 1); + break; default: panic("Unknown irq %d\n", irq); } @@ -203,6 +209,7 @@ riscv_cpu_intr(struct trapframe *frame) active_irq = (frame->tf_scause & EXCP_MASK); switch (active_irq) { + case IRQ_UART: case IRQ_SOFTWARE: case IRQ_TIMER: event = intr_events[active_irq];