1 // Copyright 2018 The Fuchsia Authors 2 // 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file or at 5 // https://opensource.org/licenses/MIT 6 7 #pragma once 8 9 #include <fbl/intrusive_double_list.h> 10 #include <fbl/macros.h> 11 #include <ktl/unique_ptr.h> 12 13 #include "hw.h" 14 #include "iommu_page.h" 15 16 namespace intel_iommu { 17 18 class DeviceContext; 19 class IommuImpl; 20 21 class ContextTableState : public fbl::DoublyLinkedListable<ktl::unique_ptr<ContextTableState>> { 22 public: 23 ~ContextTableState(); 24 25 // Create a ContextTableState for the given bus. 26 // If |extended| is true, then this will represent a reg::ExtendedContextTable, 27 // and the table will handle translations for, depending on |upper|, either the 28 // lower (dev<16) or upper half of this bus. 29 // If |extended| is false, this represents a reg::ContextTable. 30 static zx_status_t Create(uint8_t bus, bool extended, bool upper, 31 IommuImpl* parent, volatile ds::RootEntrySubentry* root_entry, 32 ktl::unique_ptr<ContextTableState>* table); 33 34 // Check if this ContextTableState is for the given BDF includes_bdf(ds::Bdf bdf)35 bool includes_bdf(ds::Bdf bdf) const { 36 if (bdf.bus() != bus_) { 37 return false; 38 } 39 if (!extended_) { 40 return true; 41 } 42 return (bdf.dev() >= 16) == upper_; 43 } 44 45 // Create a new DeviceContext representing the given BDF, and give it the specified domain_id. 46 // It is a fatal error to try to create a context for a BDF that already has one. 47 zx_status_t CreateDeviceContext(ds::Bdf bdf, uint32_t domain_id, 48 DeviceContext** context); 49 50 zx_status_t GetDeviceContext(ds::Bdf bdf, DeviceContext** context); 51 52 private: 53 ContextTableState(uint8_t bus, bool extended, bool upper, IommuImpl* parent, 54 volatile ds::RootEntrySubentry* root_entry, IommuPage page); 55 56 DISALLOW_COPY_ASSIGN_AND_MOVE(ContextTableState); 57 table()58 volatile ds::ContextTable* table() const { 59 DEBUG_ASSERT(!extended_); 60 return reinterpret_cast<volatile ds::ContextTable*>(page_.vaddr()); 61 } 62 extended_table()63 volatile ds::ExtendedContextTable* extended_table() const { 64 DEBUG_ASSERT(extended_); 65 return reinterpret_cast<volatile ds::ExtendedContextTable*>(page_.vaddr()); 66 } 67 68 // Pointer to IOMMU that owns this ContextTableState 69 IommuImpl* const parent_; 70 // Pointer to the half of the Root Table Entry that decodes to this 71 // ContextTable. 72 volatile ds::RootEntrySubentry* const root_entry_; 73 74 // Page backing the ContextTable/ExtendedContextTable 75 const IommuPage page_; 76 77 // List of device configurations beneath this ContextTable. 78 fbl::DoublyLinkedList<ktl::unique_ptr<DeviceContext>> devices_; 79 80 const uint8_t bus_; 81 const bool extended_; 82 // Only valid if extended_ is true 83 const bool upper_; 84 }; 85 86 } // namespace intel_iommu 87