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));