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
15 #include "host-common/address_space_shared_slots_host_memory_allocator.h"
16 #include <gtest/gtest.h>
17
18 namespace android {
19 namespace emulation {
20 namespace {
21 typedef AddressSpaceSharedSlotsHostMemoryAllocatorContext ASSSHMAC;
22 typedef ASSSHMAC::MemBlock MemBlock;
23 typedef MemBlock::FreeSubblocks_t FreeSubblocks_t;
24
add_memory_mapping(uint64_t gpa,void * ptr,uint64_t size)25 int add_memory_mapping(uint64_t gpa, void *ptr, uint64_t size) {
26 return 1;
27 }
28
remove_memory_mapping(uint64_t gpa,void * ptr,uint64_t size)29 int remove_memory_mapping(uint64_t gpa, void *ptr, uint64_t size) { return 1; }
30
create_address_space_device_control_ops()31 struct address_space_device_control_ops create_address_space_device_control_ops() {
32 struct address_space_device_control_ops ops = {};
33
34 ops.add_memory_mapping = &add_memory_mapping;
35 ops.remove_memory_mapping = &remove_memory_mapping;
36
37 return ops;
38 }
39
getPhysAddrStartLocked(void)40 uint64_t getPhysAddrStartLocked(void) {
41 return 2020;
42 }
43
allocSharedHostRegionLocked(uint64_t page_aligned_size,uint64_t * offset)44 int allocSharedHostRegionLocked(uint64_t page_aligned_size, uint64_t* offset) {
45 *offset = page_aligned_size * 10;
46 return 0;
47 }
48
freeSharedHostRegionLocked(uint64_t offset)49 int freeSharedHostRegionLocked(uint64_t offset) {
50 return 0;
51 }
52
create_AddressSpaceHwFuncs()53 AddressSpaceHwFuncs create_AddressSpaceHwFuncs() {
54 AddressSpaceHwFuncs hw = {};
55
56 hw.allocSharedHostRegionLocked = &allocSharedHostRegionLocked;
57 hw.freeSharedHostRegionLocked = &freeSharedHostRegionLocked;
58 hw.getPhysAddrStartLocked = &getPhysAddrStartLocked;
59
60 return hw;
61 }
62 }
63
TEST(MemBlock_findFreeSubblock,Simple)64 TEST(MemBlock_findFreeSubblock, Simple) {
65 FreeSubblocks_t fsb;
66 EXPECT_TRUE(MemBlock::findFreeSubblock(&fsb, 11) == fsb.end());
67
68 fsb[100] = 10;
69 EXPECT_TRUE(MemBlock::findFreeSubblock(&fsb, 11) == fsb.end());
70
71 FreeSubblocks_t::const_iterator i;
72
73 i = MemBlock::findFreeSubblock(&fsb, 7);
74 ASSERT_TRUE(i != fsb.end());
75 EXPECT_EQ(i->first, 100);
76 EXPECT_EQ(i->second, 10);
77
78 fsb[200] = 6;
79 i = MemBlock::findFreeSubblock(&fsb, 7);
80 ASSERT_TRUE(i != fsb.end());
81 EXPECT_EQ(i->first, 100);
82 EXPECT_EQ(i->second, 10);
83
84 fsb[300] = 8;
85 i = MemBlock::findFreeSubblock(&fsb, 7);
86 ASSERT_TRUE(i != fsb.end());
87 EXPECT_EQ(i->first, 300);
88 EXPECT_EQ(i->second, 8);
89 }
90
TEST(MemBlock_tryMergeSubblocks,NoMerge)91 TEST(MemBlock_tryMergeSubblocks, NoMerge) {
92 FreeSubblocks_t fsb;
93
94 auto i = fsb.insert({10, 5}).first;
95 auto j = fsb.insert({20, 5}).first;
96
97 auto r = MemBlock::tryMergeSubblocks(&fsb, i, i, j);
98
99 EXPECT_EQ(fsb.size(), 2);
100 EXPECT_EQ(fsb[10], 5);
101 EXPECT_EQ(fsb[20], 5);
102 EXPECT_TRUE(r == i);
103 }
104
TEST(MemBlock_tryMergeSubblocks,Merge)105 TEST(MemBlock_tryMergeSubblocks, Merge) {
106 FreeSubblocks_t fsb;
107
108 auto i = fsb.insert({10, 10}).first;
109 auto j = fsb.insert({20, 5}).first;
110
111 auto r = MemBlock::tryMergeSubblocks(&fsb, i, i, j);
112
113 EXPECT_EQ(fsb.size(), 1);
114 EXPECT_EQ(fsb[10], 15);
115 ASSERT_TRUE(r != fsb.end());
116 EXPECT_EQ(r->first, 10);
117 EXPECT_EQ(r->second, 15);
118 }
119
TEST(MemBlock,allocate)120 TEST(MemBlock, allocate) {
121 const struct address_space_device_control_ops ops =
122 create_address_space_device_control_ops();
123
124 const AddressSpaceHwFuncs hw = create_AddressSpaceHwFuncs();
125
126 MemBlock block(&ops, &hw, 100);
127 EXPECT_TRUE(block.isAllFree());
128 EXPECT_EQ(block.physBase, 2020 + 100 * 10);
129
130 EXPECT_EQ(block.allocate(110), 0); // too large
131
132 uint32_t off;
133
134 off = block.allocate(50);
135 EXPECT_GE(off, 2020 + 100 * 10);
136
137 off = block.allocate(47);
138 EXPECT_GE(off, 2020 + 100 * 10);
139
140 off = block.allocate(2);
141 EXPECT_GE(off, 2020 + 100 * 10);
142
143 off = block.allocate(2);
144 EXPECT_EQ(off, 0);
145
146 off = block.allocate(1);
147 EXPECT_GE(off, 2020 + 100 * 10);
148
149 off = block.allocate(1);
150 EXPECT_EQ(off, 0);
151 }
152
TEST(MemBlock,unallocate)153 TEST(MemBlock, unallocate) {
154 const struct address_space_device_control_ops ops =
155 create_address_space_device_control_ops();
156
157 const AddressSpaceHwFuncs hw = create_AddressSpaceHwFuncs();
158
159 MemBlock block(&ops, &hw, 100);
160 EXPECT_TRUE(block.isAllFree());
161 EXPECT_EQ(block.physBase, 2020 + 100 * 10);
162
163 uint32_t off60 = block.allocate(60);
164 EXPECT_GE(off60, 2020 + 100 * 10);
165
166 uint32_t off20 = block.allocate(20);
167 EXPECT_GE(off20, 2020 + 100 * 10);
168
169 uint32_t off30 = block.allocate(30);
170 EXPECT_EQ(off30, 0);
171
172 block.unallocate(off20, 20);
173
174 off30 = block.allocate(30);
175 EXPECT_GE(off30, 2020 + 100 * 10);
176
177 block.unallocate(off60, 60);
178 block.unallocate(off30, 30);
179
180 EXPECT_TRUE(block.isAllFree());
181 }
182
183 } // namespace emulation
184 } // namespace android
185