Skip to content

Commit

Permalink
sel4: add MSI support for x86
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-ab committed Jan 16, 2025
1 parent 266dd0b commit 7024dbd
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 27 deletions.
10 changes: 7 additions & 3 deletions repos/base-sel4/src/core/include/irq_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

/* core includes */
#include <types.h>
#include <irq_args.h>

namespace Core { class Irq_object; }

Expand All @@ -41,19 +42,22 @@ 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; }
void notify() { Signal_transmitter(_sig_cap).submit(1); }
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_ */
29 changes: 16 additions & 13 deletions repos/base-sel4/src/core/irq_session_component.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;

Expand Down Expand Up @@ -100,22 +99,19 @@ 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(Irq_args(args).irq_number() +
Irq_args(args).type() != TYPE_LEGACY ? Irq_object::MSI_OFFSET : 0),
_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();
}
Expand Down Expand Up @@ -144,6 +140,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 };
}
1 change: 1 addition & 0 deletions repos/base-sel4/src/core/platform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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", [&] {
Expand Down
3 changes: 1 addition & 2 deletions repos/base-sel4/src/core/spec/arm/irq.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
27 changes: 19 additions & 8 deletions repos/base-sel4/src/core/spec/x86/irq.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,38 @@
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 };

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();
seL4_Uint8 const depth = 32;
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;
}
}
9 changes: 8 additions & 1 deletion repos/base/src/core/include/irq_args.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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_ */

0 comments on commit 7024dbd

Please sign in to comment.