mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
riscv: Interrupt controller support
- Enable the "platform-level interrupt controller" PLIC on base-hw - The RISC-V specification offers only a register description, but no layout for the register set. This implies the layout is platform dependent, and therefore, implemented separately for Qemu issue #4042
This commit is contained in:
parent
bebba3876e
commit
6223ae4413
@ -12,6 +12,7 @@ SRC_CC += spec/riscv/kernel/cpu.cc
|
||||
SRC_CC += spec/riscv/kernel/interface.cc
|
||||
SRC_CC += spec/riscv/kernel/pd.cc
|
||||
SRC_CC += spec/riscv/cpu.cc
|
||||
SRC_CC += spec/riscv/pic.cc
|
||||
SRC_CC += spec/riscv/platform_support.cc
|
||||
SRC_CC += spec/riscv/timer.cc
|
||||
SRC_CC += spec/64bit/memory_map.cc
|
||||
|
@ -20,7 +20,7 @@ using namespace Board;
|
||||
Bootstrap::Platform::Board::Board()
|
||||
:
|
||||
early_ram_regions(Memory_region { RAM_BASE, RAM_SIZE } ),
|
||||
core_mmio()
|
||||
core_mmio(Memory_region { PLIC_BASE, PLIC_SIZE })
|
||||
{ }
|
||||
|
||||
unsigned Bootstrap::Platform::enable_mmu()
|
||||
|
38
repos/base-hw/src/core/board/riscv_qemu/plic.h
Normal file
38
repos/base-hw/src/core/board/riscv_qemu/plic.h
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* \brief Platform-level interrupt controller layout (PLIC)
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2021-03-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__SPEC__RISCV_QEMU__PLIC_H_
|
||||
#define _CORE__SPEC__RISCV_QEMU__PLIC_H_
|
||||
|
||||
namespace Board { class Plic; }
|
||||
|
||||
struct Board::Plic : Genode::Mmio
|
||||
{
|
||||
enum { NR_OF_IRQ = 32 };
|
||||
|
||||
struct Enable : Register_array<0x80, 32, 32, 1> { };
|
||||
struct Id : Register<0x1ff004, 32> { };
|
||||
|
||||
Plic(Genode::addr_t const base)
|
||||
:
|
||||
Mmio(base) { }
|
||||
|
||||
void enable(unsigned value, unsigned irq)
|
||||
{
|
||||
write<Enable>(value, irq);
|
||||
}
|
||||
|
||||
void el(unsigned, unsigned) { }
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__RISCV_QEMU__PLIC_H_ */
|
@ -644,7 +644,7 @@ void Thread::_call_new_irq()
|
||||
}
|
||||
|
||||
Genode::Irq_session::Trigger trigger =
|
||||
(Genode::Irq_session::Trigger) (user_arg_3() & 0b1100);
|
||||
(Genode::Irq_session::Trigger) ((user_arg_3() >> 2) & 0b11);
|
||||
Genode::Irq_session::Polarity polarity =
|
||||
(Genode::Irq_session::Polarity) (user_arg_3() & 0b11);
|
||||
|
||||
|
@ -28,8 +28,13 @@ void Thread::exception(Cpu & cpu)
|
||||
using Stval = Genode::Cpu::Stval;
|
||||
|
||||
if (regs->is_irq()) {
|
||||
/* there are only cpu-local timer interrupts right now */
|
||||
cpu.interrupt(cpu.timer().interrupt_id());
|
||||
/* cpu-local timer interrupt */
|
||||
if (regs->irq() == cpu.timer().interrupt_id()) {
|
||||
cpu.interrupt(cpu.timer().interrupt_id());
|
||||
} else {
|
||||
/* interrupt controller */
|
||||
_interrupt(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
25
repos/base-hw/src/core/spec/riscv/pic.cc
Normal file
25
repos/base-hw/src/core/spec/riscv/pic.cc
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief RISC-V PIC initialization
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2021-03-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
|
||||
#include <board.h>
|
||||
#include <pic.h>
|
||||
#include <platform.h>
|
||||
|
||||
Board::Pic::Pic() :
|
||||
_plic(Genode::Platform::mmio_to_virt(Board::PLIC_BASE))
|
||||
{
|
||||
/* enable external interrupts */
|
||||
enum { SEIE = 0x200 };
|
||||
Hw::Riscv_cpu::Sie external_interrupt(SEIE);
|
||||
}
|
@ -3,11 +3,11 @@
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2015-06-02
|
||||
*
|
||||
* There currently is no interrupt controller defined for the RISC-V platform.
|
||||
* The platform specific PLIC-register layout can be found in 'plic.h'
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2021 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -16,14 +16,23 @@
|
||||
#ifndef _CORE__SPEC__RISCV__PIC_H_
|
||||
#define _CORE__SPEC__RISCV__PIC_H_
|
||||
|
||||
#include <irq_session/irq_session.h>
|
||||
#include <util/mmio.h>
|
||||
#include <plic.h>
|
||||
|
||||
namespace Board { class Pic; }
|
||||
|
||||
|
||||
/**
|
||||
* Dummy PIC driver for core
|
||||
* PIC driver for core for one CPU
|
||||
*/
|
||||
class Board::Pic
|
||||
{
|
||||
private:
|
||||
|
||||
Plic _plic;
|
||||
Plic::Id::access_t _last_irq { 0 };
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
@ -32,15 +41,45 @@ class Board::Pic
|
||||
* when SMP is an aspect of CPUs only compiled where necessary
|
||||
*/
|
||||
IPI = 0,
|
||||
NR_OF_IRQ = 15,
|
||||
NR_OF_IRQ = Plic::NR_OF_IRQ,
|
||||
};
|
||||
|
||||
Pic() { }
|
||||
bool take_request(unsigned & i) { i = 0; return true; }
|
||||
void unmask(unsigned, unsigned) { }
|
||||
void mask(unsigned) { }
|
||||
void finish_request() { }
|
||||
void irq_mode(unsigned, unsigned, unsigned) { }
|
||||
Pic();
|
||||
|
||||
bool take_request(unsigned & irq)
|
||||
{
|
||||
irq = _plic.read<Plic::Id>();
|
||||
if (irq == 0) return false;
|
||||
_last_irq = irq;
|
||||
return true;
|
||||
}
|
||||
|
||||
void finish_request()
|
||||
{
|
||||
_plic.write<Plic::Id>(_last_irq);
|
||||
}
|
||||
|
||||
void unmask(unsigned irq, unsigned)
|
||||
{
|
||||
if (irq > NR_OF_IRQ) return;
|
||||
_plic.enable(1, irq);
|
||||
}
|
||||
|
||||
void mask(unsigned irq)
|
||||
{
|
||||
if (irq > NR_OF_IRQ) return;
|
||||
_plic.enable(0, irq);
|
||||
}
|
||||
|
||||
void irq_mode(unsigned irq, unsigned trigger, unsigned)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
if (irq > NR_OF_IRQ || trigger == Irq_session::TRIGGER_UNCHANGED)
|
||||
return;
|
||||
|
||||
_plic.el(trigger == Irq_session::TRIGGER_EDGE ? 1 : 0, irq);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__RISCV__PIC_H_ */
|
||||
|
@ -27,7 +27,7 @@ void Platform::_init_io_port_alloc() { }
|
||||
void Platform::_init_additional_platform_info(Genode::Xml_generator&) { }
|
||||
|
||||
|
||||
long Platform::irq(long const /* user_irq */) { return 0; }
|
||||
long Platform::irq(long const user_irq ) { return user_irq; }
|
||||
|
||||
|
||||
bool Platform::get_msi_params(addr_t /* mmconf */, addr_t & /* address */,
|
||||
|
@ -24,7 +24,7 @@ Board::Timer::Timer(unsigned)
|
||||
{
|
||||
/* enable timer interrupt */
|
||||
enum { STIE = 0x20 };
|
||||
asm volatile ("csrs sie, %0" : : "r"(STIE));
|
||||
Hw::Riscv_cpu::Sie timer(STIE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,6 +43,14 @@ struct Hw::Riscv_cpu
|
||||
struct Asid : Bitfield<44,16> { };
|
||||
struct Mode : Bitfield<60, 4> { };
|
||||
);
|
||||
|
||||
struct Sie
|
||||
{
|
||||
Sie(Genode::addr_t bits)
|
||||
{
|
||||
asm volatile ("csrs sie, %0" : : "r"(bits));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _SRC__LIB__HW__SPEC__RISCV__CPU_H_ */
|
||||
|
@ -25,6 +25,9 @@ namespace Hw::Riscv_board {
|
||||
RAM_BASE = 0x80020000,
|
||||
RAM_SIZE = 0x7fe0000,
|
||||
TIMER_HZ = 10000000,
|
||||
|
||||
PLIC_BASE = 0xc002000,
|
||||
PLIC_SIZE = 0x200000,
|
||||
};
|
||||
|
||||
enum { UART_BASE, UART_CLOCK };
|
||||
|
Loading…
Reference in New Issue
Block a user