diff --git a/repos/pc/src/driver/platform/pc/intel/io_mmu.cc b/repos/pc/src/driver/platform/pc/intel/io_mmu.cc index 24694dee31..0335cbf98d 100644 --- a/repos/pc/src/driver/platform/pc/intel/io_mmu.cc +++ b/repos/pc/src/driver/platform/pc/intel/io_mmu.cc @@ -315,62 +315,17 @@ void Intel::Io_mmu::default_mappings_complete() /* insert contexts into managed root table */ _default_mappings.copy_stage2(_managed_root_table); - /* set root table address */ - write(rtp); - - /* issue set root table pointer command */ - _global_command(1); - - /* caches must be cleared if Esrtps is not set (see 6.6) */ - if (!read()) - invalidator().invalidate_all(); - - /* enable IOMMU */ - if (!read()) - _global_command(1); + _enable_translation(); log("enabled IOMMU ", name(), " with default mappings"); } -void Intel::Io_mmu::suspend() -{ - _s3_fec = read(); - _s3_fedata = read(); - _s3_feaddr = read(); - _s3_rta = read(); -} - - void Intel::Io_mmu::resume() { - /* disable queued invalidation interface if it was re-enabled by kernel */ - if (read() && read()) - _global_command(false); - - if (read()) { - /* enable queued invalidation if supported */ - _queued_invalidator.construct(_env, base() + 0x80); - _global_command(true); - } - - /* restore fault events only if kernel did not enable IRQ remapping */ - if (!read()) { - write(_s3_fec); - write(_s3_fedata); - write(_s3_feaddr); - } - - /* issue set root table pointer command */ - write(_s3_rta); - _global_command(1); - - if (!read()) - invalidator().invalidate_all(); - - /* enable IOMMU */ - if (!read()) - _global_command(1); + _init(); + _enable_translation(); + _enable_irq_remapping(); } @@ -411,6 +366,71 @@ void Intel::Io_mmu::_enable_irq_remapping() } +void Intel::Io_mmu::_enable_translation() +{ + Root_table_address::access_t rtp = + Root_table_address::Address::masked(_managed_root_table.phys_addr()); + + /* set root table address */ + write(rtp); + + /* issue set root table pointer command */ + _global_command(1); + + /* caches must be cleared if Esrtps is not set (see 6.6) */ + if (!read()) + invalidator().invalidate_all(); + + /* enable IOMMU */ + if (!read()) + _global_command(1); +} + + +void Intel::Io_mmu::_init() +{ + if (read()) { + log("IOMMU has been enabled during boot"); + + /* disable queued invalidation interface */ + if (read()) + _global_command(false); + } + + if (read()) { + /* enable queued invalidation if supported */ + _queued_invalidator.construct(_env, base() + 0x80); + _global_command(true); + } else { + /* use register-based invalidation interface as fallback */ + addr_t context_reg_base = base() + 0x28; + addr_t iotlb_reg_base = base() + 8*_offset(); + _register_invalidator.construct(context_reg_base, iotlb_reg_base, _verbose); + } + + /* enable fault event interrupts if desired */ + if (_fault_irq.constructed()) { + Irq_session::Info info = _fault_irq->info(); + + if (info.type == Irq_session::Info::INVALID) + error("Unable to enable fault event interrupts for ", _name); + else { + write((Fault_event_address::access_t)info.address); + write((Fault_event_data::access_t)info.value); + write(0); + } + } + + /* + * We always enable IRQ remapping if its supported by the IOMMU. Note, there + * might be the possibility that the ACPI DMAR table says otherwise but + * we've never seen such a case yet. + */ + if (read()) + _enable_irq_remapping(); +} + + Intel::Io_mmu::Io_mmu(Env & env, Io_mmu_devices & io_mmu_devices, Device::Name const & name, @@ -436,48 +456,13 @@ Intel::Io_mmu::Io_mmu(Env & env, return; } - if (read()) { - log("IOMMU has been enabled during boot"); - - /* disable queued invalidation interface */ - if (read()) - _global_command(false); - } - - if (read()) { - /* enable queued invalidation if supported */ - _queued_invalidator.construct(_env, base() + 0x80); - _global_command(true); - } else { - /* use register-based invalidation interface as fallback */ - addr_t context_reg_base = base() + 0x28; - addr_t iotlb_reg_base = base() + 8*_offset(); - _register_invalidator.construct(context_reg_base, iotlb_reg_base, _verbose); - } - /* enable fault event interrupts (if not already enabled by kernel) */ if (irq_number && !read()) { _fault_irq.construct(_env, irq_number, 0, Irq_session::TYPE_MSI); _fault_irq->sigh(_fault_handler); _fault_irq->ack_irq(); - - Irq_session::Info info = _fault_irq->info(); - - if (info.type == Irq_session::Info::INVALID) - error("Unable to enable fault event interrupts for ", name); - else { - write((Fault_event_address::access_t)info.address); - write((Fault_event_data::access_t)info.value); - write(0); - } } - /* - * We always enable IRQ remapping if its supported by the IOMMU. Note, there - * might be the possibility that the ACPI DMAR table says otherwise but - * we've never seen such a case yet. - */ - if (read()) - _enable_irq_remapping(); + _init(); } diff --git a/repos/pc/src/driver/platform/pc/intel/io_mmu.h b/repos/pc/src/driver/platform/pc/intel/io_mmu.h index 34056dd1bc..e166ea3cc6 100644 --- a/repos/pc/src/driver/platform/pc/intel/io_mmu.h +++ b/repos/pc/src/driver/platform/pc/intel/io_mmu.h @@ -431,12 +431,6 @@ class Intel::Io_mmu : private Attached_mmio<0x800>, struct Info : Bitfield<12,52> { }; }; - /* saved registers during suspend */ - Fault_event_control::access_t _s3_fec { }; - Fault_event_data ::access_t _s3_fedata { }; - Fault_event_address ::access_t _s3_feaddr { }; - Root_table_address::access_t _s3_rta { }; - uint32_t _max_domains() { return 1 << (4 + read()*2); } @@ -496,6 +490,10 @@ class Intel::Io_mmu : private Attached_mmio<0x800>, void _enable_irq_remapping(); + /* utility methods used on boot and resume */ + void _init(); + void _enable_translation(); + /** * Io_mmu interface */ @@ -568,7 +566,6 @@ class Intel::Io_mmu : private Attached_mmio<0x800>, /** * Io_mmu suspend/resume interface */ - void suspend() override; void resume() override; /**