1 // Copyright 2017 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 <dev/iommu.h> 10 #include <fbl/canary.h> 11 #include <fbl/mutex.h> 12 #include <kernel/lockdep.h> 13 #include <object/dispatcher.h> 14 #include <object/pinned_memory_token_dispatcher.h> 15 16 #include <sys/types.h> 17 18 class Iommu; 19 20 class BusTransactionInitiatorDispatcher final : 21 public SoloDispatcher<BusTransactionInitiatorDispatcher, ZX_DEFAULT_BTI_RIGHTS> { 22 public: 23 static zx_status_t Create(fbl::RefPtr<Iommu> iommu, uint64_t bti_id, 24 fbl::RefPtr<Dispatcher>* dispatcher, zx_rights_t* rights); 25 26 ~BusTransactionInitiatorDispatcher() final; get_type()27 zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_BTI; } 28 29 // Pins the given VMO range and returns an PinnedMemoryTokenDispatcher 30 // representing the pinned range. 31 // 32 // |mapped_addrs_count| must be either 33 // 1) If |compress_results|, |size|/|minimum_contiguity()|, rounded up, in which 34 // case each returned address represents a run of |minimum_contiguity()| bytes (with 35 // the exception of the last which may be short) 36 // 2) Otherwise, |size|/|PAGE_SIZE|, in which case each returned address represents a 37 // single page. 38 // 39 // Returns ZX_ERR_INVALID_ARGS if |offset| or |size| are not PAGE_SIZE aligned. 40 // Returns ZX_ERR_INVALID_ARGS if |perms| is not suitable to pass to the Iommu::Map() interface. 41 // Returns ZX_ERR_INVALID_ARGS if |mapped_addrs_count| is not exactly the 42 // value described above. 43 zx_status_t Pin(fbl::RefPtr<VmObject> vmo, uint64_t offset, uint64_t size, uint32_t perms, 44 fbl::RefPtr<Dispatcher>* pmt, zx_rights_t* rights); 45 46 // Releases all quarantined PMTs. The memory pins are released and the VMO 47 // references are dropped, so the underlying VMOs may be immediately destroyed, and the 48 // underlying physical memory may be reallocated. 49 void ReleaseQuarantine(); 50 51 void on_zero_handles() final; 52 iommu()53 fbl::RefPtr<Iommu> iommu() const { return iommu_; } bti_id()54 uint64_t bti_id() const { return bti_id_; } 55 56 // Pin will always be able to return addresses that are contiguous for at 57 // least this many bytes. E.g. if this returns 1MB, then a call to Pin() 58 // with a size of 2MB will return at most two physically-contiguous runs. If the size 59 // were 2.5MB, it will return at most three physically-contiguous runs. minimum_contiguity()60 uint64_t minimum_contiguity() const { return iommu_->minimum_contiguity(bti_id_); } 61 62 // The number of bytes in the address space (UINT64_MAX if 2^64). aspace_size()63 uint64_t aspace_size() const { return iommu_->aspace_size(bti_id_); } 64 65 protected: 66 friend PinnedMemoryTokenDispatcher; 67 68 // Used to register a PMT pointer during PMT construction 69 void AddPmoLocked(PinnedMemoryTokenDispatcher* pmt) TA_REQ(get_lock()); 70 // Used to unregister a PMT pointer during PMT destruction 71 void RemovePmo(PinnedMemoryTokenDispatcher* pmt); 72 73 // Remove |pmt| from pinned_memory_ and append it to the quarantine_ list. 74 // This will prevent its underlying VMO from being unpinned until the 75 // quarantine is cleared. 76 void Quarantine(fbl::RefPtr<PinnedMemoryTokenDispatcher> pmt) TA_EXCL(get_lock()); 77 78 private: 79 BusTransactionInitiatorDispatcher(fbl::RefPtr<Iommu> iommu, uint64_t bti_id); 80 void PrintQuarantineWarningLocked() TA_REQ(get_lock()); 81 82 fbl::Canary<fbl::magic("BTID")> canary_; 83 84 const fbl::RefPtr<Iommu> iommu_; 85 const uint64_t bti_id_; 86 87 using PmoList = fbl::DoublyLinkedList<PinnedMemoryTokenDispatcher*, 88 PinnedMemoryTokenDispatcher::PinnedMemoryTokenListTraits>; 89 PmoList pinned_memory_ TA_GUARDED(get_lock()); 90 91 using QuarantineList = fbl::DoublyLinkedList<fbl::RefPtr<PinnedMemoryTokenDispatcher>, 92 PinnedMemoryTokenDispatcher::QuarantineListTraits>; 93 QuarantineList quarantine_ TA_GUARDED(get_lock()); 94 95 bool zero_handles_ TA_GUARDED(get_lock()); 96 }; 97