| // Copyright 2016 The Fuchsia Authors | 
 | // | 
 | // Use of this source code is governed by a MIT-style | 
 | // license that can be found in the LICENSE file or at | 
 | // https://opensource.org/licenses/MIT | 
 | #include <assert.h> | 
 | #include <err.h> | 
 | #include <inttypes.h> | 
 | #include <string.h> | 
 | #include <trace.h> | 
 | #include <zircon/types.h> | 
 |  | 
 | #include <fbl/auto_call.h> | 
 | #include <vm/vm.h> | 
 | #include <vm/vm_aspace.h> | 
 |  | 
 | #include "vm/vm_address_region.h" | 
 | #include "vm_priv.h" | 
 |  | 
 | #define LOCAL_TRACE VM_GLOBAL_TRACE(0) | 
 |  | 
 | VmAddressRegionOrMapping::VmAddressRegionOrMapping(vaddr_t base, size_t size, uint32_t flags, | 
 |                                                    VmAspace* aspace, VmAddressRegion* parent) | 
 |     : state_(LifeCycleState::NOT_READY), | 
 |       base_(base), | 
 |       size_(size), | 
 |       flags_(flags), | 
 |       aspace_(aspace), | 
 |       parent_(parent) { | 
 |   LTRACEF("%p\n", this); | 
 | } | 
 |  | 
 | zx_status_t VmAddressRegionOrMapping::Destroy() { | 
 |   canary_.Assert(); | 
 |  | 
 |   Guard<Mutex> guard{aspace_->lock()}; | 
 |   if (state_ != LifeCycleState::ALIVE) { | 
 |     return ZX_ERR_BAD_STATE; | 
 |   } | 
 |  | 
 |   return DestroyLocked(); | 
 | } | 
 |  | 
 | VmAddressRegionOrMapping::~VmAddressRegionOrMapping() { | 
 |   LTRACEF("%p\n", this); | 
 |  | 
 |   if (state_ == LifeCycleState::ALIVE) { | 
 |     Destroy(); | 
 |   } | 
 |  | 
 |   DEBUG_ASSERT(!this->in_subregion_tree()); | 
 | } | 
 |  | 
 | bool VmAddressRegionOrMapping::IsAliveLocked() const { | 
 |   canary_.Assert(); | 
 |   DEBUG_ASSERT(aspace_->lock()->lock().IsHeld()); | 
 |   return state_ == LifeCycleState::ALIVE; | 
 | } | 
 |  | 
 | fbl::RefPtr<VmAddressRegion> VmAddressRegionOrMapping::as_vm_address_region() { | 
 |   canary_.Assert(); | 
 |   if (is_mapping()) { | 
 |     return nullptr; | 
 |   } | 
 |   return fbl::RefPtr<VmAddressRegion>(static_cast<VmAddressRegion*>(this)); | 
 | } | 
 |  | 
 | fbl::RefPtr<VmMapping> VmAddressRegionOrMapping::as_vm_mapping() { | 
 |   canary_.Assert(); | 
 |   if (!is_mapping()) { | 
 |     return nullptr; | 
 |   } | 
 |   return fbl::RefPtr<VmMapping>(static_cast<VmMapping*>(this)); | 
 | } | 
 |  | 
 | bool VmAddressRegionOrMapping::is_valid_mapping_flags(uint arch_mmu_flags) { | 
 |   if (!(flags_ & VMAR_FLAG_CAN_MAP_READ) && (arch_mmu_flags & ARCH_MMU_FLAG_PERM_READ)) { | 
 |     return false; | 
 |   } | 
 |   if (!(flags_ & VMAR_FLAG_CAN_MAP_WRITE) && (arch_mmu_flags & ARCH_MMU_FLAG_PERM_WRITE)) { | 
 |     return false; | 
 |   } | 
 |   if (!(flags_ & VMAR_FLAG_CAN_MAP_EXECUTE) && (arch_mmu_flags & ARCH_MMU_FLAG_PERM_EXECUTE)) { | 
 |     return false; | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | size_t VmAddressRegionOrMapping::AllocatedPages() const { | 
 |   Guard<Mutex> guard{aspace_->lock()}; | 
 |   if (state_ != LifeCycleState::ALIVE) { | 
 |     return 0; | 
 |   } | 
 |   return AllocatedPagesLocked(); | 
 | } |