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
12namespace quipper {
13
14class 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