| // Copyright 2018 The Fuchsia Authors |
| // |
| // Use of this source code is governed by a MIT-style |
| // license that can be found in the LICENSE file or at |
| // https://opensource.org/licenses/MIT |
| |
| #ifndef ZIRCON_KERNEL_DEV_IOMMU_INTEL_CONTEXT_TABLE_STATE_H_ |
| #define ZIRCON_KERNEL_DEV_IOMMU_INTEL_CONTEXT_TABLE_STATE_H_ |
| |
| #include <fbl/intrusive_double_list.h> |
| #include <fbl/macros.h> |
| #include <ktl/unique_ptr.h> |
| |
| #include "hw.h" |
| #include "iommu_page.h" |
| |
| namespace intel_iommu { |
| |
| class DeviceContext; |
| class IommuImpl; |
| |
| class ContextTableState : public fbl::DoublyLinkedListable<ktl::unique_ptr<ContextTableState>> { |
| public: |
| ~ContextTableState(); |
| |
| // Create a ContextTableState for the given bus. |
| // If |extended| is true, then this will represent a reg::ExtendedContextTable, |
| // and the table will handle translations for, depending on |upper|, either the |
| // lower (dev<16) or upper half of this bus. |
| // If |extended| is false, this represents a reg::ContextTable. |
| static zx_status_t Create(uint8_t bus, bool extended, bool upper, IommuImpl* parent, |
| volatile ds::RootEntrySubentry* root_entry, |
| ktl::unique_ptr<ContextTableState>* table); |
| |
| // Check if this ContextTableState is for the given BDF |
| bool includes_bdf(ds::Bdf bdf) const { |
| if (bdf.bus() != bus_) { |
| return false; |
| } |
| if (!extended_) { |
| return true; |
| } |
| return (bdf.dev() >= 16) == upper_; |
| } |
| |
| // Create a new DeviceContext representing the given BDF, and give it the specified domain_id. |
| // It is a fatal error to try to create a context for a BDF that already has one. |
| zx_status_t CreateDeviceContext(ds::Bdf bdf, uint32_t domain_id, DeviceContext** context); |
| |
| zx_status_t GetDeviceContext(ds::Bdf bdf, DeviceContext** context); |
| |
| // Removes all mappings from all device contexts. This is only intended to be used just prior to |
| // destruction as it requires holding the parent lock. |
| void UnmapAllFromDeviceContextsLocked(); |
| |
| private: |
| ContextTableState(uint8_t bus, bool extended, bool upper, IommuImpl* parent, |
| volatile ds::RootEntrySubentry* root_entry, IommuPage page); |
| |
| DISALLOW_COPY_ASSIGN_AND_MOVE(ContextTableState); |
| |
| volatile ds::ContextTable* table() const { |
| DEBUG_ASSERT(!extended_); |
| return reinterpret_cast<volatile ds::ContextTable*>(page_.vaddr()); |
| } |
| |
| volatile ds::ExtendedContextTable* extended_table() const { |
| DEBUG_ASSERT(extended_); |
| return reinterpret_cast<volatile ds::ExtendedContextTable*>(page_.vaddr()); |
| } |
| |
| // Pointer to IOMMU that owns this ContextTableState |
| IommuImpl* const parent_; |
| // Pointer to the half of the Root Table Entry that decodes to this |
| // ContextTable. |
| volatile ds::RootEntrySubentry* const root_entry_; |
| |
| // Page backing the ContextTable/ExtendedContextTable |
| const IommuPage page_; |
| |
| // List of device configurations beneath this ContextTable. |
| fbl::DoublyLinkedList<ktl::unique_ptr<DeviceContext>> devices_; |
| |
| const uint8_t bus_; |
| const bool extended_; |
| // Only valid if extended_ is true |
| const bool upper_; |
| }; |
| |
| } // namespace intel_iommu |
| |
| #endif // ZIRCON_KERNEL_DEV_IOMMU_INTEL_CONTEXT_TABLE_STATE_H_ |