X-Git-Url: https://rtime.felk.cvut.cz/gitweb/l4.git/blobdiff_plain/987bc7f894cfdc5c72f6a3d3ed67e5bdf8963413..8d9e85aaae867f39cdd610261e3a4181c25add2d:/kernel/fiasco/src/kern/io_apic.cpp diff --git a/kernel/fiasco/src/kern/io_apic.cpp b/kernel/fiasco/src/kern/io_apic.cpp index 024c48a8b..88ffe683e 100644 --- a/kernel/fiasco/src/kern/io_apic.cpp +++ b/kernel/fiasco/src/kern/io_apic.cpp @@ -44,15 +44,25 @@ public: class Io_apic { -private: - Unsigned32 volatile adr; - Unsigned32 dummy[3]; - Unsigned32 volatile data; +public: + enum { Max_ioapics = 6 }; - static Spin_lock _l; - static Io_apic *_apic; +private: + struct Apic + { + Unsigned32 volatile adr; + Unsigned32 dummy[3]; + Unsigned32 volatile data; + } __attribute__((packed)); + + Apic *_apic; + Spin_lock<> _l; + unsigned _offset; + + static Io_apic _apics[Max_ioapics]; + static unsigned _nr_irqs; static Acpi_madt const *_madt; -} __attribute__((packed)); +}; IMPLEMENTATION: @@ -62,20 +72,19 @@ IMPLEMENTATION: #include "kip.h" #include "lock_guard.h" -Io_apic *Io_apic::_apic; -Spin_lock Io_apic::_l; +Io_apic Io_apic::_apics[Io_apic::Max_ioapics]; Acpi_madt const *Io_apic::_madt; - +unsigned Io_apic::_nr_irqs; PRIVATE inline NEEDS["lock_guard.h"] Mword Io_apic::read(int reg) { - Lock_guard g(&_l); - adr = reg; + Lock_guard g(&_l); + _apic->adr = reg; asm volatile ("": : :"memory"); - return data; + return _apic->data; } PRIVATE inline NEEDS["lock_guard.h"] @@ -83,23 +92,23 @@ void Io_apic::modify(int reg, Mword set_bits, Mword del_bits) { register Mword tmp; - Lock_guard g(&_l); - adr = reg; + Lock_guard g(&_l); + _apic->adr = reg; asm volatile ("": : :"memory"); - tmp = data; + tmp = _apic->data; tmp &= ~del_bits; tmp |= set_bits; - data = tmp; + _apic->data = tmp; } PRIVATE inline NEEDS["lock_guard.h"] void Io_apic::write(int reg, Mword value) { - Lock_guard g(&_l); - adr = reg; + Lock_guard g(&_l); + _apic->adr = reg; asm volatile ("": : :"memory"); - data = value; + _apic->data = value; } PRIVATE inline @@ -141,22 +150,61 @@ Io_apic::init() printf("Could not find APIC in RSDT nor XSDT, skipping init\n"); return false; } - printf("MADT = %p\n", _madt); + printf("IO-APIC: MADT = %p\n", _madt); + + int n_apics = 0; + + for (n_apics = 0; + Acpi_madt::Io_apic const *ioapic = static_cast(_madt->find(Acpi_madt::IOAPIC, n_apics)); + ++n_apics) + { + + if (n_apics >= Max_ioapics) + { + printf("Maximum number of IO-APICs exceeded ignore further IO-APICs\n"); + break; + } + + printf("IO-APIC[%2d]: struct: %p adr=%x\n", n_apics, ioapic, ioapic->adr); + + Address offs; + Address va = Mem_layout::alloc_io_vmem(Config::PAGE_SIZE); + assert (va); - Acpi_madt::Io_apic const *ioapic - = static_cast(_madt->find(Acpi_madt::IOAPIC, 0)); + Kmem::map_phys_page(ioapic->adr, va, false, true, &offs); - if (!ioapic) + Kip::k()->add_mem_region(Mem_desc(ioapic->adr, ioapic->adr + Config::PAGE_SIZE -1, Mem_desc::Reserved)); + + + Io_apic *apic = Io_apic::apic(n_apics); + apic->_apic = (Io_apic::Apic*)(va + offs); + apic->write(0, 0); + unsigned ne = apic->num_entries(); + apic->_offset = _nr_irqs; + _nr_irqs += ne + 1; + + for (unsigned i = 0; i <= ne; ++i) + { + int v = 0x20+i; + Io_apic_entry e(v, Io_apic_entry::Fixed, Io_apic_entry::Physical, + Io_apic_entry::High_active, Io_apic_entry::Edge, 0); + apic->write_entry(i, e); + } + + printf("IO-APIC[%2d]: pins %u\n", n_apics, ne); + apic->dump(); + } + + if (!n_apics) { printf("IO-APIC: Could not find IO-APIC in MADT, skip init\n"); return false; } - printf("IO-APIC: struct: %p adr=%x\n", ioapic, ioapic->adr); + printf("IO-APIC: dual 8259: %s\n", _madt->apic_flags & 1 ? "yes" : "no"); - unsigned tmp = 0; - for (;;++tmp) + for (unsigned tmp = 0;;++tmp) { Acpi_madt::Irq_source const *irq = static_cast(_madt->find(Acpi_madt::Irq_src_ovr, tmp)); @@ -167,39 +215,21 @@ Io_apic::init() printf("IO-APIC: ovr[%2u] %02x -> %x\n", tmp, irq->src, irq->irq); } - if (tmp) - printf("IO-APIC: NOTE IRQ overrides are ignored!\n"); - - Address offs; - Kmem::map_phys_page(ioapic->adr, Mem_layout::Io_apic_page, - false, true, &offs); - - Kip::k()->add_mem_region(Mem_desc(ioapic->adr, ioapic->adr + Config::PAGE_SIZE -1, Mem_desc::Reserved)); - - - Io_apic *apic = (Io_apic*)(Mem_layout::Io_apic_page + offs); - _apic = apic; - apic->write(0, 0); - unsigned ne = apic->num_entries(); - - for (unsigned i = 0; i <= ne; ++i) - { - int v = 0x20+i; - Io_apic_entry e(v, Io_apic_entry::Fixed, Io_apic_entry::Physical, - Io_apic_entry::High_active, Io_apic_entry::Edge, 0); - apic->write_entry(i, e); - } - - printf("IO-APIC: pins %u\n", ne); - dump(); - return true; }; +PUBLIC static +unsigned +Io_apic::total_irqs() +{ return _nr_irqs; } + PUBLIC static unsigned Io_apic::legacy_override(unsigned i) { + if (!_madt) + return i; + unsigned tmp = 0; for (;;++tmp) { @@ -215,14 +245,14 @@ Io_apic::legacy_override(unsigned i) return i; } -PUBLIC static +PUBLIC void Io_apic::dump() { - unsigned ne = _apic->num_entries(); + unsigned ne = num_entries(); for (unsigned i = 0; i <= ne; ++i) { - Io_apic_entry e = _apic->read_entry(i); + Io_apic_entry e = read_entry(i); printf(" PIN[%2u%c]: vector=%2x, del=%u, dm=%s, dest=%u (%s, %s)\n", i, e.mask() ? 'm' : '.', e.vector(), e.delivery(), e.dest_mode() ? "logical" : "physical", @@ -236,54 +266,74 @@ Io_apic::dump() PUBLIC static inline bool Io_apic::active() -{ return _apic; } +{ return _apics[0]._apic; } -PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::modify] +PUBLIC inline +bool +Io_apic::valid() const { return _apic; } + +PUBLIC inline NEEDS["kdb_ke.h", Io_apic::modify] void Io_apic::mask(unsigned irq) { //assert_kdb(irq <= _apic->num_entries()); - _apic->modify(0x10 + irq * 2, 1UL << 16, 0); + modify(0x10 + irq * 2, 1UL << 16, 0); } -PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::modify] +PUBLIC inline NEEDS["kdb_ke.h", Io_apic::modify] void Io_apic::unmask(unsigned irq) { //assert_kdb(irq <= _apic->num_entries()); - _apic->modify(0x10 + irq * 2, 0, 1UL << 16); + modify(0x10 + irq * 2, 0, 1UL << 16); } -PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::read] +PUBLIC inline NEEDS["kdb_ke.h", Io_apic::read] bool Io_apic::masked(unsigned irq) { //assert_kdb(irq <= _apic->num_entries()); - return _apic->read(0x10 + irq * 2) & (1UL << 16); + return read(0x10 + irq * 2) & (1UL << 16); } -PUBLIC static inline NEEDS[Io_apic::read] +PUBLIC inline NEEDS[Io_apic::read] void Io_apic::sync() { (void)_apic->data; } -PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::modify] +PUBLIC inline NEEDS["kdb_ke.h", Io_apic::modify] void Io_apic::set_dest(unsigned irq, Mword dst) { //assert_kdb(irq <= _apic->num_entries()); - _apic->modify(0x11 + irq * 2, dst & (~0UL << 24), ~0UL << 24); + modify(0x11 + irq * 2, dst & (~0UL << 24), ~0UL << 24); } -PUBLIC static inline NEEDS[Io_apic::num_entries] +PUBLIC inline NEEDS[Io_apic::num_entries] unsigned Io_apic::nr_irqs() -{ return _apic->num_entries() + 1; } +{ return num_entries() + 1; } + +PUBLIC inline +unsigned +Io_apic::gsi_offset() const { return _offset; } PUBLIC static inline Io_apic * -Io_apic::apic() -{ return _apic; } +Io_apic::apic(unsigned idx) +{ return &_apics[idx]; } + +PUBLIC static +unsigned +Io_apic::find_apic(unsigned irqnum) +{ + for (unsigned i = Max_ioapics; i > 0; --i) + { + if (_apics[i-1]._apic && _apics[i-1]._offset < irqnum) + return i - 1; + } + return 0; +};