1 // Copyright 2016 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 <vm/vm_address_region.h>
8 
9 #include "vm_priv.h"
10 #include <assert.h>
11 #include <err.h>
12 #include <fbl/auto_call.h>
13 #include <inttypes.h>
14 #include <string.h>
15 #include <trace.h>
16 #include <vm/vm.h>
17 #include <vm/vm_aspace.h>
18 #include <zircon/types.h>
19 
20 #define LOCAL_TRACE MAX(VM_GLOBAL_TRACE, 0)
21 
VmAddressRegionOrMapping(vaddr_t base,size_t size,uint32_t flags,VmAspace * aspace,VmAddressRegion * parent)22 VmAddressRegionOrMapping::VmAddressRegionOrMapping(
23     vaddr_t base, size_t size, uint32_t flags,
24     VmAspace* aspace, VmAddressRegion* parent)
25     : state_(LifeCycleState::NOT_READY), base_(base), size_(size),
26       flags_(flags), aspace_(aspace), parent_(parent) {
27     LTRACEF("%p\n", this);
28 }
29 
Destroy()30 zx_status_t VmAddressRegionOrMapping::Destroy() {
31     canary_.Assert();
32 
33     Guard<fbl::Mutex> guard{aspace_->lock()};
34     if (state_ != LifeCycleState::ALIVE) {
35         return ZX_ERR_BAD_STATE;
36     }
37 
38     return DestroyLocked();
39 }
40 
~VmAddressRegionOrMapping()41 VmAddressRegionOrMapping::~VmAddressRegionOrMapping() {
42     LTRACEF("%p\n", this);
43 
44     if (state_ == LifeCycleState::ALIVE) {
45         Destroy();
46     }
47 
48     DEBUG_ASSERT(!subregion_list_node_.InContainer());
49 }
50 
IsAliveLocked() const51 bool VmAddressRegionOrMapping::IsAliveLocked() const {
52     canary_.Assert();
53     DEBUG_ASSERT(aspace_->lock()->lock().IsHeld());
54     return state_ == LifeCycleState::ALIVE;
55 }
56 
as_vm_address_region()57 fbl::RefPtr<VmAddressRegion> VmAddressRegionOrMapping::as_vm_address_region() {
58     canary_.Assert();
59     if (is_mapping()) {
60         return nullptr;
61     }
62     return fbl::RefPtr<VmAddressRegion>(static_cast<VmAddressRegion*>(this));
63 }
64 
as_vm_mapping()65 fbl::RefPtr<VmMapping> VmAddressRegionOrMapping::as_vm_mapping() {
66     canary_.Assert();
67     if (!is_mapping()) {
68         return nullptr;
69     }
70     return fbl::RefPtr<VmMapping>(static_cast<VmMapping*>(this));
71 }
72 
is_valid_mapping_flags(uint arch_mmu_flags)73 bool VmAddressRegionOrMapping::is_valid_mapping_flags(uint arch_mmu_flags) {
74     if (!(flags_ & VMAR_FLAG_CAN_MAP_READ) && (arch_mmu_flags & ARCH_MMU_FLAG_PERM_READ)) {
75         return false;
76     }
77     if (!(flags_ & VMAR_FLAG_CAN_MAP_WRITE) && (arch_mmu_flags & ARCH_MMU_FLAG_PERM_WRITE)) {
78         return false;
79     }
80     if (!(flags_ & VMAR_FLAG_CAN_MAP_EXECUTE) && (arch_mmu_flags & ARCH_MMU_FLAG_PERM_EXECUTE)) {
81         return false;
82     }
83     return true;
84 }
85 
AllocatedPages() const86 size_t VmAddressRegionOrMapping::AllocatedPages() const {
87     Guard<fbl::Mutex> guard{aspace_->lock()};
88     if (state_ != LifeCycleState::ALIVE) {
89         return 0;
90     }
91     return AllocatedPagesLocked();
92 }
93