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 #include <dev/iommu/dummy.h>
8
9 #include <err.h>
10 #include <fbl/ref_ptr.h>
11 #include <ktl/move.h>
12 #include <new>
13 #include <vm/vm.h>
14
15 #define INVALID_PADDR UINT64_MAX
16
DummyIommu()17 DummyIommu::DummyIommu() {
18 }
19
Create(ktl::unique_ptr<const uint8_t[]> desc,size_t desc_len,fbl::RefPtr<Iommu> * out)20 zx_status_t DummyIommu::Create(ktl::unique_ptr<const uint8_t[]> desc, size_t desc_len,
21 fbl::RefPtr<Iommu>* out) {
22 if (desc_len != sizeof(zx_iommu_desc_dummy_t)) {
23 return ZX_ERR_INVALID_ARGS;
24 }
25
26 fbl::AllocChecker ac;
27 auto instance = fbl::AdoptRef<DummyIommu>(new (&ac) DummyIommu());
28 if (!ac.check()) {
29 return ZX_ERR_NO_MEMORY;
30 }
31 *out = ktl::move(instance);
32 return ZX_OK;
33 }
34
~DummyIommu()35 DummyIommu::~DummyIommu() {
36 }
37
IsValidBusTxnId(uint64_t bus_txn_id) const38 bool DummyIommu::IsValidBusTxnId(uint64_t bus_txn_id) const {
39 return true;
40 }
41
Map(uint64_t bus_txn_id,const fbl::RefPtr<VmObject> & vmo,uint64_t offset,size_t size,uint32_t perms,dev_vaddr_t * vaddr,size_t * mapped_len)42 zx_status_t DummyIommu::Map(uint64_t bus_txn_id, const fbl::RefPtr<VmObject>& vmo,
43 uint64_t offset, size_t size, uint32_t perms,
44 dev_vaddr_t* vaddr, size_t* mapped_len) {
45 DEBUG_ASSERT(vaddr);
46 DEBUG_ASSERT(mapped_len);
47
48 if (!IS_PAGE_ALIGNED(offset) || size == 0) {
49 return ZX_ERR_INVALID_ARGS;
50 }
51 if (perms & ~(IOMMU_FLAG_PERM_READ | IOMMU_FLAG_PERM_WRITE | IOMMU_FLAG_PERM_EXECUTE)) {
52 return ZX_ERR_INVALID_ARGS;
53 }
54 if (perms == 0) {
55 return ZX_ERR_INVALID_ARGS;
56 }
57 if (offset + size < offset || offset + size > vmo->size()) {
58 return ZX_ERR_OUT_OF_RANGE;
59 }
60
61 auto lookup_fn = [](void* ctx, size_t offset, size_t index, paddr_t pa) {
62 paddr_t* paddr = static_cast<paddr_t*>(ctx);
63 *paddr = pa;
64 return ZX_OK;
65 };
66
67 paddr_t paddr = INVALID_PADDR;
68 zx_status_t status = vmo->Lookup(offset, fbl::min<size_t>(PAGE_SIZE, size), lookup_fn, &paddr);
69 if (status != ZX_OK) {
70 return status;
71 }
72 if (paddr == INVALID_PADDR) {
73 return ZX_ERR_BAD_STATE;
74 }
75
76 if (vmo->is_paged()) {
77 *vaddr = paddr;
78 *mapped_len = PAGE_SIZE;
79 } else {
80 *vaddr = paddr;
81 *mapped_len = ROUNDUP(size, PAGE_SIZE);
82 }
83 return ZX_OK;
84 }
85
MapContiguous(uint64_t bus_txn_id,const fbl::RefPtr<VmObject> & vmo,uint64_t offset,size_t size,uint32_t perms,dev_vaddr_t * vaddr,size_t * mapped_len)86 zx_status_t DummyIommu::MapContiguous(uint64_t bus_txn_id, const fbl::RefPtr<VmObject>& vmo,
87 uint64_t offset, size_t size, uint32_t perms,
88 dev_vaddr_t* vaddr, size_t* mapped_len) {
89 DEBUG_ASSERT(vaddr);
90 DEBUG_ASSERT(mapped_len);
91
92 if (!IS_PAGE_ALIGNED(offset) || size == 0) {
93 return ZX_ERR_INVALID_ARGS;
94 }
95 if (perms & ~(IOMMU_FLAG_PERM_READ | IOMMU_FLAG_PERM_WRITE | IOMMU_FLAG_PERM_EXECUTE)) {
96 return ZX_ERR_INVALID_ARGS;
97 }
98 if (perms == 0) {
99 return ZX_ERR_INVALID_ARGS;
100 }
101 uint64_t end;
102 if (add_overflow(offset, size, &end) || end > vmo->size()) {
103 return ZX_ERR_OUT_OF_RANGE;
104 }
105
106 if (!vmo->is_contiguous()) {
107 return ZX_ERR_NO_RESOURCES;
108 }
109
110 auto lookup_fn = [](void* ctx, size_t offset, size_t index, paddr_t pa) {
111 paddr_t* paddr = static_cast<paddr_t*>(ctx);
112 *paddr = pa;
113 return ZX_OK;
114 };
115
116 paddr_t paddr = INVALID_PADDR;
117 zx_status_t status = vmo->Lookup(offset, PAGE_SIZE, lookup_fn, &paddr);
118 if (status != ZX_OK) {
119 return status;
120 }
121 if (paddr == INVALID_PADDR) {
122 return ZX_ERR_BAD_STATE;
123 }
124
125 *vaddr = paddr;
126 *mapped_len = size;
127 return ZX_OK;
128 }
129
Unmap(uint64_t bus_txn_id,dev_vaddr_t vaddr,size_t size)130 zx_status_t DummyIommu::Unmap(uint64_t bus_txn_id, dev_vaddr_t vaddr, size_t size) {
131 if (!IS_PAGE_ALIGNED(vaddr) || !IS_PAGE_ALIGNED(size)) {
132 return ZX_ERR_INVALID_ARGS;
133 }
134 return ZX_OK;
135 }
136
ClearMappingsForBusTxnId(uint64_t bus_txn_id)137 zx_status_t DummyIommu::ClearMappingsForBusTxnId(uint64_t bus_txn_id) {
138 return ZX_OK;
139 }
140
minimum_contiguity(uint64_t bus_txn_id)141 uint64_t DummyIommu::minimum_contiguity(uint64_t bus_txn_id) {
142 return PAGE_SIZE;
143 }
144
aspace_size(uint64_t bus_txn_id)145 uint64_t DummyIommu::aspace_size(uint64_t bus_txn_id) {
146 return UINT64_MAX;
147 }
148