riscv: Add support for timer interrupts

RISCV requires that timer interrupts be handled in machine
mode and delegated as necessary. Also you can only reset the
timer interrupt by writing to mtimecmp. Further, you must
write a number > mtime, not just != mtime. This rather clumsy
situation requires that we write some value into the future
into mtimecmp lest we never be able to leave machine mode as
the interrupt either is not cleared or instantly reoccurs.

This current code is tested and works for harvey (Plan 9)
timer interrupts.

Change-Id: I8538d5fd8d80d9347773c638f5cbf0da18dc1cae
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Reviewed-on: https://review.coreboot.org/17807
Tested-by: build bot (Jenkins)
Reviewed-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
This commit is contained in:
Ronald G. Minnich
2016-12-12 15:09:42 -08:00
parent a01695bf9a
commit d9307c2e8a
3 changed files with 94 additions and 4 deletions

View File

@@ -292,12 +292,21 @@ void initVirtualMemory(void) {
void mstatus_init(void)
{
uintptr_t ms = 0;
ms = INSERT_FIELD(ms, MSTATUS_FS, 3);
ms = INSERT_FIELD(ms, MSTATUS_XS, 3);
write_csr(mstatus, ms);
clear_csr(mip, MIP_MSIP);
set_csr(mie, MIP_MSIP);
// clear any pending timer interrupts.
clear_csr(mip, MIP_STIP | MIP_SSIP);
// enable machine and supervisor timer and
// all other supervisor interrupts.
set_csr(mie, MIP_MTIP | MIP_STIP | MIP_SSIP);
// Delegate supervisor timer and other interrupts
// to supervisor mode.
set_csr(mideleg, MIP_STIP | MIP_SSIP);
set_csr(medeleg, delegate);