1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <fbl/macros.h>
8 #include <fbl/ref_ptr.h>
9 #include <fbl/ref_counted.h>
10 #include <lib/fzl/vmar-manager.h>
11 #include <lib/zx/vmo.h>
12 
13 #include <utility>
14 
15 namespace fzl {
16 
17 class VmoMapper {
18 public:
19     VmoMapper() = default;
~VmoMapper()20     ~VmoMapper() { Unmap(); }
21     DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(VmoMapper);
22 
23     // Move support
VmoMapper(VmoMapper && other)24     VmoMapper(VmoMapper&& other) {
25         MoveFromOther(&other);
26     }
27 
28     VmoMapper& operator=(VmoMapper&& other) {
29         Unmap();
30         MoveFromOther(&other);
31         return *this;
32     }
33 
34     // Create a new VMO and map it into our address space using the provided map
35     // flags and optional target VMAR.  If requested, return the created VMO
36     // with the requested rights.
37     //
38     // size         : The minimum size, in bytes, of the VMO to create.
39     // map_flags    : The flags to use when mapping the VMO.
40     // vmar         : A reference to a VmarManager to use when mapping the VMO, or
41     //                nullptr to map the VMO using the root VMAR.
42     // vmo_out      : A pointer which will receive the created VMO handle, or
43     //                nullptr if the handle should be simply closed after it has
44     //                been mapped.
45     // vmo_rights   : The rights which should be applied to the VMO which is
46     //                passed back to the user via vmo_out, or ZX_RIGHT_SAME_RIGHTS
47     //                to leave the default rights.
48     // cache_policy : When non-zero, indicates the cache policy to apply to the
49     //                created VMO.
50     zx_status_t CreateAndMap(uint64_t size,
51                              zx_vm_option_t map_flags,
52                              fbl::RefPtr<VmarManager> vmar_manager = nullptr,
53                              zx::vmo* vmo_out = nullptr,
54                              zx_rights_t vmo_rights = ZX_RIGHT_SAME_RIGHTS,
55                              uint32_t cache_policy = 0);
56 
57     // Map an existing VMO our address space using the provided map
58     // flags and optional target VMAR.
59     //
60     // vmo        : The vmo to map.
61     // offset     : The offset into the vmo, in bytes, to start the map
62     // size       : The amount of the vmo, in bytes, to map, or 0 to map from
63     //              the offset to the end of the VMO.
64     // map_flags  : The flags to use when mapping the VMO.
65     // vmar       : A reference to a VmarManager to use when mapping the VMO, or
66     //              nullptr to map the VMO using the root VMAR.
67     zx_status_t Map(const zx::vmo& vmo,
68                     uint64_t offset,
69                     uint64_t size,
70                     zx_vm_option_t map_flags,
71                     fbl::RefPtr<VmarManager> vmar_manager = nullptr);
72 
73     // Unmap the VMO from whichever VMAR it was mapped into.
74     void Unmap();
75 
start()76     void* start() const { return reinterpret_cast<void*>(start_); }
size()77     uint64_t size() const { return size_; }
manager()78     const fbl::RefPtr<VmarManager>& manager() const { return vmar_manager_; }
79 
80 protected:
81     zx_status_t CheckReadyToMap(const fbl::RefPtr<VmarManager>& vmar_manager);
82     zx_status_t InternalMap(const zx::vmo& vmo,
83                             uint64_t offset,
84                             uint64_t size,
85                             zx_vm_option_t map_flags,
86                             fbl::RefPtr<VmarManager> vmar_manager);
87 
MoveFromOther(VmoMapper * other)88     void MoveFromOther(VmoMapper* other) {
89         vmar_manager_ = std::move(other->vmar_manager_);
90 
91         start_ = other->start_;
92         other->start_ = 0;
93 
94         size_ = other->size_;
95         other->size_ = 0;
96     }
97 
98     fbl::RefPtr<VmarManager> vmar_manager_;
99     uintptr_t start_ = 0;
100     uint64_t size_ = 0;
101 };
102 
103 }  // namespace fzl
104