mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
parent
47c924d1f5
commit
ab9a2107e4
@ -257,6 +257,30 @@ namespace Nova {
|
||||
*/
|
||||
enum Pd_op { TRANSFER_QUOTA = 0U, PD_DEBUG = 2U };
|
||||
|
||||
class Gsi_flags
|
||||
{
|
||||
private:
|
||||
|
||||
uint8_t _value { 0 };
|
||||
|
||||
public:
|
||||
|
||||
enum Mode { HIGH, LOW, EDGE };
|
||||
|
||||
Gsi_flags() { }
|
||||
|
||||
Gsi_flags(Mode m)
|
||||
{
|
||||
switch (m) {
|
||||
case HIGH: _value = 0b110; break; /* level-high */
|
||||
case LOW: _value = 0b111; break; /* level-low */
|
||||
case EDGE: _value = 0b100; break; /* edge-triggered */
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t value() const { return _value; }
|
||||
};
|
||||
|
||||
|
||||
class Descriptor
|
||||
{
|
||||
|
@ -457,12 +457,12 @@ namespace Nova {
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t assign_gsi(mword_t sm, mword_t dev, mword_t cpu,
|
||||
mword_t &msi_addr, mword_t &msi_data,
|
||||
mword_t si = ~0UL)
|
||||
mword_t si = ~0UL, Gsi_flags flags = Gsi_flags())
|
||||
{
|
||||
msi_addr = dev;
|
||||
msi_data = cpu;
|
||||
|
||||
return syscall_5(NOVA_ASSIGN_GSI, 0, sm, msi_addr, msi_data, si);
|
||||
return syscall_5(NOVA_ASSIGN_GSI, flags.value(), sm, msi_addr, msi_data, si);
|
||||
}
|
||||
|
||||
|
||||
|
@ -402,11 +402,11 @@ namespace Nova {
|
||||
ALWAYS_INLINE
|
||||
inline uint8_t assign_gsi(mword_t sm, mword_t dev, mword_t cpu,
|
||||
mword_t &msi_addr, mword_t &msi_data,
|
||||
mword_t si = ~0UL)
|
||||
mword_t si = ~0UL, Gsi_flags flags = Gsi_flags())
|
||||
{
|
||||
msi_addr = dev;
|
||||
msi_data = cpu;
|
||||
return syscall_5(NOVA_ASSIGN_GSI, 0, sm, msi_addr, msi_data, si);
|
||||
return syscall_5(NOVA_ASSIGN_GSI, flags.value(), sm, msi_addr, msi_data, si);
|
||||
}
|
||||
}
|
||||
#endif /* _INCLUDE__SPEC__64BIT__NOVA__SYSCALLS_H_ */
|
||||
|
@ -1 +1 @@
|
||||
33a2fa953ec52b0f63b921f4d33d68891c0aada0
|
||||
1b4d51180f6c3e64b2adb13a27257ef0544b859d
|
||||
|
@ -4,7 +4,7 @@ DOWNLOADS := nova.git
|
||||
|
||||
# r10 branch
|
||||
URL(nova) := https://github.com/alex-ab/NOVA.git
|
||||
REV(nova) := 00dc49bc18e7f72a9c85487e8f94fd859511d89d
|
||||
REV(nova) := 87db5b14163bc5e8b5dac6b191dbbe4833fb8cb3
|
||||
DIR(nova) := src/kernel/nova
|
||||
|
||||
PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch))
|
||||
|
@ -13,7 +13,9 @@
|
||||
#ifndef _CORE__INCLUDE__IRQ_OBJECT_H_
|
||||
#define _CORE__INCLUDE__IRQ_OBJECT_H_
|
||||
|
||||
namespace Genode { class Irq_object; }
|
||||
#include <nova/syscall-generic.h> /* Gsi_flags */
|
||||
|
||||
namespace Genode { class Irq_object; class Irq_args; }
|
||||
|
||||
class Genode::Irq_object
|
||||
{
|
||||
@ -26,22 +28,24 @@ class Genode::Irq_object
|
||||
addr_t _msi_data;
|
||||
addr_t _device_phys = 0; /* PCI config extended address */
|
||||
|
||||
Nova::Gsi_flags _gsi_flags { };
|
||||
|
||||
enum { KERNEL_CAP_COUNT_LOG2 = 0 };
|
||||
|
||||
Genode::addr_t irq_sel() const { return _kernel_caps; }
|
||||
addr_t irq_sel() const { return _kernel_caps; }
|
||||
|
||||
public:
|
||||
|
||||
Irq_object();
|
||||
~Irq_object();
|
||||
|
||||
Genode::addr_t msi_address() const { return _msi_addr; }
|
||||
Genode::addr_t msi_value() const { return _msi_data; }
|
||||
addr_t msi_address() const { return _msi_addr; }
|
||||
addr_t msi_value() const { return _msi_data; }
|
||||
|
||||
void sigh(Signal_context_capability cap);
|
||||
void ack_irq();
|
||||
|
||||
void start(unsigned irq, Genode::addr_t);
|
||||
void start(unsigned irq, addr_t, Irq_args const &);
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_OBJECT_H_ */
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <irq_root.h>
|
||||
#include <irq_args.h>
|
||||
#include <platform.h>
|
||||
|
||||
/* NOVA includes */
|
||||
@ -27,13 +28,12 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static bool irq_ctrl(Genode::addr_t irq_sel,
|
||||
Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
|
||||
Genode::addr_t sig_sel, Genode::addr_t virt_addr = 0)
|
||||
static bool irq_ctrl(addr_t irq_sel, addr_t &msi_addr, addr_t &msi_data,
|
||||
addr_t sig_sel, Nova::Gsi_flags flags, addr_t virt_addr)
|
||||
{
|
||||
/* assign IRQ to CPU && request msi data to be used by driver */
|
||||
uint8_t res = Nova::assign_gsi(irq_sel, virt_addr, boot_cpu(),
|
||||
msi_addr, msi_data, sig_sel);
|
||||
msi_addr, msi_data, sig_sel, flags);
|
||||
|
||||
if (res != Nova::NOVA_OK)
|
||||
error("setting up MSI failed - error ", res);
|
||||
@ -46,30 +46,28 @@ static bool irq_ctrl(Genode::addr_t irq_sel,
|
||||
}
|
||||
|
||||
|
||||
static bool associate(Genode::addr_t irq_sel,
|
||||
Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
|
||||
Genode::Signal_context_capability sig_cap,
|
||||
Genode::addr_t virt_addr = 0)
|
||||
{
|
||||
return irq_ctrl(irq_sel, msi_addr, msi_data, sig_cap.local_name(),
|
||||
virt_addr);
|
||||
}
|
||||
|
||||
|
||||
static void deassociate(Genode::addr_t irq_sel)
|
||||
static bool associate_gsi(addr_t irq_sel, Signal_context_capability sig_cap,
|
||||
Nova::Gsi_flags gsi_flags)
|
||||
{
|
||||
addr_t dummy1 = 0, dummy2 = 0;
|
||||
|
||||
if (!irq_ctrl(irq_sel, dummy1, dummy2, irq_sel))
|
||||
return irq_ctrl(irq_sel, dummy1, dummy2, sig_cap.local_name(), gsi_flags, 0);
|
||||
}
|
||||
|
||||
|
||||
static void deassociate(addr_t irq_sel)
|
||||
{
|
||||
addr_t dummy1 = 0, dummy2 = 0;
|
||||
|
||||
if (!irq_ctrl(irq_sel, dummy1, dummy2, irq_sel, Nova::Gsi_flags(), 0))
|
||||
warning("Irq could not be de-associated");
|
||||
}
|
||||
|
||||
|
||||
static bool msi(Genode::addr_t irq_sel, Genode::addr_t phys_mem,
|
||||
Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
|
||||
Genode::Signal_context_capability sig_cap)
|
||||
static bool associate_msi(addr_t irq_sel, addr_t phys_mem, addr_t &msi_addr,
|
||||
addr_t &msi_data, Signal_context_capability sig_cap)
|
||||
{
|
||||
return platform().region_alloc().alloc_aligned(4096, 12).convert<bool>(
|
||||
return platform().region_alloc().alloc_aligned(4096, 12).convert<bool>(
|
||||
|
||||
[&] (void *virt_ptr) {
|
||||
|
||||
@ -89,7 +87,7 @@ static bool msi(Genode::addr_t irq_sel, Genode::addr_t phys_mem,
|
||||
}
|
||||
|
||||
/* try to assign MSI to device */
|
||||
bool res = associate(irq_sel, msi_addr, msi_data, sig_cap, virt_addr);
|
||||
bool res = irq_ctrl(irq_sel, msi_addr, msi_data, sig_cap.local_name(), Nova::Gsi_flags(), virt_addr);
|
||||
|
||||
unmap_local(Nova::Mem_crd(virt_addr >> 12, 0, Rights(true, true, true)));
|
||||
platform().region_alloc().free(virt_ptr, 4096);
|
||||
@ -118,11 +116,12 @@ void Irq_object::sigh(Signal_context_capability cap)
|
||||
return;
|
||||
}
|
||||
|
||||
/* associate GSI or MSI to device belonging to device_phys */
|
||||
bool ok = false;
|
||||
if (_device_phys)
|
||||
ok = msi(irq_sel(), _device_phys, _msi_addr, _msi_data, cap);
|
||||
ok = associate_msi(irq_sel(), _device_phys, _msi_addr, _msi_data, cap);
|
||||
else
|
||||
ok = associate(irq_sel(), _msi_addr, _msi_data, cap);
|
||||
ok = associate_gsi(irq_sel(), cap, _gsi_flags);
|
||||
|
||||
if (!ok) {
|
||||
deassociate(irq_sel());
|
||||
@ -141,7 +140,7 @@ void Irq_object::ack_irq()
|
||||
}
|
||||
|
||||
|
||||
void Irq_object::start(unsigned irq, Genode::addr_t const device_phys)
|
||||
void Irq_object::start(unsigned irq, addr_t const device_phys, Irq_args const &irq_args)
|
||||
{
|
||||
/* map IRQ SM cap from kernel to core at irq_sel selector */
|
||||
using Nova::Obj_crd;
|
||||
@ -158,12 +157,29 @@ void Irq_object::start(unsigned irq, Genode::addr_t const device_phys)
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
/* initialize GSI IRQ flags */
|
||||
auto gsi_flags = [] (Irq_args const &args) {
|
||||
if (args.trigger() == Irq_session::TRIGGER_UNCHANGED
|
||||
|| args.polarity() == Irq_session::POLARITY_UNCHANGED)
|
||||
return Nova::Gsi_flags();
|
||||
|
||||
if (args.trigger() == Irq_session::TRIGGER_EDGE)
|
||||
return Nova::Gsi_flags(Nova::Gsi_flags::EDGE);
|
||||
|
||||
if (args.polarity() == Irq_session::POLARITY_HIGH)
|
||||
return Nova::Gsi_flags(Nova::Gsi_flags::HIGH);
|
||||
else
|
||||
return Nova::Gsi_flags(Nova::Gsi_flags::LOW);
|
||||
};
|
||||
|
||||
_gsi_flags = gsi_flags(irq_args);
|
||||
|
||||
/* associate GSI or MSI to device belonging to device_phys */
|
||||
bool ok = false;
|
||||
if (device_phys)
|
||||
ok = msi(irq_sel(), device_phys, _msi_addr, _msi_data, _sigh_cap);
|
||||
ok = associate_msi(irq_sel(), device_phys, _msi_addr, _msi_data, _sigh_cap);
|
||||
else
|
||||
ok = associate(irq_sel(), _msi_addr, _msi_data, _sigh_cap);
|
||||
ok = associate_gsi(irq_sel(), _sigh_cap, _gsi_flags);
|
||||
|
||||
if (!ok)
|
||||
throw Service_denied();
|
||||
@ -212,7 +228,9 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
:
|
||||
_irq_number(~0U), _irq_alloc(irq_alloc), _irq_object()
|
||||
{
|
||||
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
Irq_args const irq_args(args);
|
||||
|
||||
long irq_number = irq_args.irq_number();
|
||||
long device_phys = Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
if (device_phys) {
|
||||
|
||||
@ -232,7 +250,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
|
||||
_irq_number = (unsigned)irq_number;
|
||||
|
||||
_irq_object.start(_irq_number, device_phys);
|
||||
_irq_object.start(_irq_number, device_phys, irq_args);
|
||||
}
|
||||
|
||||
|
||||
@ -241,7 +259,7 @@ Irq_session_component::~Irq_session_component()
|
||||
if (_irq_number == ~0U)
|
||||
return;
|
||||
|
||||
Genode::addr_t free_irq = _irq_number;
|
||||
addr_t free_irq = _irq_number;
|
||||
_irq_alloc.free((void *)free_irq);
|
||||
}
|
||||
|
||||
@ -252,13 +270,13 @@ void Irq_session_component::ack_irq()
|
||||
}
|
||||
|
||||
|
||||
void Irq_session_component::sigh(Genode::Signal_context_capability cap)
|
||||
void Irq_session_component::sigh(Signal_context_capability cap)
|
||||
{
|
||||
_irq_object.sigh(cap);
|
||||
}
|
||||
|
||||
|
||||
Genode::Irq_session::Info Irq_session_component::info()
|
||||
Irq_session::Info Irq_session_component::info()
|
||||
{
|
||||
if (!_irq_object.msi_address() || !_irq_object.msi_value())
|
||||
return { .type = Info::Type::INVALID, .address = 0, .value = 0 };
|
||||
|
Loading…
x
Reference in New Issue
Block a user