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 <kernel/mutex.h> 10#include <fbl/intrusive_double_list.h> 11#include <fbl/ref_counted.h> 12#include <fbl/ref_ptr.h> 13#include <vm/vm_object.h> 14#include <zircon/thread_annotations.h> 15 16#include <stdbool.h> 17#include <sys/types.h> 18#include <inttypes.h> 19 20#define IOMMU_FLAG_PERM_READ (1<<0) 21#define IOMMU_FLAG_PERM_WRITE (1<<1) 22#define IOMMU_FLAG_PERM_EXECUTE (1<<2) 23 24// Type used to refer to virtual addresses presented to a device by the IOMMU. 25typedef uint64_t dev_vaddr_t; 26 27class Iommu : public fbl::RefCounted<Iommu>, 28 public fbl::DoublyLinkedListable<fbl::RefPtr<Iommu>> { 29public: 30 // Check if |bus_txn_id| is valid for this IOMMU (i.e. could be used 31 // to configure a device). 32 virtual bool IsValidBusTxnId(uint64_t bus_txn_id) const = 0; 33 34 // Grant the device identified by |bus_txn_id| access to the range of 35 // pages given by [offset, offset + size) in |vmo|. The base of the 36 // mapped range is returned via |vaddr|. The number of bytes mapped is 37 // returned via |mapped_len|. |vaddr| and |mapped_len| must not be NULL. 38 // 39 // |mapped_len| may be more than |size|, in the event that |size| is 40 // not page-aligned. |mapped_len| will always be page-aligned. 41 // 42 // The memory in the given range of |vmo| MUST have been pined before 43 // calling this function, and if this function returns ZX_OK, 44 // MUST NOT be unpined until after Unmap() is called on the returned range. 45 // 46 // |perms| defines the access permissions, using the IOMMU_FLAG_PERM_* 47 // flags. 48 // 49 // If |size| is no more than |minimum_contiguity()|, this will never return 50 // a partial mapping. 51 // 52 // Returns ZX_ERR_INVALID_ARGS if: 53 // |size| is zero. 54 // |offset| is not aligned to PAGE_SIZE 55 // Returns ZX_ERR_OUT_OF_RANGE if [offset, offset + size) is not a valid range in |vmo|. 56 // Returns ZX_ERR_NOT_FOUND if |bus_txn_id| is not valid. 57 // Returns ZX_ERR_NO_RESOURCES if the mapping could not be made due to lack 58 // of an available address range. 59 virtual zx_status_t Map(uint64_t bus_txn_id, const fbl::RefPtr<VmObject>& vmo, 60 uint64_t offset, size_t size, uint32_t perms, 61 dev_vaddr_t* vaddr, size_t* mapped_len) = 0; 62 63 // Same as Map, but with additional guarantee that this will never return a 64 // partial mapping. It will either return a single contiguous mapping or 65 // return a failure. 66 virtual zx_status_t MapContiguous(uint64_t bus_txn_id, const fbl::RefPtr<VmObject>& vmo, 67 uint64_t offset, size_t size, uint32_t perms, 68 dev_vaddr_t* vaddr, size_t* mapped_len) = 0; 69 70 // Revoke access to the range of addresses [vaddr, vaddr + size) for the 71 // device identified by |bus_txn_id|. 72 // 73 // Returns ZX_ERR_INVALID_ARGS if: 74 // |size| is not a multiple of PAGE_SIZE 75 // |vaddr| is not aligned to PAGE_SIZE 76 // Returns ZX_ERR_NOT_FOUND if |bus_txn_id| is not valid. 77 virtual zx_status_t Unmap(uint64_t bus_txn_id, dev_vaddr_t vaddr, size_t size) = 0; 78 79 // Remove all mappings for |bus_txn_id|. 80 // Returns ZX_ERR_NOT_FOUND if |bus_txn_id| is not valid. 81 virtual zx_status_t ClearMappingsForBusTxnId(uint64_t bus_txn_id) = 0; 82 83 // Returns the number of bytes that Map() can guarantee, upon success, to find 84 // a contiguous address range for. This function is only returns meaningful 85 // values if |IsValidBusTxnId(bus_txn_id)|. 86 virtual uint64_t minimum_contiguity(uint64_t bus_txn_id) = 0; 87 88 // Returns the total size of the space the addresses are mapped into. This 89 // function is only returns meaningful values if |IsValidBusTxnId(bus_txn_id)|. 90 virtual uint64_t aspace_size(uint64_t bus_txn_id) = 0; 91 92 virtual ~Iommu() { } 93}; 94