mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-06 11:10:24 +00:00
parent
ea3ed25431
commit
2ad1c450ee
@ -23,6 +23,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <types.h>
|
||||
#include <irq_args.h>
|
||||
|
||||
namespace Core { class Irq_object; }
|
||||
|
||||
@ -41,11 +42,12 @@ class Core::Irq_object : public Thread {
|
||||
|
||||
void entry() override;
|
||||
|
||||
long _associate(Irq_session::Trigger const &irq_trigger,
|
||||
Irq_session::Polarity const &irq_polarity);
|
||||
long _associate(Irq_args const &);
|
||||
|
||||
public:
|
||||
|
||||
enum { MSI_OFFSET = 64 };
|
||||
|
||||
Irq_object(unsigned irq);
|
||||
|
||||
void sigh(Signal_context_capability cap) { _sig_cap = cap; }
|
||||
@ -53,7 +55,9 @@ class Core::Irq_object : public Thread {
|
||||
void ack_irq();
|
||||
|
||||
Start_result start() override;
|
||||
bool associate(Irq_session::Trigger const, Irq_session::Polarity const);
|
||||
bool associate(Irq_args const &);
|
||||
|
||||
bool msi() const { return _irq >= MSI_OFFSET; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_OBJECT_H_ */
|
||||
|
@ -22,12 +22,11 @@
|
||||
using namespace Core;
|
||||
|
||||
|
||||
bool Irq_object::associate(Irq_session::Trigger const irq_trigger,
|
||||
Irq_session::Polarity const irq_polarity)
|
||||
bool Irq_object::associate(Irq_args const &args)
|
||||
{
|
||||
/* allocate notification object within core's CNode */
|
||||
Platform &platform = platform_specific();
|
||||
Range_allocator &phys_alloc = platform.ram_alloc();
|
||||
auto &platform = platform_specific();
|
||||
auto &phys_alloc = platform.ram_alloc();
|
||||
|
||||
{
|
||||
addr_t const phys_addr = Untyped_memory::alloc_page(phys_alloc);
|
||||
@ -38,7 +37,7 @@ bool Irq_object::associate(Irq_session::Trigger const irq_trigger,
|
||||
}
|
||||
|
||||
/* setup IRQ platform specific */
|
||||
long res = _associate(irq_trigger, irq_polarity);
|
||||
long res = _associate(args);
|
||||
if (res != seL4_NoError)
|
||||
return false;
|
||||
|
||||
@ -100,22 +99,20 @@ Irq_object::Irq_object(unsigned irq)
|
||||
Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
const char *args)
|
||||
:
|
||||
_irq_number((unsigned)Arg_string::find_arg(args, "irq_number").long_value(-1)),
|
||||
_irq_number(unsigned(Irq_args(args).type() == TYPE_LEGACY ?
|
||||
Irq_args(args).irq_number() :
|
||||
Irq_args(args).irq_number() + Irq_object::MSI_OFFSET)),
|
||||
_irq_alloc(irq_alloc),
|
||||
_irq_object(_irq_number)
|
||||
{
|
||||
Irq_args const irq_args(args);
|
||||
bool msi { irq_args.type() != Irq_session::TYPE_LEGACY };
|
||||
if (msi)
|
||||
throw Service_denied();
|
||||
|
||||
if (irq_alloc.alloc_addr(1, _irq_number).failed()) {
|
||||
error("unavailable IRQ ", _irq_number, " requested");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
|
||||
if (!_irq_object.associate(irq_args.trigger(), irq_args.polarity())) {
|
||||
if (!_irq_object.associate(irq_args)) {
|
||||
error("could not associate with IRQ ", irq_args.irq_number());
|
||||
throw Service_denied();
|
||||
}
|
||||
@ -144,6 +141,13 @@ void Irq_session_component::sigh(Signal_context_capability cap)
|
||||
|
||||
Irq_session::Info Irq_session_component::info()
|
||||
{
|
||||
/* no MSI support */
|
||||
return { .type = Info::Type::INVALID, .address = 0, .value = 0 };
|
||||
if (!_irq_object.msi())
|
||||
return { .type = Info::Type::INVALID, .address = 0, .value = 0 };
|
||||
|
||||
// see include/plat/pc99/plat/machine.h
|
||||
enum { PIC_IRQ_LINES = 16, IRQ_INT_OFFSET = 0x20 };
|
||||
|
||||
return { .type = Info::Type::MSI,
|
||||
.address = 0xfee00000ul,
|
||||
.value = IRQ_INT_OFFSET + PIC_IRQ_LINES + _irq_number };
|
||||
}
|
||||
|
@ -380,6 +380,7 @@ void Core::Platform::_init_rom_modules()
|
||||
xml.node("kernel", [&] {
|
||||
xml.attribute("name", "sel4");
|
||||
xml.attribute("acpi", true);
|
||||
xml.attribute("msi" , true);
|
||||
});
|
||||
xml.node("hardware", [&] {
|
||||
xml.node("features", [&] {
|
||||
|
@ -11,8 +11,7 @@
|
||||
using namespace Core;
|
||||
|
||||
|
||||
long Irq_object::_associate(Irq_session::Trigger const &,
|
||||
Irq_session::Polarity const &)
|
||||
long Irq_object::_associate(Irq_args const &)
|
||||
{
|
||||
seL4_CNode const root = seL4_CapInitThreadCNode;
|
||||
seL4_Word const index = _kernel_irq_sel.value();
|
||||
|
@ -12,8 +12,7 @@
|
||||
using namespace Core;
|
||||
|
||||
|
||||
long Irq_object::_associate(Irq_session::Trigger const &irq_trigger,
|
||||
Irq_session::Polarity const &irq_polarity)
|
||||
long Irq_object::_associate(Irq_args const & args)
|
||||
{
|
||||
enum { IRQ_EDGE = 0, IRQ_LEVEL = 1 };
|
||||
enum { IRQ_HIGH = 0, IRQ_LOW = 1 };
|
||||
@ -21,11 +20,11 @@ long Irq_object::_associate(Irq_session::Trigger const &irq_trigger,
|
||||
seL4_Word level = (_irq < 16) ? IRQ_EDGE : IRQ_LEVEL;
|
||||
seL4_Word polarity = (_irq < 16) ? IRQ_HIGH : IRQ_LOW;
|
||||
|
||||
if (irq_trigger != Irq_session::TRIGGER_UNCHANGED)
|
||||
level = (irq_trigger == Irq_session::TRIGGER_LEVEL) ? IRQ_LEVEL : IRQ_EDGE;
|
||||
if (args.trigger() != Irq_session::TRIGGER_UNCHANGED)
|
||||
level = (args.trigger() == Irq_session::TRIGGER_LEVEL) ? IRQ_LEVEL : IRQ_EDGE;
|
||||
|
||||
if (irq_polarity != Irq_session::POLARITY_UNCHANGED)
|
||||
polarity = (irq_polarity == Irq_session::POLARITY_HIGH) ? IRQ_HIGH : IRQ_LOW;
|
||||
if (args.polarity() != Irq_session::POLARITY_UNCHANGED)
|
||||
polarity = (args.polarity() == Irq_session::POLARITY_HIGH) ? IRQ_HIGH : IRQ_LOW;
|
||||
|
||||
seL4_CNode const root = seL4_CapInitThreadCNode;
|
||||
seL4_Word const index = _kernel_irq_sel.value();
|
||||
@ -33,6 +32,18 @@ long Irq_object::_associate(Irq_session::Trigger const &irq_trigger,
|
||||
seL4_Word const ioapic = 0;
|
||||
seL4_Word const pin = _irq ? _irq : 2;
|
||||
seL4_Word const vector = _irq;
|
||||
return seL4_IRQControl_GetIOAPIC(seL4_CapIRQControl, root, index, depth,
|
||||
ioapic, pin, level, polarity, vector);
|
||||
seL4_Word const handle = 0;
|
||||
|
||||
switch (args.type()) {
|
||||
case Irq_session::TYPE_LEGACY:
|
||||
return seL4_IRQControl_GetIOAPIC(seL4_CapIRQControl, root, index, depth,
|
||||
ioapic, pin, level, polarity, vector);
|
||||
case Irq_session::TYPE_MSI:
|
||||
case Irq_session::TYPE_MSIX:
|
||||
return seL4_IRQControl_GetMSI(seL4_CapIRQControl, root, index, depth,
|
||||
args.pci_bus(), args.pci_dev(),
|
||||
args.pci_func(), handle, vector);
|
||||
default:
|
||||
return seL4_InvalidArgument;
|
||||
}
|
||||
}
|
||||
|
@ -33,11 +33,14 @@ class Core::Irq_args
|
||||
|
||||
long const _irq_number;
|
||||
|
||||
long const _bdf;
|
||||
|
||||
public:
|
||||
|
||||
Irq_args(const char * args)
|
||||
:
|
||||
_irq_number(Arg_string::find_arg(args, "irq_number").long_value(-1))
|
||||
_irq_number(Arg_string::find_arg(args, "irq_number").long_value(-1)),
|
||||
_bdf(Arg_string::find_arg(args, "bdf").long_value(-1))
|
||||
{
|
||||
long irq_trg = Arg_string::find_arg(args, "irq_trigger").long_value(-1);
|
||||
long irq_pol = Arg_string::find_arg(args, "irq_polarity").long_value(-1);
|
||||
@ -99,6 +102,10 @@ class Core::Irq_args
|
||||
Irq_session::Trigger trigger() const { return _irq_trigger; }
|
||||
Irq_session::Polarity polarity() const { return _irq_polarity; }
|
||||
Irq_session::Type type() const { return _irq_type; }
|
||||
|
||||
unsigned pci_bus() const { return 0xffu & (_bdf >> 8); }
|
||||
unsigned pci_dev() const { return 0x1fu & (_bdf >> 3); }
|
||||
unsigned pci_func() const { return 0x07u & _bdf; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_ARGS_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user