1 // Copyright (c) 2013 The Chromium OS 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 #include "address_mapper.h"
6 
7 #include <algorithm>
8 #include <memory>
9 
10 #include "base/logging.h"
11 #include "base/macros.h"
12 
13 #include "compat/test.h"
14 
15 namespace quipper {
16 
17 namespace {
18 
19 struct Range {
20   uint64_t addr;
21   uint64_t size;
22   uint64_t id;
23   uint64_t base_offset;
24 
25   Range() : addr(0), size(0), id(0), base_offset(0) {}
26 
27   Range(uint64_t addr, uint64_t size, uint64_t id, uint64_t base_offset)
28       : addr(addr), size(size), id(id), base_offset(base_offset) {}
29 
30   bool contains(const uint64_t check_addr) const {
31     return (check_addr >= addr && check_addr < addr + size);
32   }
33 };
34 
35 // Some address ranges to map.  It is important that none of these overlap with
36 // each other, nor are any two of them contiguous.
37 const Range kMapRanges[] = {
38     Range(0xff000000, 0x100000, 0xdeadbeef, 0),
39     Range(0x00a00000, 0x10000, 0xcafebabe, 0),
40     Range(0x0c000000, 0x1000000, 0x900df00d, 0),
41     Range(0x00001000, 0x30000, 0x9000091e, 0),
42 };
43 
44 // List of real addresses that are not in the above ranges.
45 const uint64_t kAddressesNotInRanges[] = {
46     0x00000000, 0x00000100, 0x00038000, 0x00088888, 0x00100000, 0x004fffff,
47     0x00a20000, 0x00cc0000, 0x00ffffff, 0x03e00000, 0x0b000000, 0x0d100000,
48     0x0fffffff, 0x1fffffff, 0x7ffffff0, 0xdffffff0, 0xfe000000, 0xffffffff,
49 };
50 
51 // Number of regularly-spaced intervals within a mapped range to test.
52 const int kNumRangeTestIntervals = 8;
53 
54 // A simple test function to convert a real address to a mapped address.
55 // Address ranges in |ranges| are mapped starting at address 0.
56 uint64_t GetMappedAddressFromRanges(const Range* ranges,
57                                     const unsigned int num_ranges,
58                                     const uint64_t addr) {
59   unsigned int i;
60   uint64_t mapped_range_addr;
61   for (i = 0, mapped_range_addr = 0; i < num_ranges;
62        mapped_range_addr += ranges[i].size, ++i) {
63     const Range& range = ranges[i];
64     if (range.contains(addr)) return (addr - range.addr) + mapped_range_addr;
65   }
66   return static_cast<uint64_t>(-1);
67 }
68 
69 }  // namespace
70 
71 // The unit test class for AddressMapper.
72 class AddressMapperTest : public ::testing::Test {
73  public:
74   AddressMapperTest() {}
75   ~AddressMapperTest() {}
76 
77   virtual void SetUp() { mapper_.reset(new AddressMapper); }
78 
79  protected:
80   // Maps a range using the AddressMapper and makes sure that it was successful.
81   // Uses all fields of |range|, including id and base_offset.
82   bool MapRange(const Range& range, bool remove_old_mappings) {
83     VLOG(1) << "Mapping range at " << std::hex << range.addr
84             << " with length of " << range.size << " and id " << range.id;
85     return mapper_->MapWithID(range.addr, range.size, range.id,
86                               range.base_offset, remove_old_mappings);
87   }
88 
89   // Tests a range that has been mapped. |expected_mapped_addr| is the starting
90   // address that it should have been mapped to. This mapper will test the start
91   // and end addresses of the range, as well as a bunch of addresses inside it.
92   // Also checks lookup of ID and offset.
93   void TestMappedRange(const Range& range, uint64_t expected_mapped_addr) {
94     uint64_t mapped_addr = UINT64_MAX;
95     AddressMapper::MappingList::const_iterator addr_iter;
96 
97     VLOG(1) << "Testing range at " << std::hex << range.addr
98             << " with length of " << std::hex << range.size;
99 
100     // Check address at the beginning of the range and at subsequent intervals.
101     for (int i = 0; i < kNumRangeTestIntervals; ++i) {
102       const uint64_t offset = i * (range.size / kNumRangeTestIntervals);
103       uint64_t addr = range.addr + offset;
104       EXPECT_TRUE(mapper_->GetMappedAddressAndListIterator(addr, &mapped_addr,
105                                                            &addr_iter));
106       EXPECT_EQ(expected_mapped_addr + offset, mapped_addr);
107 
108       uint64_t mapped_offset;
109       uint64_t mapped_id;
110       mapper_->GetMappedIDAndOffset(addr, addr_iter, &mapped_id,
111                                     &mapped_offset);
112       EXPECT_EQ(range.base_offset + offset, mapped_offset);
113       EXPECT_EQ(range.id, mapped_id);
114     }
115 
116     // Check address at end of the range.
117     EXPECT_TRUE(mapper_->GetMappedAddressAndListIterator(
118         range.addr + range.size - 1, &mapped_addr, &addr_iter));
119     EXPECT_EQ(expected_mapped_addr + range.size - 1, mapped_addr);
120   }
121 
122   std::unique_ptr<AddressMapper> mapper_;
123 };
124 
125 // Map one range at a time and test looking up addresses.
126 TEST_F(AddressMapperTest, MapSingle) {
127   for (const Range& range : kMapRanges) {
128     mapper_.reset(new AddressMapper);
129     ASSERT_TRUE(MapRange(range, false));
130     EXPECT_EQ(1U, mapper_->GetNumMappedRanges());
131     TestMappedRange(range, 0);
132 
133     // Check addresses before the mapped range, should be invalid.
134     uint64_t mapped_addr;
135     AddressMapper::MappingList::const_iterator iter;
136     EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(range.addr - 1,
137                                                           &mapped_addr, &iter));
138     EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(range.addr - 0x100,
139                                                           &mapped_addr, &iter));
140     EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(
141         range.addr + range.size, &mapped_addr, &iter));
142     EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(
143         range.addr + range.size + 0x100, &mapped_addr, &iter));
144     EXPECT_EQ(range.size, mapper_->GetMaxMappedLength());
145   }
146 }
147 
148 // Map all the ranges at once and test looking up addresses.
149 TEST_F(AddressMapperTest, MapAll) {
150   uint64_t size_mapped = 0;
151   for (const Range& range : kMapRanges) {
152     ASSERT_TRUE(MapRange(range, false));
153     size_mapped += range.size;
154   }
155   EXPECT_EQ(arraysize(kMapRanges), mapper_->GetNumMappedRanges());
156 
157   // Check the max mapped length in quipper space.
158   EXPECT_EQ(size_mapped, mapper_->GetMaxMappedLength());
159 
160   // For each mapped range, test addresses at the start, middle, and end.
161   // Also test the address right before and after each range.
162   uint64_t mapped_addr;
163   AddressMapper::MappingList::const_iterator iter;
164   for (const Range& range : kMapRanges) {
165     TestMappedRange(range, GetMappedAddressFromRanges(
166                                kMapRanges, arraysize(kMapRanges), range.addr));
167 
168     // Check addresses before and after the mapped range, should be invalid.
169     EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(range.addr - 1,
170                                                           &mapped_addr, &iter));
171     EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(range.addr - 0x100,
172                                                           &mapped_addr, &iter));
173     EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(
174         range.addr + range.size, &mapped_addr, &iter));
175     EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(
176         range.addr + range.size + 0x100, &mapped_addr, &iter));
177   }
178 
179   // Test some addresses that are out of these ranges, should not be able to
180   // get mapped addresses.
181   for (uint64_t addr : kAddressesNotInRanges)
182     EXPECT_FALSE(
183         mapper_->GetMappedAddressAndListIterator(addr, &mapped_addr, &iter));
184 }
185 
186 // Map all the ranges at once and test looking up IDs and offsets.
187 TEST_F(AddressMapperTest, MapAllWithIDsAndOffsets) {
188   for (const Range& range : kMapRanges) {
189     LOG(INFO) << "Mapping range at " << std::hex << range.addr
190               << " with length of " << std::hex << range.size;
191     ASSERT_TRUE(mapper_->MapWithID(range.addr, range.size, range.id, 0, false));
192   }
193   EXPECT_EQ(arraysize(kMapRanges), mapper_->GetNumMappedRanges());
194 
195   // For each mapped range, test addresses at the start, middle, and end.
196   // Also test the address right before and after each range.
197   for (const Range& range : kMapRanges) {
198     TestMappedRange(range, GetMappedAddressFromRanges(
199                                kMapRanges, arraysize(kMapRanges), range.addr));
200   }
201 }
202 
203 // Test overlap detection.
204 TEST_F(AddressMapperTest, OverlapSimple) {
205   // Map all the ranges first.
206   for (const Range& range : kMapRanges) ASSERT_TRUE(MapRange(range, false));
207 
208   // Attempt to re-map each range, but offset by size / 2.
209   for (const Range& range : kMapRanges) {
210     Range new_range;
211     new_range.addr = range.addr + range.size / 2;
212     new_range.size = range.size;
213     // The maps should fail because of overlap with an existing mapping.
214     EXPECT_FALSE(MapRange(new_range, false));
215   }
216 
217   // Re-map each range with the same offset.  Only this time, remove any old
218   // mapped range that overlaps with it.
219   for (const Range& range : kMapRanges) {
220     Range new_range;
221     new_range.addr = range.addr + range.size / 2;
222     new_range.size = range.size;
223     EXPECT_TRUE(MapRange(new_range, true));
224     // Make sure the number of ranges is unchanged (one deleted, one added).
225     EXPECT_EQ(arraysize(kMapRanges), mapper_->GetNumMappedRanges());
226 
227     // The range is shifted in real space but should still be the same in
228     // quipper space.
229     TestMappedRange(
230         new_range, GetMappedAddressFromRanges(kMapRanges, arraysize(kMapRanges),
231                                               range.addr));
232   }
233 }
234 
235 // Test mapping of a giant map that overlaps with all existing ranges.
236 TEST_F(AddressMapperTest, OverlapBig) {
237   // A huge region that overlaps with all ranges in |kMapRanges|.
238   const Range kBigRegion(0xa00, 0xff000000, 0x1234, 0);
239 
240   // Map all the ranges first.
241   for (const Range& range : kMapRanges) ASSERT_TRUE(MapRange(range, false));
242 
243   // Make sure overlap is detected before removing old ranges.
244   ASSERT_FALSE(MapRange(kBigRegion, false));
245   ASSERT_TRUE(MapRange(kBigRegion, true));
246   EXPECT_EQ(1U, mapper_->GetNumMappedRanges());
247 
248   TestMappedRange(kBigRegion, 0);
249 
250   // Given the list of previously unmapped addresses, test that the ones within
251   // |kBigRegion| are now mapped; for the ones that are not, test that they are
252   // not mapped.
253   for (uint64_t addr : kAddressesNotInRanges) {
254     uint64_t mapped_addr = UINT64_MAX;
255     AddressMapper::MappingList::const_iterator addr_iter;
256     bool map_success = mapper_->GetMappedAddressAndListIterator(
257         addr, &mapped_addr, &addr_iter);
258     if (kBigRegion.contains(addr)) {
259       EXPECT_TRUE(map_success);
260       EXPECT_EQ(addr - kBigRegion.addr, mapped_addr);
261     } else {
262       EXPECT_FALSE(map_success);
263     }
264   }
265 
266   // Check that addresses in the originally mapped ranges no longer map to the
267   // same addresses if they fall within |kBigRegion|, and don't map at all if
268   // they are not within |kBigRegion|.
269   for (const Range& range : kMapRanges) {
270     for (uint64_t addr = range.addr; addr < range.addr + range.size;
271          addr += range.size / kNumRangeTestIntervals) {
272       uint64_t mapped_addr = UINT64_MAX;
273       AddressMapper::MappingList::const_iterator addr_iter;
274       bool map_success = mapper_->GetMappedAddressAndListIterator(
275           addr, &mapped_addr, &addr_iter);
276       if (kBigRegion.contains(addr)) {
277         EXPECT_TRUE(map_success);
278         EXPECT_EQ(addr - kBigRegion.addr, mapped_addr);
279       } else {
280         EXPECT_FALSE(map_success);
281       }
282     }
283   }
284 
285   EXPECT_EQ(kBigRegion.size, mapper_->GetMaxMappedLength());
286 }
287 
288 // Test a mapping at the end of memory space.
289 TEST_F(AddressMapperTest, EndOfMemory) {
290   // A region that extends to the end of the address space.
291   const Range kEndRegion(0xffffffff00000000, 0x100000000, 0x3456, 0);
292 
293   ASSERT_TRUE(MapRange(kEndRegion, true));
294   EXPECT_EQ(1U, mapper_->GetNumMappedRanges());
295   TestMappedRange(kEndRegion, 0);
296 }
297 
298 // Test mapping of an out-of-bounds mapping.
299 TEST_F(AddressMapperTest, OutOfBounds) {
300   // A region toward the end of address space that overruns the end of the
301   // address space.
302   const Range kOutOfBoundsRegion(0xffffffff00000000, 0x00000000, 0xccddeeff, 0);
303 
304   ASSERT_FALSE(MapRange(kOutOfBoundsRegion, false));
305   ASSERT_FALSE(MapRange(kOutOfBoundsRegion, true));
306   EXPECT_EQ(0, mapper_->GetNumMappedRanges());
307   uint64_t mapped_addr;
308   AddressMapper::MappingList::const_iterator iter;
309   EXPECT_FALSE(mapper_->GetMappedAddressAndListIterator(
310       kOutOfBoundsRegion.addr + 0x100, &mapped_addr, &iter));
311 }
312 
313 // Test mapping of a region that covers the entire memory space.  Then map other
314 // regions over it.
315 TEST_F(AddressMapperTest, FullRange) {
316   // A huge region that covers all of the available space.
317   const Range kFullRegion(0, UINT64_MAX, 0xaabbccdd, 0);
318 
319   ASSERT_TRUE(MapRange(kFullRegion, false));
320   size_t num_expected_ranges = 1;
321   EXPECT_EQ(num_expected_ranges, mapper_->GetNumMappedRanges());
322 
323   TestMappedRange(kFullRegion, 0);
324 
325   // Map some smaller ranges.
326   for (const Range& range : kMapRanges) {
327     // Check for collision first.
328     ASSERT_FALSE(MapRange(range, false));
329     ASSERT_TRUE(MapRange(range, true));
330 
331     // Make sure the number of mapped ranges has increased by two.  The mapping
332     // should have split an existing range.
333     num_expected_ranges += 2;
334     EXPECT_EQ(num_expected_ranges, mapper_->GetNumMappedRanges());
335   }
336 }
337 
338 // Test mapping of one range in the middle of an existing range. The existing
339 // range should be split into two to accommodate it. Also tests the use of base
340 // offsets.
341 TEST_F(AddressMapperTest, SplitRangeWithOffsetBase) {
342   // Define the two ranges, with distinct IDs.
343   const Range kFirstRange(0x10000, 0x4000, 0x11223344, 0x5000);
344   const Range kSecondRange(0x12000, 0x1000, 0x55667788, 0);
345 
346   // As a sanity check, make sure the second range is fully contained within the
347   // first range.
348   EXPECT_LT(kFirstRange.addr, kSecondRange.addr);
349   EXPECT_GT(kFirstRange.addr + kFirstRange.size,
350             kSecondRange.addr + kSecondRange.size);
351 
352   // Map the two ranges.
353   ASSERT_TRUE(MapRange(kFirstRange, true));
354   ASSERT_TRUE(MapRange(kSecondRange, true));
355 
356   // The first range should have been split into two parts to make way for the
357   // second range. There should be a total of three ranges.
358   EXPECT_EQ(3U, mapper_->GetNumMappedRanges());
359 
360   // Now make sure the mappings are correct.
361 
362   // The first range has been split up. Define the expected ranges here.
363   const Range kFirstRangeHead(0x10000, 0x2000, kFirstRange.id, 0x5000);
364   const Range kFirstRangeTail(0x13000, 0x1000, kFirstRange.id, 0x8000);
365 
366   // Test the two remaining parts of the first range.
367   TestMappedRange(kFirstRangeHead, 0);
368   TestMappedRange(kFirstRangeTail, kFirstRangeTail.addr - kFirstRangeHead.addr);
369 
370   // Test the second range normally.
371   TestMappedRange(kSecondRange, kSecondRange.addr - kFirstRange.addr);
372 }
373 
374 // Test mappings that are not aligned to mmap page boundaries.
375 TEST_F(AddressMapperTest, NotPageAligned) {
376   mapper_->set_page_alignment(0x1000);
377 
378   // Some address ranges that do not begin on a page boundary.
379   const Range kUnalignedRanges[] = {
380       Range(0xff000100, 0x1fff00, 0xdeadbeef, 0x100),
381       Range(0x00a00180, 0x10000, 0xcafebabe, 0x180),
382       Range(0x0c000300, 0x1000800, 0x900df00d, 0x4300),
383       Range(0x000017f0, 0x30000, 0x9000091e, 0x7f0),
384   };
385 
386   // Map the ranges.
387   for (const Range& range : kUnalignedRanges)
388     ASSERT_TRUE(MapRange(range, true));
389 
390   EXPECT_EQ(4U, mapper_->GetNumMappedRanges());
391 
392   // Now make sure the mappings are correct.
393 
394   // First region is mapped as usual, except it does not start at the page
395   // boundary.
396   TestMappedRange(kUnalignedRanges[0], 0x00000100);
397 
398   // Second region follows at the end of the first, but notice that its length
399   // is a full number of pages, which means...
400   TestMappedRange(kUnalignedRanges[1], 0x00200180);
401 
402   // ... the third region starts beyond the next page boundary: 0x211000 instead
403   // of 0x210000.
404   TestMappedRange(kUnalignedRanges[2], 0x00211300);
405 
406   // Similarly, the fourth region starts beyond the next page boundary:
407   // 0x1212000 instead of 0x1211000.
408   TestMappedRange(kUnalignedRanges[3], 0x012127f0);
409 }
410 
411 // Have one mapping in the middle of another, with a nonzero page alignment
412 // parameter.
413 TEST_F(AddressMapperTest, SplitRangeWithPageAlignment) {
414   mapper_->set_page_alignment(0x1000);
415 
416   // These should map just fine.
417   const Range kRange0(0x3000, 0x8000, 0xdeadbeef, 0);
418   const Range kRange1(0x5000, 0x2000, 0xfeedbabe, 0);
419 
420   EXPECT_TRUE(MapRange(kRange0, true));
421   EXPECT_TRUE(MapRange(kRange1, true));
422 
423   EXPECT_EQ(3U, mapper_->GetNumMappedRanges());
424 
425   // Determine the expected split mappings.
426   const Range kRange0Head(0x3000, 0x2000, 0xdeadbeef, 0);
427   const Range kRange0Tail(0x7000, 0x4000, 0xdeadbeef, 0x4000);
428 
429   // Everything should be mapped and split as usual.
430   TestMappedRange(kRange0Head, 0);
431   TestMappedRange(kRange0Tail, 0x4000);
432   TestMappedRange(kRange1, 0x2000);
433 }
434 
435 // Have one mapping in the middle of another, with a nonzero page alignment
436 // parameter. The overlapping region will not be aligned to page boundaries.
437 TEST_F(AddressMapperTest, MisalignedSplitRangeWithPageAlignment) {
438   mapper_->set_page_alignment(0x1000);
439 
440   const Range kRange0(0x3000, 0x8000, 0xdeadbeef, 0);
441   const Range kMisalignedRange(0x4800, 0x2000, 0xfeedbabe, 0);
442 
443   EXPECT_TRUE(MapRange(kRange0, true));
444   // The misaligned mapping should not find enough space to split the existing
445   // range. It is not allowed to move the existing mapping.
446   EXPECT_FALSE(MapRange(kMisalignedRange, true));
447 }
448 
449 }  // namespace quipper
450