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 #ifndef CHROMIUMOS_WIDE_PROFILING_ADDRESS_MAPPER_H_
      6 #define CHROMIUMOS_WIDE_PROFILING_ADDRESS_MAPPER_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include <list>
     11 
     12 namespace quipper {
     13 
     14 class AddressMapper {
     15  public:
     16   AddressMapper() {}
     17 
     18   // Copy constructor: copies mappings from |source| to this AddressMapper. This
     19   // is useful for copying mappings from parent to child process upon fork(). It
     20   // is also useful to copy kernel mappings to any process that is created.
     21   AddressMapper(const AddressMapper& source);
     22 
     23   // Maps a new address range to quipper space.
     24   // |remove_existing_mappings| indicates whether to remove old mappings that
     25   // collide with the new range in real address space, indicating it has been
     26   // unmapped.
     27   // Returns true if mapping was successful.
     28   bool Map(const uint64_t real_addr,
     29            const uint64_t length,
     30            bool remove_existing_mappings);
     31 
     32   // Like Map(real_addr, length, remove_existing_mappings).  |id| is an
     33   // identifier value to be stored along with the mapping.  AddressMapper does
     34   // not care whether it is unique compared to all other IDs passed in.  That is
     35   // up to the caller to keep track of.
     36   // |offset_base| represents the offset within the original region at which the
     37   // mapping begins. The original region can be much larger than the mapped
     38   // region.
     39   // e.g. Given a mapped region with base=0x4000 and size=0x2000 mapped with
     40   // offset_base=0x10000, then the address 0x5000 maps to an offset of 0x11000
     41   // (0x5000 - 0x4000 + 0x10000).
     42   bool MapWithID(const uint64_t real_addr,
     43                  const uint64_t length,
     44                  const uint64_t id,
     45                  const uint64_t offset_base,
     46                  bool remove_existing_mappings);
     47 
     48   // Looks up |real_addr| and returns the mapped address.
     49   bool GetMappedAddress(const uint64_t real_addr, uint64_t* mapped_addr) const;
     50 
     51   // Looks up |real_addr| and returns the mapping's ID and offset from the
     52   // start of the mapped space.
     53   bool GetMappedIDAndOffset(const uint64_t real_addr,
     54                             uint64_t* id,
     55                             uint64_t* offset) const;
     56 
     57   // Returns true if there are no mappings.
     58   bool IsEmpty() const {
     59     return mappings_.empty();
     60   }
     61 
     62   // Returns the number of address ranges that are currently mapped.
     63   unsigned int GetNumMappedRanges() const {
     64     return mappings_.size();
     65   }
     66 
     67   // Returns the maximum length of quipper space containing mapped areas.
     68   // There may be gaps in between blocks.
     69   // If the result is 2^64 (all of quipper space), this returns 0.  Call
     70   // IsEmpty() to distinguish this from actual emptiness.
     71   uint64_t GetMaxMappedLength() const;
     72 
     73   // Dumps the state of the address mapper to logs. Useful for debugging.
     74   void DumpToLog() const;
     75 
     76  private:
     77   struct MappedRange {
     78     uint64_t real_addr;
     79     uint64_t mapped_addr;
     80     uint64_t size;
     81 
     82     uint64_t id;
     83     uint64_t offset_base;
     84 
     85     // Length of unmapped space after this range.
     86     uint64_t unmapped_space_after;
     87 
     88     // Determines if this range intersects another range in real space.
     89     inline bool Intersects(const MappedRange& range) const {
     90       return (real_addr <= range.real_addr + range.size - 1) &&
     91              (real_addr + size - 1 >= range.real_addr);
     92     }
     93 
     94     // Determines if this range fully covers another range in real space.
     95     inline bool Covers(const MappedRange& range) const {
     96       return (real_addr <= range.real_addr) &&
     97              (real_addr + size - 1 >= range.real_addr + range.size - 1);
     98     }
     99 
    100     // Determines if this range fully contains another range in real space.
    101     // This is different from Covers() in that the boundaries cannot overlap.
    102     inline bool Contains(const MappedRange& range) const {
    103       return (real_addr < range.real_addr) &&
    104              (real_addr + size - 1 > range.real_addr + range.size - 1);
    105     }
    106 
    107     // Determines if this range contains the given address |addr|.
    108     inline bool ContainsAddress(uint64_t addr) const {
    109       return (addr >= real_addr && addr <= real_addr + size - 1);
    110     }
    111   };
    112 
    113   // TODO(sque): implement with set or map to improve searching.
    114   typedef std::list<MappedRange> MappingList;
    115 
    116   // Removes an existing address mapping.
    117   // Returns true if successful, false if no mapped address range was found.
    118   bool Unmap(const MappedRange& range);
    119 
    120   // Container for all the existing mappings.
    121   MappingList mappings_;
    122 
    123   bool CheckMappings() const;
    124 };
    125 
    126 }  // namespace quipper
    127 
    128 #endif  // CHROMIUMOS_WIDE_PROFILING_ADDRESS_MAPPER_H_
    129