1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #pragma once
15 
16 #include "host-common/AddressSpaceService.h"
17 #include "host-common/address_space_device.h"
18 #include <map>
19 #include <unordered_map>
20 
21 namespace android {
22 namespace emulation {
23 
24 class AddressSpaceSharedSlotsHostMemoryAllocatorContext : public AddressSpaceDeviceContext {
25 public:
26     enum class HostMemoryAllocatorCommand {
27         Allocate = 1,
28         Unallocate = 2,
29         CheckIfSharedSlotsSupported = 3
30     };
31 
32     struct MemBlock {
33         typedef std::map<uint32_t, uint32_t> FreeSubblocks_t;  // offset -> size
34 
35         MemBlock() = default;
36         MemBlock(const address_space_device_control_ops* o,
37                  const AddressSpaceHwFuncs* h,
38                  uint32_t sz);
39         MemBlock(MemBlock&& rhs);
40         MemBlock& operator=(MemBlock rhs);
41         ~MemBlock();
42 
43         friend void swap(MemBlock& lhs, MemBlock& rhs);
44 
45         bool isAllFree() const;
46         uint64_t allocate(size_t requestedSize);
47         void unallocate(uint64_t phys, uint32_t subblockSize);
48 
49         static
50         FreeSubblocks_t::iterator findFreeSubblock(FreeSubblocks_t* fsb, size_t sz);
51 
52         static
53         FreeSubblocks_t::iterator tryMergeSubblocks(FreeSubblocks_t* fsb,
54                                                     FreeSubblocks_t::iterator ret,
55                                                     FreeSubblocks_t::iterator lhs,
56                                                     FreeSubblocks_t::iterator rhs);
57 
58         void save(base::Stream* stream) const;
59         static bool load(base::Stream* stream,
60                          const address_space_device_control_ops* ops,
61                          const AddressSpaceHwFuncs* hw,
62                          MemBlock* block);
63 
64         const address_space_device_control_ops* ops = nullptr;
65         const AddressSpaceHwFuncs* hw = nullptr;
66         uint64_t physBase = 0;
67         uint64_t physBaseLoaded = 0;
68         void* bits = nullptr;
69         uint32_t bitsSize = 0;
70         FreeSubblocks_t freeSubblocks;
71 
72         MemBlock(const MemBlock&) = delete;
73         MemBlock& operator=(const MemBlock&) = delete;
74     };
75 
76     AddressSpaceSharedSlotsHostMemoryAllocatorContext(const address_space_device_control_ops *ops,
77                                                       const AddressSpaceHwFuncs* hw);
78     ~AddressSpaceSharedSlotsHostMemoryAllocatorContext();
79 
80     void perform(AddressSpaceDevicePingInfo *info) override;
81 
82     AddressSpaceDeviceType getDeviceType() const override;
83     void save(base::Stream* stream) const override;
84     bool load(base::Stream* stream) override;
85 
86     static void globalStateSave(base::Stream* stream);
87     static bool globalStateLoad(base::Stream* stream,
88                                 const address_space_device_control_ops *ops,
89                                 const AddressSpaceHwFuncs* hw);
90     static void globalStateClear();
91 
92 private:
93     uint64_t allocate(AddressSpaceDevicePingInfo *info);
94     uint64_t unallocate(uint64_t phys);
95     void gcEmptyBlocks(int allowedEmpty);
96     void clear();
97 
98     uint64_t populatePhysAddr(AddressSpaceDevicePingInfo *info,
99                               uint64_t phys,
100                               uint32_t sz,
101                               MemBlock*);
102     uint64_t unallocateLocked(uint64_t phys, int allowedEmpty);
103 
104     // physAddr->{size, owner}
105     std::unordered_map<uint64_t, std::pair<uint32_t, MemBlock*>> m_allocations;
106     const address_space_device_control_ops *m_ops;  // do not save/load
107     const AddressSpaceHwFuncs* m_hw;
108 };
109 
110 }  // namespace emulation
111 }  // namespace android
112