mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
base-hw: global IRQ controller as Main member
Let the kernel's driver for the global IRQ controller be a member of the one Kernel::Main object instead of having it as static variables in the drivers for the local IRQ controllers. Note that this commit spares out renaming 'Pic' to 'Local_interrupt_controller' which would be more sensible now with the new 'Global_interrupt_controller' class. Furthermore, on ARM boards the commit doesn't move 'Distributer' stuff to the new global IRQ controller class as they don't have real data members (only MMIO) and can be instanciated for each CPU anew. However, the right way would be to instanciate them only once in Main as well. Ref #4217
This commit is contained in:
parent
441d137482
commit
02f00a999c
@ -26,7 +26,8 @@ namespace Board {
|
||||
|
||||
using namespace Hw::Imx6q_sabrelite_board;
|
||||
|
||||
class Pic : public Hw::Gicv2 { };
|
||||
class Global_interrupt_controller { };
|
||||
class Pic : public Hw::Gicv2 { public: Pic(Global_interrupt_controller &) { } };
|
||||
|
||||
using L2_cache = Hw::Pl310;
|
||||
|
||||
|
@ -26,7 +26,8 @@ namespace Board {
|
||||
|
||||
using namespace Hw::Nit6_solox_board;
|
||||
|
||||
class Pic : public Hw::Gicv2 { };
|
||||
class Global_interrupt_controller { };
|
||||
class Pic : public Hw::Gicv2 { public: Pic(Global_interrupt_controller &) { } };
|
||||
|
||||
using L2_cache = Hw::Pl310;
|
||||
|
||||
|
@ -26,7 +26,8 @@ namespace Board {
|
||||
|
||||
using namespace Hw::Pbxa9_board;
|
||||
|
||||
class Pic : public Hw::Gicv2 { };
|
||||
class Global_interrupt_controller { };
|
||||
class Pic : public Hw::Gicv2 { public: Pic(Global_interrupt_controller &) { } };
|
||||
|
||||
L2_cache & l2_cache();
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ namespace Board {
|
||||
|
||||
using namespace Hw::Pc_board;
|
||||
|
||||
class Pic : public Local_interrupt_controller { };
|
||||
|
||||
enum {
|
||||
VECTOR_REMAP_BASE = 48,
|
||||
TIMER_VECTOR_KERNEL = 32,
|
||||
|
@ -29,7 +29,8 @@ namespace Board {
|
||||
|
||||
using L2_cache = Hw::Pl310;
|
||||
|
||||
class Pic : public Hw::Gicv2 { };
|
||||
class Global_interrupt_controller { };
|
||||
class Pic : public Hw::Gicv2 { public: Pic(Global_interrupt_controller &) { } };
|
||||
|
||||
L2_cache & l2_cache();
|
||||
|
||||
|
@ -28,7 +28,8 @@ namespace Board {
|
||||
|
||||
using namespace Hw::Zynq_qemu_board;
|
||||
|
||||
class Pic : public Hw::Gicv2 { };
|
||||
class Global_interrupt_controller { };
|
||||
class Pic : public Hw::Gicv2 { public: Pic(Global_interrupt_controller &) { } };
|
||||
|
||||
L2_cache & l2_cache();
|
||||
}
|
||||
|
@ -174,13 +174,15 @@ addr_t Cpu::stack_start()
|
||||
}
|
||||
|
||||
|
||||
Cpu::Cpu(unsigned const id,
|
||||
Board::Address_space_id_allocator &addr_space_id_alloc,
|
||||
Irq::Pool &user_irq_pool,
|
||||
Cpu_pool &cpu_pool,
|
||||
Pd &core_pd)
|
||||
Cpu::Cpu(unsigned const id,
|
||||
Board::Address_space_id_allocator &addr_space_id_alloc,
|
||||
Irq::Pool &user_irq_pool,
|
||||
Cpu_pool &cpu_pool,
|
||||
Pd &core_pd,
|
||||
Board::Global_interrupt_controller &global_irq_ctrl)
|
||||
:
|
||||
_id { id },
|
||||
_pic { global_irq_ctrl },
|
||||
_timer { *this },
|
||||
_scheduler { _idle, _quota(), _fill() },
|
||||
_idle { addr_space_id_alloc, user_irq_pool, cpu_pool, *this,
|
||||
@ -198,13 +200,14 @@ Cpu::Cpu(unsigned const id,
|
||||
|
||||
void
|
||||
Cpu_pool::
|
||||
initialize_executing_cpu(Board::Address_space_id_allocator &addr_space_id_alloc,
|
||||
Irq::Pool &user_irq_pool,
|
||||
Pd &core_pd)
|
||||
initialize_executing_cpu(Board::Address_space_id_allocator &addr_space_id_alloc,
|
||||
Irq::Pool &user_irq_pool,
|
||||
Pd &core_pd,
|
||||
Board::Global_interrupt_controller &global_irq_ctrl)
|
||||
{
|
||||
unsigned id = Cpu::executing_id();
|
||||
_cpus[id].construct(
|
||||
id, addr_space_id_alloc, user_irq_pool, *this, core_pd);
|
||||
id, addr_space_id_alloc, user_irq_pool, *this, core_pd, global_irq_ctrl);
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,7 +111,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
|
||||
|
||||
|
||||
unsigned const _id;
|
||||
Board::Pic _pic {};
|
||||
Board::Pic _pic;
|
||||
Timer _timer;
|
||||
Cpu_scheduler _scheduler;
|
||||
Idle_thread _idle;
|
||||
@ -131,11 +131,12 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
|
||||
/**
|
||||
* Construct object for CPU 'id'
|
||||
*/
|
||||
Cpu(unsigned const id,
|
||||
Board::Address_space_id_allocator &addr_space_id_alloc,
|
||||
Irq::Pool &user_irq_pool,
|
||||
Cpu_pool &cpu_pool,
|
||||
Pd &core_pd);
|
||||
Cpu(unsigned const id,
|
||||
Board::Address_space_id_allocator &addr_space_id_alloc,
|
||||
Irq::Pool &user_irq_pool,
|
||||
Cpu_pool &cpu_pool,
|
||||
Pd &core_pd,
|
||||
Board::Global_interrupt_controller &global_irq_ctrl);
|
||||
|
||||
static inline unsigned primary_id() { return 0; }
|
||||
|
||||
@ -207,9 +208,10 @@ class Kernel::Cpu_pool
|
||||
Cpu_pool(unsigned nr_of_cpus);
|
||||
|
||||
void
|
||||
initialize_executing_cpu(Board::Address_space_id_allocator &addr_space_id_alloc,
|
||||
Irq::Pool &user_irq_pool,
|
||||
Pd &core_pd);
|
||||
initialize_executing_cpu(Board::Address_space_id_allocator &addr_space_id_alloc,
|
||||
Irq::Pool &user_irq_pool,
|
||||
Pd &core_pd,
|
||||
Board::Global_interrupt_controller &global_irq_ctrl);
|
||||
|
||||
/**
|
||||
* Return object of CPU 'id'
|
||||
|
@ -51,6 +51,7 @@ class Kernel::Main
|
||||
Board::Address_space_id_allocator _addr_space_id_alloc { };
|
||||
Genode::Core_platform_pd _core_platform_pd { _addr_space_id_alloc };
|
||||
Genode::Constructible<Core_main_thread> _core_main_thread { };
|
||||
Board::Global_interrupt_controller _global_irq_ctrl { };
|
||||
|
||||
void _handle_kernel_entry();
|
||||
|
||||
@ -137,7 +138,8 @@ void Kernel::main_initialize_and_handle_kernel_entry()
|
||||
Main::_instance->_cpu_pool.initialize_executing_cpu(
|
||||
Main::_instance->_addr_space_id_alloc,
|
||||
Main::_instance->_user_irq_pool,
|
||||
Main::_instance->_core_platform_pd.kernel_pd());
|
||||
Main::_instance->_core_platform_pd.kernel_pd(),
|
||||
Main::_instance->_global_irq_ctrl);
|
||||
|
||||
nr_of_initialized_cpus++;
|
||||
};
|
||||
|
@ -37,9 +37,11 @@ bool Board::Pic::Usb_dwc_otg::_need_trigger_sof(uint32_t host_frame,
|
||||
}
|
||||
|
||||
|
||||
Board::Pic::Usb_dwc_otg::Usb_dwc_otg()
|
||||
Board::Pic::
|
||||
Usb_dwc_otg::Usb_dwc_otg(Global_interrupt_controller &global_irq_ctrl)
|
||||
:
|
||||
Mmio(Platform::mmio_to_virt(Board::USB_DWC_OTG_BASE))
|
||||
Mmio { Platform::mmio_to_virt(Board::USB_DWC_OTG_BASE) },
|
||||
_global_irq_ctrl { global_irq_ctrl }
|
||||
{
|
||||
write<Guid::Num>(0);
|
||||
write<Guid::Num_valid>(false);
|
||||
@ -52,10 +54,8 @@ bool Board::Pic::Usb_dwc_otg::handle_sof()
|
||||
if (!_is_sof())
|
||||
return false;
|
||||
|
||||
static int cnt = 0;
|
||||
|
||||
if (++cnt == 8*20) {
|
||||
cnt = 0;
|
||||
if (_global_irq_ctrl.increment_and_return_sof_cnt() == 8*20) {
|
||||
_global_irq_ctrl.reset_sof_cnt();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -72,9 +72,10 @@ bool Board::Pic::Usb_dwc_otg::handle_sof()
|
||||
}
|
||||
|
||||
|
||||
Board::Pic::Pic()
|
||||
Board::Pic::Pic(Global_interrupt_controller &global_irq_ctrl)
|
||||
:
|
||||
Mmio(Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE))
|
||||
Mmio { Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE) },
|
||||
_usb { global_irq_ctrl }
|
||||
{
|
||||
mask();
|
||||
}
|
||||
|
@ -17,7 +17,25 @@
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
|
||||
namespace Board { class Pic; }
|
||||
namespace Board {
|
||||
|
||||
class Global_interrupt_controller;
|
||||
class Pic;
|
||||
}
|
||||
|
||||
|
||||
class Board::Global_interrupt_controller
|
||||
{
|
||||
private:
|
||||
|
||||
int _sof_cnt { 0 };
|
||||
|
||||
public:
|
||||
|
||||
int increment_and_return_sof_cnt() { return ++_sof_cnt; }
|
||||
|
||||
void reset_sof_cnt() { _sof_cnt = 0; }
|
||||
};
|
||||
|
||||
|
||||
class Board::Pic : Genode::Mmio
|
||||
@ -80,6 +98,8 @@ class Board::Pic : Genode::Mmio
|
||||
struct Num : Bitfield<0, 14> { };
|
||||
};
|
||||
|
||||
Global_interrupt_controller &_global_irq_ctrl;
|
||||
|
||||
bool _is_sof() const
|
||||
{
|
||||
return read<Core_irq_status::Sof>();
|
||||
@ -90,12 +110,12 @@ class Board::Pic : Genode::Mmio
|
||||
|
||||
public:
|
||||
|
||||
Usb_dwc_otg();
|
||||
Usb_dwc_otg(Global_interrupt_controller &global_irq_ctrl);
|
||||
|
||||
bool handle_sof();
|
||||
};
|
||||
|
||||
Usb_dwc_otg _usb { };
|
||||
Usb_dwc_otg _usb;
|
||||
|
||||
/**
|
||||
* Return true if specified interrupt is pending
|
||||
@ -108,7 +128,7 @@ class Board::Pic : Genode::Mmio
|
||||
|
||||
public:
|
||||
|
||||
Pic();
|
||||
Pic(Global_interrupt_controller &global_irq_ctrl);
|
||||
|
||||
bool take_request(unsigned &irq);
|
||||
void finish_request() { }
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
Board::Pic::Pic()
|
||||
Board::Pic::Pic(Global_interrupt_controller &)
|
||||
:
|
||||
Genode::Mmio(Genode::Platform::mmio_to_virt(Board::LOCAL_IRQ_CONTROLLER_BASE))
|
||||
{ }
|
||||
|
@ -16,7 +16,11 @@
|
||||
|
||||
#include <util/mmio.h>
|
||||
|
||||
namespace Board { class Pic; }
|
||||
namespace Board {
|
||||
|
||||
class Global_interrupt_controller { };
|
||||
class Pic;
|
||||
}
|
||||
|
||||
|
||||
class Board::Pic : Genode::Mmio
|
||||
@ -54,7 +58,7 @@ class Board::Pic : Genode::Mmio
|
||||
|
||||
public:
|
||||
|
||||
Pic();
|
||||
Pic(Global_interrupt_controller &);
|
||||
|
||||
bool take_request(unsigned &irq);
|
||||
void finish_request() { }
|
||||
|
@ -27,7 +27,8 @@ namespace Board {
|
||||
struct Vm_page_table {};
|
||||
struct Vm_page_table_array {};
|
||||
|
||||
struct Pic : Hw::Pic { struct Virtual_context {}; };
|
||||
class Global_interrupt_controller { };
|
||||
struct Pic : Hw::Pic { struct Virtual_context {}; Pic(Global_interrupt_controller &) { } };
|
||||
struct Vcpu_context { Vcpu_context(Kernel::Cpu &) {} };
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,11 @@
|
||||
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board { struct Pic; };
|
||||
namespace Board {
|
||||
|
||||
class Global_interrupt_controller { };
|
||||
class Pic;
|
||||
};
|
||||
|
||||
|
||||
class Board::Pic : public Hw::Gicv2
|
||||
@ -50,6 +54,8 @@ class Board::Pic : public Hw::Gicv2
|
||||
|
||||
bool ack_virtual_irq(Virtual_context & c);
|
||||
void insert_virtual_irq(Virtual_context & c, unsigned irq);
|
||||
|
||||
Pic(Global_interrupt_controller &) { }
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__ARM__VIRTUALIZATION__GICV2_H_ */
|
||||
|
@ -16,7 +16,11 @@
|
||||
|
||||
#include <hw/spec/arm/gicv3.h>
|
||||
|
||||
namespace Board { class Pic; };
|
||||
namespace Board {
|
||||
|
||||
class Global_interrupt_controller { };
|
||||
class Pic;
|
||||
};
|
||||
|
||||
|
||||
class Board::Pic : public Hw::Pic
|
||||
@ -51,6 +55,8 @@ class Board::Pic : public Hw::Pic
|
||||
|
||||
c.lr = irq | 1ULL << 41 | 1ULL << 60 | 1ULL << 62;
|
||||
}
|
||||
|
||||
Pic(Global_interrupt_controller &) { }
|
||||
};
|
||||
|
||||
#endif /* _CORE__SPEC__ARM__VIRTUALIZATION__GICV3_H_ */
|
||||
|
@ -16,7 +16,8 @@
|
||||
#include <pic.h>
|
||||
#include <platform.h>
|
||||
|
||||
Board::Pic::Pic() :
|
||||
Board::Pic::Pic(Global_interrupt_controller &)
|
||||
:
|
||||
_plic(Genode::Platform::mmio_to_virt(Board::PLIC_BASE))
|
||||
{
|
||||
/* enable external interrupts */
|
||||
|
@ -20,7 +20,11 @@
|
||||
#include <util/mmio.h>
|
||||
#include <plic.h>
|
||||
|
||||
namespace Board { class Pic; }
|
||||
namespace Board {
|
||||
|
||||
class Global_interrupt_controller { };
|
||||
class Pic;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -44,7 +48,7 @@ class Board::Pic
|
||||
NR_OF_IRQ = Plic::NR_OF_IRQ,
|
||||
};
|
||||
|
||||
Pic();
|
||||
Pic(Global_interrupt_controller &);
|
||||
|
||||
bool take_request(unsigned & irq)
|
||||
{
|
||||
|
@ -24,11 +24,8 @@
|
||||
using namespace Genode;
|
||||
using namespace Board;
|
||||
|
||||
|
||||
uint8_t Pic::lapic_ids[NR_OF_CPUS];
|
||||
|
||||
|
||||
enum {
|
||||
REMAP_BASE = Board::VECTOR_REMAP_BASE,
|
||||
PIC_CMD_MASTER = 0x20,
|
||||
PIC_CMD_SLAVE = 0xa0,
|
||||
PIC_DATA_MASTER = 0x21,
|
||||
@ -36,9 +33,15 @@ enum {
|
||||
};
|
||||
|
||||
|
||||
Pic::Pic()
|
||||
/***************************************
|
||||
** Board::Local_interrupt_controller **
|
||||
***************************************/
|
||||
|
||||
Local_interrupt_controller::
|
||||
Local_interrupt_controller(Global_interrupt_controller &global_irq_ctrl)
|
||||
:
|
||||
Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()))
|
||||
Mmio { Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()) },
|
||||
_global_irq_ctrl { global_irq_ctrl }
|
||||
{
|
||||
/* Start initialization sequence in cascade mode */
|
||||
outb(PIC_CMD_MASTER, 0x11);
|
||||
@ -68,7 +71,7 @@ Pic::Pic()
|
||||
}
|
||||
|
||||
|
||||
bool Pic::take_request(unsigned &irq)
|
||||
bool Local_interrupt_controller::take_request(unsigned &irq)
|
||||
{
|
||||
irq = get_lowest_bit();
|
||||
if (!irq) {
|
||||
@ -80,32 +83,33 @@ bool Pic::take_request(unsigned &irq)
|
||||
}
|
||||
|
||||
|
||||
void Pic::finish_request()
|
||||
void Local_interrupt_controller::finish_request()
|
||||
{
|
||||
write<EOI>(0);
|
||||
}
|
||||
|
||||
|
||||
void Pic::unmask(unsigned const i, unsigned)
|
||||
void Local_interrupt_controller::unmask(unsigned const i, unsigned)
|
||||
{
|
||||
ioapic.toggle_mask(i, false);
|
||||
_global_irq_ctrl.toggle_mask(i, false);
|
||||
}
|
||||
|
||||
|
||||
void Pic::mask(unsigned const i)
|
||||
void Local_interrupt_controller::mask(unsigned const i)
|
||||
{
|
||||
ioapic.toggle_mask(i, true);
|
||||
_global_irq_ctrl.toggle_mask(i, true);
|
||||
}
|
||||
|
||||
|
||||
void Pic::irq_mode(unsigned irq_number, unsigned trigger,
|
||||
unsigned polarity)
|
||||
void Local_interrupt_controller::irq_mode(unsigned irq_number,
|
||||
unsigned trigger,
|
||||
unsigned polarity)
|
||||
{
|
||||
ioapic.irq_mode(irq_number, trigger, polarity);
|
||||
_global_irq_ctrl.irq_mode(irq_number, trigger, polarity);
|
||||
}
|
||||
|
||||
|
||||
inline unsigned Pic::get_lowest_bit(void)
|
||||
inline unsigned Local_interrupt_controller::get_lowest_bit()
|
||||
{
|
||||
unsigned bit, vec_base = 0;
|
||||
|
||||
@ -120,7 +124,7 @@ inline unsigned Pic::get_lowest_bit(void)
|
||||
}
|
||||
|
||||
|
||||
void Pic::send_ipi(unsigned const cpu_id)
|
||||
void Local_interrupt_controller::send_ipi(unsigned const cpu_id)
|
||||
{
|
||||
while (read<Icr_low::Delivery_status>())
|
||||
asm volatile("pause" : : : "memory");
|
||||
@ -128,9 +132,9 @@ void Pic::send_ipi(unsigned const cpu_id)
|
||||
Icr_high::access_t icr_high = 0;
|
||||
Icr_low::access_t icr_low = 0;
|
||||
|
||||
Icr_high::Destination::set(icr_high, lapic_ids[cpu_id]);
|
||||
Icr_high::Destination::set(icr_high, _global_irq_ctrl.lapic_id(cpu_id));
|
||||
|
||||
Icr_low::Vector::set(icr_low, Pic::IPI);
|
||||
Icr_low::Vector::set(icr_low, Local_interrupt_controller::IPI);
|
||||
Icr_low::Level_assert::set(icr_low);
|
||||
|
||||
/* program */
|
||||
@ -139,14 +143,26 @@ void Pic::send_ipi(unsigned const cpu_id)
|
||||
}
|
||||
|
||||
|
||||
Ioapic::Irq_mode Ioapic::_irq_mode[IRQ_COUNT];
|
||||
/****************************************
|
||||
** Board::Global_interrupt_controller **
|
||||
****************************************/
|
||||
|
||||
uint8_t Global_interrupt_controller::lapic_id(unsigned cpu_id) const
|
||||
{
|
||||
return _lapic_id[cpu_id];
|
||||
}
|
||||
|
||||
|
||||
enum { REMAP_BASE = Board::VECTOR_REMAP_BASE };
|
||||
void Global_interrupt_controller::lapic_id(unsigned cpu_id,
|
||||
uint8_t lapic_id)
|
||||
{
|
||||
_lapic_id[cpu_id] = lapic_id;
|
||||
}
|
||||
|
||||
|
||||
void Ioapic::irq_mode(unsigned irq_number, unsigned trigger,
|
||||
unsigned polarity)
|
||||
void Global_interrupt_controller::irq_mode(unsigned irq_number,
|
||||
unsigned trigger,
|
||||
unsigned polarity)
|
||||
{
|
||||
const unsigned irq_nr = irq_number - REMAP_BASE;
|
||||
bool needs_sync = false;
|
||||
@ -185,7 +201,7 @@ void Ioapic::irq_mode(unsigned irq_number, unsigned trigger,
|
||||
}
|
||||
|
||||
|
||||
void Ioapic::_update_irt_entry(unsigned irq)
|
||||
void Global_interrupt_controller::_update_irt_entry(unsigned irq)
|
||||
{
|
||||
Irte::access_t irte;
|
||||
|
||||
@ -200,7 +216,8 @@ void Ioapic::_update_irt_entry(unsigned irq)
|
||||
}
|
||||
|
||||
|
||||
Irte::access_t Ioapic::_create_irt_entry(unsigned const irq)
|
||||
Irte::access_t
|
||||
Global_interrupt_controller::_create_irt_entry(unsigned const irq)
|
||||
{
|
||||
Irte::access_t irte = REMAP_BASE + irq;
|
||||
Irte::Mask::set(irte, 1);
|
||||
@ -212,7 +229,7 @@ Irte::access_t Ioapic::_create_irt_entry(unsigned const irq)
|
||||
}
|
||||
|
||||
|
||||
Ioapic::Ioapic()
|
||||
Global_interrupt_controller::Global_interrupt_controller()
|
||||
:
|
||||
Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::MMIO_IOAPIC_BASE))
|
||||
{
|
||||
@ -242,7 +259,8 @@ Ioapic::Ioapic()
|
||||
};
|
||||
|
||||
|
||||
void Ioapic::toggle_mask(unsigned const vector, bool const set)
|
||||
void Global_interrupt_controller::toggle_mask(unsigned const vector,
|
||||
bool const set)
|
||||
{
|
||||
/*
|
||||
* Ignore toggle requests for vectors not handled by the I/O APIC.
|
||||
|
@ -18,9 +18,6 @@
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
|
||||
namespace Board {
|
||||
|
||||
/*
|
||||
@ -31,12 +28,12 @@ namespace Board {
|
||||
/**
|
||||
* IO advanced programmable interrupt controller
|
||||
*/
|
||||
class Ioapic;
|
||||
class Global_interrupt_controller;
|
||||
|
||||
/**
|
||||
* Programmable interrupt controller for core
|
||||
*/
|
||||
class Pic;
|
||||
class Local_interrupt_controller;
|
||||
|
||||
enum { IRQ_COUNT = 256 };
|
||||
}
|
||||
@ -50,13 +47,10 @@ struct Board::Irte : Genode::Register<64>
|
||||
};
|
||||
|
||||
|
||||
class Board::Ioapic : public Genode::Mmio
|
||||
class Board::Global_interrupt_controller : public Genode::Mmio
|
||||
{
|
||||
private:
|
||||
|
||||
/* Number of Redirection Table entries */
|
||||
unsigned _irte_count = 0;
|
||||
|
||||
enum {
|
||||
/* Register selectors */
|
||||
IOAPICVER = 0x01,
|
||||
@ -78,7 +72,19 @@ class Board::Ioapic : public Genode::Mmio
|
||||
unsigned polarity;
|
||||
};
|
||||
|
||||
static Irq_mode _irq_mode[IRQ_COUNT];
|
||||
/*
|
||||
* Registers
|
||||
*/
|
||||
|
||||
struct Ioregsel : Register<0x00, 32> { };
|
||||
struct Iowin : Register<0x10, 32>
|
||||
{
|
||||
struct Maximum_redirection_entry : Bitfield<16, 8> { };
|
||||
};
|
||||
|
||||
unsigned _irte_count = 0; /* number of redirection table entries */
|
||||
Genode::uint8_t _lapic_id[NR_OF_CPUS]; /* unique name of the LAPIC of each CPU */
|
||||
Irq_mode _irq_mode[IRQ_COUNT];
|
||||
|
||||
/**
|
||||
* Return whether 'irq' is an edge-triggered interrupt
|
||||
@ -104,7 +110,7 @@ class Board::Ioapic : public Genode::Mmio
|
||||
|
||||
public:
|
||||
|
||||
Ioapic();
|
||||
Global_interrupt_controller();
|
||||
|
||||
/**
|
||||
* Set/unset mask bit of IRTE for given vector
|
||||
@ -112,7 +118,8 @@ class Board::Ioapic : public Genode::Mmio
|
||||
* \param vector targeted vector
|
||||
* \param set whether to set or to unset the mask bit
|
||||
*/
|
||||
void toggle_mask(unsigned const vector, bool const set);
|
||||
void toggle_mask(unsigned const vector,
|
||||
bool const set);
|
||||
|
||||
/**
|
||||
* Setup mode of an IRQ to specified trigger mode and polarity
|
||||
@ -121,22 +128,23 @@ class Board::Ioapic : public Genode::Mmio
|
||||
* \param trigger new interrupt trigger mode
|
||||
* \param polarity new interrupt polarity setting
|
||||
*/
|
||||
void irq_mode(unsigned irq_number, unsigned trigger,
|
||||
void irq_mode(unsigned irq_number,
|
||||
unsigned trigger,
|
||||
unsigned polarity);
|
||||
|
||||
/*
|
||||
* Registers
|
||||
*/
|
||||
|
||||
struct Ioregsel : Register<0x00, 32> { };
|
||||
struct Iowin : Register<0x10, 32>
|
||||
{
|
||||
struct Maximum_redirection_entry : Bitfield<16, 8> { };
|
||||
};
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
void lapic_id(unsigned cpu_id,
|
||||
Genode::uint8_t lapic_id);
|
||||
|
||||
Genode::uint8_t lapic_id(unsigned cpu_id) const;
|
||||
};
|
||||
|
||||
|
||||
class Board::Pic : public Genode::Mmio
|
||||
class Board::Local_interrupt_controller : public Genode::Mmio
|
||||
{
|
||||
private:
|
||||
|
||||
@ -173,6 +181,8 @@ class Board::Pic : public Genode::Mmio
|
||||
struct Destination : Bitfield<24, 8> { };
|
||||
};
|
||||
|
||||
Global_interrupt_controller &_global_irq_ctrl;
|
||||
|
||||
/**
|
||||
* Determine lowest pending interrupt in ISR register
|
||||
*
|
||||
@ -181,11 +191,6 @@ class Board::Pic : public Genode::Mmio
|
||||
*/
|
||||
inline unsigned get_lowest_bit(void);
|
||||
|
||||
/**
|
||||
* Mapping of our logical boot CPUs to the local APIC IDs
|
||||
*/
|
||||
static Genode::uint8_t lapic_ids[NR_OF_CPUS];
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
@ -201,9 +206,7 @@ class Board::Pic : public Genode::Mmio
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Pic();
|
||||
|
||||
Ioapic ioapic { };
|
||||
Local_interrupt_controller(Global_interrupt_controller &global_irq_ctrl);
|
||||
|
||||
bool take_request(unsigned &irq);
|
||||
|
||||
@ -219,7 +222,7 @@ class Board::Pic : public Genode::Mmio
|
||||
{
|
||||
if (cpu_id < NR_OF_CPUS) {
|
||||
Id::access_t const lapic_id = read<Id>();
|
||||
lapic_ids[cpu_id] = (lapic_id >> 24) & 0xff;
|
||||
_global_irq_ctrl.lapic_id(cpu_id, (lapic_id >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user