OK. I'm not completely at the end of my tether here, but I'm close.

I'm trying to write an OS kernel for #RiscV (using #qemu's "virt" machine with an S-mode kernel and OpenSBI), and every time I try to enable interrupts -- specifically the timer interrupt -- it just locks up hard.

I can see in the registers that `scause` is STI. Most of the time, `stvec` is the correct value (occasionally, it's not, which I don't get either).

1/2

In my `stvec` routine, I'm saving a couple of t registers on the stack, clearing the STI bit of `sip`, restoring the t registers, and returning with `SRET`. Nothing else.

But the thing just seems to lock up hard as soon as the first timer interrupts lands.

What am I doing wrong?

2/2

#RiscV #qemu #OSDev

Oh, yes... if I put an illegal instruction (CSRR t0, mstatus) into the `stvec` routine, it doesn't trigger. So either the STI interrupt is firing very fast and interrupting the interrupt routine (how?), or something else is happening, but I have no idea what.

3/2 (I mean it this time)

@darkling
You need to stop the source of the clock
interrupts, not just clear the sip bit. Typically
you'd need to increase the value of the clint's
mtimecmp register past the mtime register's
value. You could also turn off stie in the sie csr.

@geoff_collyer I've finally got it working!

Turns out that OpenSBI blanks out all lower-priv access to the CLINT by setting a PMA over it, so I have to use the `time` CSR to read the current time, and the SBI TIME extension to set the timer. It also runs far faster than I'd anticipated (10 MHz, vs the 32.768 kHz that I'd found something else using on their embedded system's CLINT).

@darkling
Some vendors do that. I guess they don't trust the operating system. 10 MHz is typical for the clint clock.