Home | History | Annotate | Download | only in quipper
      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