mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-11 06:54:18 +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/interface.cc
|
||||||
SRC_CC += spec/riscv/kernel/pd.cc
|
SRC_CC += spec/riscv/kernel/pd.cc
|
||||||
SRC_CC += spec/riscv/cpu.cc
|
SRC_CC += spec/riscv/cpu.cc
|
||||||
|
SRC_CC += spec/riscv/pic.cc
|
||||||
SRC_CC += spec/riscv/platform_support.cc
|
SRC_CC += spec/riscv/platform_support.cc
|
||||||
SRC_CC += spec/riscv/timer.cc
|
SRC_CC += spec/riscv/timer.cc
|
||||||
SRC_CC += spec/64bit/memory_map.cc
|
SRC_CC += spec/64bit/memory_map.cc
|
||||||
|
@ -20,7 +20,7 @@ using namespace Board;
|
|||||||
Bootstrap::Platform::Board::Board()
|
Bootstrap::Platform::Board::Board()
|
||||||
:
|
:
|
||||||
early_ram_regions(Memory_region { RAM_BASE, RAM_SIZE } ),
|
early_ram_regions(Memory_region { RAM_BASE, RAM_SIZE } ),
|
||||||
core_mmio()
|
core_mmio(Memory_region { PLIC_BASE, PLIC_SIZE })
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
unsigned Bootstrap::Platform::enable_mmu()
|
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 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 polarity =
|
||||||
(Genode::Irq_session::Polarity) (user_arg_3() & 0b11);
|
(Genode::Irq_session::Polarity) (user_arg_3() & 0b11);
|
||||||
|
|
||||||
|
@ -28,8 +28,13 @@ void Thread::exception(Cpu & cpu)
|
|||||||
using Stval = Genode::Cpu::Stval;
|
using Stval = Genode::Cpu::Stval;
|
||||||
|
|
||||||
if (regs->is_irq()) {
|
if (regs->is_irq()) {
|
||||||
/* there are only cpu-local timer interrupts right now */
|
/* cpu-local timer interrupt */
|
||||||
cpu.interrupt(cpu.timer().interrupt_id());
|
if (regs->irq() == cpu.timer().interrupt_id()) {
|
||||||
|
cpu.interrupt(cpu.timer().interrupt_id());
|
||||||
|
} else {
|
||||||
|
/* interrupt controller */
|
||||||
|
_interrupt(0);
|
||||||
|
}
|
||||||
return;
|
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
|
* \author Sebastian Sumpf
|
||||||
* \date 2015-06-02
|
* \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
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
@ -16,14 +16,23 @@
|
|||||||
#ifndef _CORE__SPEC__RISCV__PIC_H_
|
#ifndef _CORE__SPEC__RISCV__PIC_H_
|
||||||
#define _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; }
|
namespace Board { class Pic; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dummy PIC driver for core
|
* PIC driver for core for one CPU
|
||||||
*/
|
*/
|
||||||
class Board::Pic
|
class Board::Pic
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Plic _plic;
|
||||||
|
Plic::Id::access_t _last_irq { 0 };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -32,15 +41,45 @@ class Board::Pic
|
|||||||
* when SMP is an aspect of CPUs only compiled where necessary
|
* when SMP is an aspect of CPUs only compiled where necessary
|
||||||
*/
|
*/
|
||||||
IPI = 0,
|
IPI = 0,
|
||||||
NR_OF_IRQ = 15,
|
NR_OF_IRQ = Plic::NR_OF_IRQ,
|
||||||
};
|
};
|
||||||
|
|
||||||
Pic() { }
|
Pic();
|
||||||
bool take_request(unsigned & i) { i = 0; return true; }
|
|
||||||
void unmask(unsigned, unsigned) { }
|
bool take_request(unsigned & irq)
|
||||||
void mask(unsigned) { }
|
{
|
||||||
void finish_request() { }
|
irq = _plic.read<Plic::Id>();
|
||||||
void irq_mode(unsigned, unsigned, unsigned) { }
|
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_ */
|
#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&) { }
|
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 */,
|
bool Platform::get_msi_params(addr_t /* mmconf */, addr_t & /* address */,
|
||||||
|
@ -24,7 +24,7 @@ Board::Timer::Timer(unsigned)
|
|||||||
{
|
{
|
||||||
/* enable timer interrupt */
|
/* enable timer interrupt */
|
||||||
enum { STIE = 0x20 };
|
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 Asid : Bitfield<44,16> { };
|
||||||
struct Mode : Bitfield<60, 4> { };
|
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_ */
|
#endif /* _SRC__LIB__HW__SPEC__RISCV__CPU_H_ */
|
||||||
|
@ -25,6 +25,9 @@ namespace Hw::Riscv_board {
|
|||||||
RAM_BASE = 0x80020000,
|
RAM_BASE = 0x80020000,
|
||||||
RAM_SIZE = 0x7fe0000,
|
RAM_SIZE = 0x7fe0000,
|
||||||
TIMER_HZ = 10000000,
|
TIMER_HZ = 10000000,
|
||||||
|
|
||||||
|
PLIC_BASE = 0xc002000,
|
||||||
|
PLIC_SIZE = 0x200000,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { UART_BASE, UART_CLOCK };
|
enum { UART_BASE, UART_CLOCK };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user