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