1 #include "memoryspace.hpp"
3 #include "serialization.hpp"
9 template<typename T
, bool linear
> inline T
internal_read(memory_space
& m
, uint64_t addr
)
11 const int system_endian
= memory_space::get_system_endian();
12 std::pair
<memory_region
*, uint64_t> g
;
14 g
= m
.lookup_linear(addr
);
17 if(!g
.first
|| g
.second
+ sizeof(T
) > g
.first
->size
)
19 if(g
.first
->direct_map
)
20 return serialization::read_endian
<T
>(g
.first
->direct_map
+ g
.second
, g
.first
->endian
);
23 g
.first
->read(g
.second
, &buf
, sizeof(T
));
24 return serialization::read_endian
<T
>(&buf
, g
.first
->endian
);
28 template<typename T
, bool linear
> inline bool internal_write(memory_space
& m
, uint64_t addr
, T value
)
30 const int system_endian
= memory_space::get_system_endian();
31 std::pair
<memory_region
*, uint64_t> g
;
33 g
= m
.lookup_linear(addr
);
36 if(!g
.first
|| g
.first
->readonly
|| g
.second
+ sizeof(T
) > g
.first
->size
)
38 if(g
.first
->direct_map
)
39 serialization::write_endian(g
.first
->direct_map
+ g
.second
, value
, g
.first
->endian
);
42 serialization::write_endian(&buf
, value
, g
.first
->endian
);
43 g
.first
->write(g
.second
, &buf
, sizeof(T
));
48 void read_range_r(memory_region
& r
, uint64_t offset
, void* buffer
, size_t bsize
)
51 if(offset
>= r
.size
) {
52 memset(buffer
, 0, bsize
);
55 uint64_t maxcopy
= min(static_cast<uint64_t>(bsize
), r
.size
- offset
);
56 memcpy(buffer
, r
.direct_map
+ offset
, maxcopy
);
58 memset(reinterpret_cast<char*>(buffer
) + maxcopy
, 0, bsize
- maxcopy
);
60 r
.read(offset
, buffer
, bsize
);
63 bool write_range_r(memory_region
& r
, uint64_t offset
, const void* buffer
, size_t bsize
)
70 uint64_t maxcopy
= min(static_cast<uint64_t>(bsize
), r
.size
- offset
);
71 memcpy(r
.direct_map
+ offset
, buffer
, maxcopy
);
74 return r
.write(offset
, buffer
, bsize
);
78 memory_region::~memory_region() throw()
82 void memory_region::read(uint64_t offset
, void* buffer
, size_t tsize
)
84 if(!direct_map
|| offset
>= size
) {
85 memset(buffer
, 0, tsize
);
88 uint64_t maxcopy
= min(static_cast<uint64_t>(tsize
), size
- offset
);
89 memcpy(buffer
, direct_map
+ offset
, maxcopy
);
91 memset(reinterpret_cast<char*>(buffer
) + maxcopy
, 0, tsize
- maxcopy
);
94 bool memory_region::write(uint64_t offset
, const void* buffer
, size_t tsize
)
96 if(!direct_map
|| readonly
|| offset
>= size
)
98 uint64_t maxcopy
= min(static_cast<uint64_t>(tsize
), size
- offset
);
99 memcpy(direct_map
+ offset
, buffer
, maxcopy
);
103 std::pair
<memory_region
*, uint64_t> memory_space::lookup(uint64_t address
)
105 umutex_class
m(mutex
);
107 size_t ub
= u_regions
.size();
109 size_t mb
= (lb
+ ub
) / 2;
110 if(u_regions
[mb
]->base
> address
) {
114 if(u_regions
[mb
]->last_address() < address
) {
118 return std::make_pair(u_regions
[mb
], address
- u_regions
[mb
]->base
);
120 return std::make_pair(reinterpret_cast<memory_region
*>(NULL
), 0);
123 std::pair
<memory_region
*, uint64_t> memory_space::lookup_linear(uint64_t linear
)
125 umutex_class
m(mutex
);
126 if(linear
>= linear_size
)
127 return std::make_pair(reinterpret_cast<memory_region
*>(NULL
), 0);
129 size_t ub
= linear_bases
.size() - 1;
131 size_t mb
= (lb
+ ub
) / 2;
132 if(linear_bases
[mb
] > linear
) {
136 if(linear_bases
[mb
+ 1] <= linear
) {
140 return std::make_pair(u_lregions
[mb
], linear
- linear_bases
[mb
]);
142 return std::make_pair(reinterpret_cast<memory_region
*>(NULL
), 0);
145 void memory_space::read_all_linear_memory(uint8_t* buffer
)
147 auto g
= lookup_linear(0);
150 read_range_r(*g
.first
, g
.second
, buffer
+ off
, g
.first
->size
);
151 off
+= g
.first
->size
;
152 g
= lookup_linear(off
);
156 #define MSR memory_space::read
157 #define MSW memory_space::write
158 #define MSRL memory_space::read_linear
159 #define MSWL memory_space::write_linear
161 template<> int8_t MSR (uint64_t address
) { return internal_read
<int8_t, false>(*this, address
); }
162 template<> uint8_t MSR (uint64_t address
) { return internal_read
<uint8_t, false>(*this, address
); }
163 template<> int16_t MSR (uint64_t address
) { return internal_read
<int16_t, false>(*this, address
); }
164 template<> uint16_t MSR (uint64_t address
) { return internal_read
<uint16_t, false>(*this, address
); }
165 template<> ss_int24_t
MSR (uint64_t address
) { return internal_read
<ss_int24_t
, false>(*this, address
); }
166 template<> ss_uint24_t
MSR (uint64_t address
) { return internal_read
<ss_uint24_t
, false>(*this, address
); }
167 template<> int32_t MSR (uint64_t address
) { return internal_read
<int32_t, false>(*this, address
); }
168 template<> uint32_t MSR (uint64_t address
) { return internal_read
<uint32_t, false>(*this, address
); }
169 template<> int64_t MSR (uint64_t address
) { return internal_read
<int64_t, false>(*this, address
); }
170 template<> uint64_t MSR (uint64_t address
) { return internal_read
<uint64_t, false>(*this, address
); }
171 template<> float MSR (uint64_t address
) { return internal_read
<float, false>(*this, address
); }
172 template<> double MSR (uint64_t address
) { return internal_read
<double, false>(*this, address
); }
173 template<> bool MSW (uint64_t a
, int8_t v
) { return internal_write
<int8_t, false>(*this, a
, v
); }
174 template<> bool MSW (uint64_t a
, uint8_t v
) { return internal_write
<uint8_t, false>(*this, a
, v
); }
175 template<> bool MSW (uint64_t a
, int16_t v
) { return internal_write
<int16_t, false>(*this, a
, v
); }
176 template<> bool MSW (uint64_t a
, uint16_t v
) { return internal_write
<uint16_t, false>(*this, a
, v
); }
177 template<> bool MSW (uint64_t a
, ss_int24_t v
) { return internal_write
<ss_int24_t
, false>(*this, a
, v
); }
178 template<> bool MSW (uint64_t a
, ss_uint24_t v
) { return internal_write
<ss_uint24_t
, false>(*this, a
, v
); }
179 template<> bool MSW (uint64_t a
, int32_t v
) { return internal_write
<int32_t, false>(*this, a
, v
); }
180 template<> bool MSW (uint64_t a
, uint32_t v
) { return internal_write
<uint32_t, false>(*this, a
, v
); }
181 template<> bool MSW (uint64_t a
, int64_t v
) { return internal_write
<int64_t, false>(*this, a
, v
); }
182 template<> bool MSW (uint64_t a
, uint64_t v
) { return internal_write
<uint64_t, false>(*this, a
, v
); }
183 template<> bool MSW (uint64_t a
, float v
) { return internal_write
<float, false>(*this, a
, v
); }
184 template<> bool MSW (uint64_t a
, double v
) { return internal_write
<double, false>(*this, a
, v
); }
185 template<> int8_t MSRL (uint64_t address
) { return internal_read
<int8_t, true>(*this, address
); }
186 template<> uint8_t MSRL (uint64_t address
) { return internal_read
<uint8_t, true>(*this, address
); }
187 template<> int16_t MSRL (uint64_t address
) { return internal_read
<int16_t, true>(*this, address
); }
188 template<> uint16_t MSRL (uint64_t address
) { return internal_read
<uint16_t, true>(*this, address
); }
189 template<> ss_int24_t
MSRL (uint64_t address
) { return internal_read
<ss_int24_t
, true>(*this, address
); }
190 template<> ss_uint24_t
MSRL (uint64_t address
) { return internal_read
<ss_uint24_t
, true>(*this, address
); }
191 template<> int32_t MSRL (uint64_t address
) { return internal_read
<int32_t, true>(*this, address
); }
192 template<> uint32_t MSRL (uint64_t address
) { return internal_read
<uint32_t, true>(*this, address
); }
193 template<> int64_t MSRL (uint64_t address
) { return internal_read
<int64_t, true>(*this, address
); }
194 template<> uint64_t MSRL (uint64_t address
) { return internal_read
<uint64_t, true>(*this, address
); }
195 template<> float MSRL (uint64_t address
) { return internal_read
<float, true>(*this, address
); }
196 template<> double MSRL (uint64_t address
) { return internal_read
<double, true>(*this, address
); }
197 template<> bool MSWL (uint64_t a
, int8_t v
) { return internal_write
<int8_t, true>(*this, a
, v
); }
198 template<> bool MSWL (uint64_t a
, uint8_t v
) { return internal_write
<uint8_t, true>(*this, a
, v
); }
199 template<> bool MSWL (uint64_t a
, int16_t v
) { return internal_write
<int16_t, true>(*this, a
, v
); }
200 template<> bool MSWL (uint64_t a
, uint16_t v
) { return internal_write
<uint16_t, true>(*this, a
, v
); }
201 template<> bool MSWL (uint64_t a
, ss_int24_t v
) { return internal_write
<ss_int24_t
, true>(*this, a
, v
); }
202 template<> bool MSWL (uint64_t a
, ss_uint24_t v
) { return internal_write
<ss_uint24_t
, true>(*this, a
, v
); }
203 template<> bool MSWL (uint64_t a
, int32_t v
) { return internal_write
<int32_t, true>(*this, a
, v
); }
204 template<> bool MSWL (uint64_t a
, uint32_t v
) { return internal_write
<uint32_t, true>(*this, a
, v
); }
205 template<> bool MSWL (uint64_t a
, int64_t v
) { return internal_write
<int64_t, true>(*this, a
, v
); }
206 template<> bool MSWL (uint64_t a
, uint64_t v
) { return internal_write
<uint64_t, true>(*this, a
, v
); }
207 template<> bool MSWL (uint64_t a
, float v
) { return internal_write
<float, true>(*this, a
, v
); }
208 template<> bool MSWL (uint64_t a
, double v
) { return internal_write
<double, true>(*this, a
, v
); }
210 void memory_space::read_range(uint64_t address
, void* buffer
, size_t bsize
)
212 auto g
= lookup(address
);
214 memset(buffer
, 0, bsize
);
217 read_range_r(*g
.first
, g
.second
, buffer
, bsize
);
220 bool memory_space::write_range(uint64_t address
, const void* buffer
, size_t bsize
)
222 auto g
= lookup(address
);
225 return write_range_r(*g
.first
, g
.second
, buffer
, bsize
);
228 void memory_space::read_range_linear(uint64_t address
, void* buffer
, size_t bsize
)
230 auto g
= lookup_linear(address
);
232 memset(buffer
, 0, bsize
);
235 read_range_r(*g
.first
, g
.second
, buffer
, bsize
);
238 bool memory_space::write_range_linear(uint64_t address
, const void* buffer
, size_t bsize
)
240 auto g
= lookup_linear(address
);
243 return write_range_r(*g
.first
, g
.second
, buffer
, bsize
);
246 memory_region
* memory_space::lookup_n(size_t n
)
248 umutex_class
m(mutex
);
249 if(n
>= u_regions
.size())
255 std::list
<memory_region
*> memory_space::get_regions()
257 umutex_class
m(mutex
);
258 std::list
<memory_region
*> r
;
259 for(auto i
: u_regions
)
264 char* memory_space::get_physical_mapping(uint64_t base
, uint64_t size
)
266 uint64_t last
= base
+ size
- 1;
268 return NULL
; //Warps around.
269 auto g1
= lookup(base
);
270 auto g2
= lookup(last
);
271 if(g1
.first
!= g2
.first
)
272 return NULL
; //Not the same VMA.
273 if(!g1
.first
|| !g1
.first
->direct_map
)
274 return NULL
; //Not mapped.
276 return reinterpret_cast<char*>(g1
.first
->direct_map
+ g1
.second
);
279 void memory_space::set_regions(const std::list
<memory_region
*>& regions
)
281 umutex_class
m(mutex
);
282 std::vector
<memory_region
*> n_regions
;
283 std::vector
<memory_region
*> n_lregions
;
284 std::vector
<uint64_t> n_linear_bases
;
285 //Calculate array sizes.
286 n_regions
.resize(regions
.size());
288 for(auto i
: regions
)
289 if(!i
->readonly
&& !i
->special
)
291 n_lregions
.resize(linear_c
);
292 n_linear_bases
.resize(linear_c
+ 1);
294 //Fill the main array (it must be sorted!).
296 for(auto j
: regions
)
298 std::sort(n_regions
.begin(), n_regions
.end(),
299 [](memory_region
* a
, memory_region
* b
) -> bool { return a
->base
< b
->base
; });
301 //Fill linear address arrays from the main array.
304 for(auto j
: n_regions
) {
305 if(j
->readonly
|| j
->special
)
308 n_linear_bases
[i
] = base
;
309 base
= base
+ j
->size
;
312 n_linear_bases
[i
] = base
;
314 std::swap(u_regions
, n_regions
);
315 std::swap(u_lregions
, n_lregions
);
316 std::swap(linear_bases
, n_linear_bases
);
320 int memory_space::_get_system_endian()
324 uint16_t magic
= 258;
325 return (*reinterpret_cast<uint8_t*>(&magic
) == 1) ? 1 : -1;
328 int memory_space::sysendian
= 0;
330 memory_region_direct::memory_region_direct(const std::string
& _name
, uint64_t _base
, int _endian
,
331 unsigned char* _memory
, size_t _size
, bool _readonly
)
336 direct_map
= _memory
;
338 readonly
= _readonly
;
342 memory_region_direct::~memory_region_direct() throw() {}