handle_interrupt.c 1.76 KB
#include <stdint.h>

enum {
        RISCV_INTERRUPT_SOFTWARE_MACHINE = 3,
        RISCV_INTERRUPT_TIMER_MACHINE = 7,
        RISCV_INTERRUPT_EXTERNAL_MACHINE = 11
};

union clint_time_regs {
        uint64_t val_64;
        uint32_t val_32[2];
};

struct clint_regs {
        /* one per hart */
        /* 0x0000 */
        uint32_t msip[4096];
        /* 0x4000 */
        union clint_time_regs mtimecmp[4096/2];
        /* 0x8000 */
        uint32_t reserved_8000[4094];
        /* 0xbff8 */
        union clint_time_regs mtime;
        /* 0xc000 */
        uint32_t reserved_c000[4096];
};

#include "bcc/bcc.h"
#include "bcc/bcc_param.h"
#include <bcc/regs/plic.h>
#include "isr_priv.h"

struct isr_ctx;

void __bcc_handle_interrupt(
        unsigned long mstatus,
        uintptr_t mepc,
        unsigned long mcause,
        struct isr_ctx *frame
)
{
        (void) sizeof mstatus;
        (void) sizeof mepc;
        (void) sizeof frame;
        mcause <<= 1;
        mcause >>= 1;
        if (mcause == RISCV_INTERRUPT_EXTERNAL_MACHINE) {
                volatile struct plic_regs *pregs = (void *) __bcc_plic_handle;
                while (1) {
                        uint32_t source = pregs->context[0].claim_complete;
                        if (source == 0) {
                                break;
                        }
                        DBG("source=%d\n", (int) source);
                        struct bcc_isr_node *n = __bcc_isr_list[source];
                        while (n) {
                                n->handler(n->arg, source);
                                n = n->__private;
                        }
                        pregs->context[0].claim_complete = source;
                }
        } else {
                __asm__ volatile ("ebreak");
        }
}