From 2ad1c450eeb2697705db3553bb86cf55c6bf330e Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 16 Jan 2025 09:41:48 +0100 Subject: [PATCH] sel4: add MSI support for x86 Fixes #5423 --- repos/base-sel4/src/core/include/irq_object.h | 10 +++++-- .../src/core/irq_session_component.cc | 30 +++++++++++-------- repos/base-sel4/src/core/platform.cc | 1 + repos/base-sel4/src/core/spec/arm/irq.cc | 3 +- repos/base-sel4/src/core/spec/x86/irq.cc | 27 ++++++++++++----- repos/base/src/core/include/irq_args.h | 9 +++++- 6 files changed, 53 insertions(+), 27 deletions(-) diff --git a/repos/base-sel4/src/core/include/irq_object.h b/repos/base-sel4/src/core/include/irq_object.h index e5fa51aad7..38f1a3e803 100644 --- a/repos/base-sel4/src/core/include/irq_object.h +++ b/repos/base-sel4/src/core/include/irq_object.h @@ -23,6 +23,7 @@ /* core includes */ #include +#include 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_ */ diff --git a/repos/base-sel4/src/core/irq_session_component.cc b/repos/base-sel4/src/core/irq_session_component.cc index 108f8f9940..be5beeb975 100644 --- a/repos/base-sel4/src/core/irq_session_component.cc +++ b/repos/base-sel4/src/core/irq_session_component.cc @@ -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 }; } diff --git a/repos/base-sel4/src/core/platform.cc b/repos/base-sel4/src/core/platform.cc index 25b68940cb..2bd987fdbc 100644 --- a/repos/base-sel4/src/core/platform.cc +++ b/repos/base-sel4/src/core/platform.cc @@ -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", [&] { diff --git a/repos/base-sel4/src/core/spec/arm/irq.cc b/repos/base-sel4/src/core/spec/arm/irq.cc index a16be9edd6..2e2df4ac53 100644 --- a/repos/base-sel4/src/core/spec/arm/irq.cc +++ b/repos/base-sel4/src/core/spec/arm/irq.cc @@ -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(); diff --git a/repos/base-sel4/src/core/spec/x86/irq.cc b/repos/base-sel4/src/core/spec/x86/irq.cc index e0f6c9715c..39830a735c 100644 --- a/repos/base-sel4/src/core/spec/x86/irq.cc +++ b/repos/base-sel4/src/core/spec/x86/irq.cc @@ -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; + } } diff --git a/repos/base/src/core/include/irq_args.h b/repos/base/src/core/include/irq_args.h index 4630097971..f8c70ee242 100644 --- a/repos/base/src/core/include/irq_args.h +++ b/repos/base/src/core/include/irq_args.h @@ -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_ */