[iommu] Add generic ARM64 IOMMU implementation

Doesn't do anything yet.

Change-Id: I325bac49b6a22e4984a0993fd75ddd302f105e9f
diff --git a/src/devices/board/drivers/acpi-arm64/acpi-arm64.cc b/src/devices/board/drivers/acpi-arm64/acpi-arm64.cc
index e6a09ef..24edc33 100644
--- a/src/devices/board/drivers/acpi-arm64/acpi-arm64.cc
+++ b/src/devices/board/drivers/acpi-arm64/acpi-arm64.cc
@@ -11,6 +11,7 @@
 #include "src/devices/board/drivers/acpi-arm64/acpi-arm64-bind.h"
 #include "src/devices/board/lib/acpi/acpi-impl.h"
 #include "src/devices/board/lib/acpi/pci.h"
+#include "zircon/status.h"
 
 zx_handle_t root_resource_handle;
 
@@ -32,7 +33,14 @@
 }
 
 void AcpiArm64::DdkInit(ddk::InitTxn txn) {
-  manager_.emplace(&acpi_, zxdev_);
+  // TODO(simonshields): add the spiel here.
+  zx_status_t status = iommu_manager_.Init(zx::unowned_resource(get_root_resource()));
+  if (status != ZX_OK) {
+    zxlogf(ERROR, "failed to init iommu manager: %s", zx_status_get_string(status));
+    txn.Reply(status);
+    return;
+  }
+  manager_.emplace(&acpi_, &iommu_manager_, zxdev_);
 
   // TODO(simonshields): add the spiel here.
   root_resource_handle = get_root_resource();
diff --git a/src/devices/board/drivers/acpi-arm64/acpi-arm64.h b/src/devices/board/drivers/acpi-arm64/acpi-arm64.h
index cd568ea..35095c5 100644
--- a/src/devices/board/drivers/acpi-arm64/acpi-arm64.h
+++ b/src/devices/board/drivers/acpi-arm64/acpi-arm64.h
@@ -10,6 +10,7 @@
 
 #include "src/devices/board/lib/acpi/acpi-impl.h"
 #include "src/devices/board/lib/acpi/manager.h"
+#include "src/devices/lib/iommu/iommu-arm.h"
 
 namespace acpi_arm64 {
 
@@ -30,6 +31,7 @@
  private:
   std::optional<acpi::Manager> manager_;
   acpi::AcpiImpl acpi_;
+  iommu::ArmIommuManager iommu_manager_;
   ddk::PBusProtocolClient pbus_;
 
   std::thread init_thread_;
diff --git a/src/devices/lib/iommu/BUILD.gn b/src/devices/lib/iommu/BUILD.gn
index 97e751e..38eaf5d 100644
--- a/src/devices/lib/iommu/BUILD.gn
+++ b/src/devices/lib/iommu/BUILD.gn
@@ -7,6 +7,8 @@
 
 source_set("iommu") {
   sources = [
+    "iommu-arm.cc",
+    "iommu-arm.h",
     "iommu-x86.cc",
     "iommu-x86.h",
   ]
diff --git a/src/devices/lib/iommu/iommu-arm.cc b/src/devices/lib/iommu/iommu-arm.cc
new file mode 100644
index 0000000..9a12fcf
--- /dev/null
+++ b/src/devices/lib/iommu/iommu-arm.cc
@@ -0,0 +1,22 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/devices/lib/iommu/iommu-arm.h"
+
+#include <zircon/syscalls/iommu.h>
+
+namespace iommu {
+
+zx_status_t ArmIommuManager::Init(zx::unowned_resource root_resource) {
+  zx_iommu_desc_dummy_t dummy;
+  zx_status_t status =
+      zx::iommu::create(*root_resource, ZX_IOMMU_TYPE_DUMMY, &dummy, sizeof(dummy), &dummy_iommu_);
+  if (status != ZX_OK) {
+    return status;
+  }
+
+  return ZX_OK;
+}
+
+}  // namespace iommu
diff --git a/src/devices/lib/iommu/iommu-arm.h b/src/devices/lib/iommu/iommu-arm.h
new file mode 100644
index 0000000..a8043ba
--- /dev/null
+++ b/src/devices/lib/iommu/iommu-arm.h
@@ -0,0 +1,28 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/devices/lib/iommu/iommu.h"
+
+#ifndef SRC_DEVICES_LIB_IOMMU_IOMMU_ARM_H_
+#define SRC_DEVICES_LIB_IOMMU_IOMMU_ARM_H_
+
+namespace iommu {
+
+// IOMMU manager implementation for ARM.
+// This class does not yet do anything, but one day it should read from the IORT to determine IOMMU
+// information.
+class ArmIommuManager : public iommu::IommuManagerBase {
+ public:
+  zx_status_t Init(zx::unowned_resource root_resource);
+
+  zx::unowned_iommu IommuForBdf(uint32_t bdf) override { return dummy_iommu_.borrow(); }
+  zx::unowned_iommu IommuForAcpiDevice(const char* path) override { return dummy_iommu_.borrow(); }
+
+ private:
+  zx::iommu dummy_iommu_;
+};
+
+}  // namespace iommu
+
+#endif