diff --git a/lib/mammoth/include/mammoth/memory_region.h b/lib/mammoth/include/mammoth/memory_region.h
index 1dbe6f8..a74b36f 100644
--- a/lib/mammoth/include/mammoth/memory_region.h
+++ b/lib/mammoth/include/mammoth/memory_region.h
@@ -32,3 +32,40 @@ class MappedMemoryRegion {
   uint64_t vaddr_ = 0;
   uint64_t size_ = 0;
 };
+
+/*
+ * Memory Region class that unmaps its memory and releases its
+ * capability when it goes out of scope.
+ */
+class OwnedMemoryRegion {
+ public:
+  OwnedMemoryRegion() = default;
+
+  OwnedMemoryRegion(const OwnedMemoryRegion&) = delete;
+  OwnedMemoryRegion& operator=(const OwnedMemoryRegion&) = delete;
+
+  OwnedMemoryRegion(OwnedMemoryRegion&&);
+  OwnedMemoryRegion& operator=(OwnedMemoryRegion&&);
+
+  ~OwnedMemoryRegion();
+
+  static OwnedMemoryRegion FromCapability(z_cap_t vmmo_cap);
+
+  uint64_t paddr() { return paddr_; }
+  uint64_t vaddr() { return vaddr_; }
+  uint64_t size() { return size_; }
+
+  uint64_t cap() { return vmmo_cap_; }
+
+  bool empty() { return vmmo_cap_ != 0; }
+  explicit operator bool() { return vmmo_cap_ != 0; }
+
+ private:
+  OwnedMemoryRegion(uint64_t vmmo_cap, uint64_t paddr, uint64_t vaddr,
+                    uint64_t size)
+      : vmmo_cap_(vmmo_cap), paddr_(paddr), vaddr_(vaddr), size_(size) {}
+  uint64_t vmmo_cap_ = 0;
+  uint64_t paddr_ = 0;
+  uint64_t vaddr_ = 0;
+  uint64_t size_ = 0;
+};
diff --git a/lib/mammoth/src/memory_region.cpp b/lib/mammoth/src/memory_region.cpp
index 5490a4c..9b7ea57 100644
--- a/lib/mammoth/src/memory_region.cpp
+++ b/lib/mammoth/src/memory_region.cpp
@@ -43,3 +43,41 @@ MappedMemoryRegion MappedMemoryRegion::FromCapability(z_cap_t vmmo_cap) {
   // FIXME: get the size here.
   return MappedMemoryRegion(vmmo_cap, 0, vaddr, 0);
 }
+
+OwnedMemoryRegion::OwnedMemoryRegion(OwnedMemoryRegion&& other)
+    : OwnedMemoryRegion(other.vmmo_cap_, other.paddr_, other.vaddr_,
+                        other.size_) {
+  other.vmmo_cap_ = 0;
+  other.paddr_ = 0;
+  other.vaddr_ = 0;
+  other.size_ = 0;
+}
+
+OwnedMemoryRegion& OwnedMemoryRegion::operator=(OwnedMemoryRegion&& other) {
+  if (vmmo_cap_) {
+    check(ZCapRelease(vmmo_cap_));
+  }
+  vmmo_cap_ = other.vmmo_cap_;
+  paddr_ = other.paddr_;
+  vaddr_ = other.vaddr_;
+  size_ = other.size_;
+  other.vmmo_cap_ = 0;
+  other.paddr_ = 0;
+  other.vaddr_ = 0;
+  other.size_ = 0;
+  return *this;
+}
+
+OwnedMemoryRegion::~OwnedMemoryRegion() {
+  if (vmmo_cap_ != 0) {
+    check(ZCapRelease(vmmo_cap_));
+  }
+}
+
+OwnedMemoryRegion OwnedMemoryRegion::FromCapability(z_cap_t vmmo_cap) {
+  uint64_t vaddr;
+  check(ZAddressSpaceMap(gSelfVmasCap, 0, vmmo_cap, &vaddr));
+
+  // FIXME: get the size here.
+  return OwnedMemoryRegion(vmmo_cap, 0, vaddr, 0);
+}
diff --git a/sys/denali/ahci/ahci_driver.cpp b/sys/denali/ahci/ahci_driver.cpp
index 998f59b..addd338 100644
--- a/sys/denali/ahci/ahci_driver.cpp
+++ b/sys/denali/ahci/ahci_driver.cpp
@@ -21,8 +21,8 @@ void interrupt_thread(void* void_driver) {
 }  // namespace
 
 glcr::ErrorOr<glcr::UniquePtr<AhciDriver>> AhciDriver::Init(
-    MappedMemoryRegion pci_region) {
-  glcr::UniquePtr<AhciDriver> driver(new AhciDriver(pci_region));
+    OwnedMemoryRegion&& pci_region) {
+  glcr::UniquePtr<AhciDriver> driver(new AhciDriver(glcr::Move(pci_region)));
   // RET_ERR(driver->LoadCapabilities());
   RET_ERR(driver->LoadHbaRegisters());
   RET_ERR(driver->LoadDevices());
diff --git a/sys/denali/ahci/ahci_driver.h b/sys/denali/ahci/ahci_driver.h
index 410ee5d..48b05d0 100644
--- a/sys/denali/ahci/ahci_driver.h
+++ b/sys/denali/ahci/ahci_driver.h
@@ -11,7 +11,7 @@
 class AhciDriver {
  public:
   static glcr::ErrorOr<glcr::UniquePtr<AhciDriver>> Init(
-      MappedMemoryRegion ahci_phys);
+      OwnedMemoryRegion&& ahci_phys);
   glcr::ErrorCode RegisterIrq();
 
   void InterruptLoop();
@@ -22,7 +22,7 @@ class AhciDriver {
   void DumpPorts();
 
  private:
-  MappedMemoryRegion pci_region_;
+  OwnedMemoryRegion pci_region_;
   PciDeviceHeader* pci_device_header_ = nullptr;
   MappedMemoryRegion ahci_region_;
   AhciHba* ahci_hba_ = nullptr;
@@ -40,8 +40,8 @@ class AhciDriver {
   glcr::ErrorCode LoadHbaRegisters();
   glcr::ErrorCode LoadDevices();
 
-  AhciDriver(MappedMemoryRegion pci_region)
-      : pci_region_(pci_region),
+  AhciDriver(OwnedMemoryRegion&& pci_region)
+      : pci_region_(glcr::Move(pci_region)),
         pci_device_header_(
             reinterpret_cast<PciDeviceHeader*>(pci_region_.vaddr())) {}
 };
diff --git a/sys/denali/denali.cpp b/sys/denali/denali.cpp
index 51f2189..a099803 100644
--- a/sys/denali/denali.cpp
+++ b/sys/denali/denali.cpp
@@ -18,9 +18,9 @@ uint64_t main(uint64_t init_port_cap) {
   Empty empty;
   AhciInfo ahci;
   RET_ERR(stub.GetAhciInfo(empty, ahci));
-  MappedMemoryRegion ahci_region =
-      MappedMemoryRegion::FromCapability(ahci.ahci_region());
-  ASSIGN_OR_RETURN(auto driver, AhciDriver::Init(ahci_region));
+  OwnedMemoryRegion ahci_region =
+      OwnedMemoryRegion::FromCapability(ahci.ahci_region());
+  ASSIGN_OR_RETURN(auto driver, AhciDriver::Init(glcr::Move(ahci_region)));
 
   ASSIGN_OR_RETURN(glcr::UniquePtr<DenaliServer> server,
                    DenaliServer::Create(*driver));