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 #include "iommu_page.h"
8 
9 #include <vm/pmm.h>
10 #include <vm/vm_aspace.h>
11 
12 namespace intel_iommu {
13 
IommuPage(vm_page_t * page,uintptr_t virt)14 IommuPage::IommuPage(vm_page_t* page, uintptr_t virt) : page_(page), virt_(virt) {
15 }
16 
~IommuPage()17 IommuPage::~IommuPage() {
18     if (page_) {
19         VmAspace::kernel_aspace()->FreeRegion(reinterpret_cast<vaddr_t>(virt_));
20         pmm_free_page(page_);
21     }
22 }
23 
AllocatePage(IommuPage * out)24 zx_status_t IommuPage::AllocatePage(IommuPage* out) {
25     vm_page_t* page;
26     zx_status_t status = pmm_alloc_page(0, &page);
27     if (status != ZX_OK) {
28         return status;
29     }
30     page->state = VM_PAGE_STATE_IOMMU;
31 
32     void* vaddr;
33     auto kernel_aspace = VmAspace::kernel_aspace();
34     status = kernel_aspace->AllocPhysical(
35             "iommu_ctx_tbl",
36             PAGE_SIZE,
37             &vaddr,
38             PAGE_SIZE_SHIFT,
39             page->paddr(),
40             0,
41             ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE);
42     if (status != ZX_OK) {
43         pmm_free_page(page);
44         return status;
45     }
46 
47     arch_zero_page(vaddr);
48 
49     *out = IommuPage(page, reinterpret_cast<uintptr_t>(vaddr));
50     return ZX_OK;
51 }
52 
53 } // namespace intel_iommu
54