summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/memory.cpp127
-rw-r--r--src/core/memory.h78
2 files changed, 199 insertions, 6 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index f0888327f..6061d37ae 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -242,7 +242,52 @@ struct Memory::Impl {
242 } 242 }
243 case Common::PageType::RasterizerCachedMemory: { 243 case Common::PageType::RasterizerCachedMemory: {
244 const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); 244 const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
245 system.GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount); 245 system.GPU().FlushRegion(current_vaddr, copy_amount);
246 std::memcpy(dest_buffer, host_ptr, copy_amount);
247 break;
248 }
249 default:
250 UNREACHABLE();
251 }
252
253 page_index++;
254 page_offset = 0;
255 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
256 remaining_size -= copy_amount;
257 }
258 }
259
260 void ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
261 const std::size_t size) {
262 const auto& page_table = process.VMManager().page_table;
263
264 std::size_t remaining_size = size;
265 std::size_t page_index = src_addr >> PAGE_BITS;
266 std::size_t page_offset = src_addr & PAGE_MASK;
267
268 while (remaining_size > 0) {
269 const std::size_t copy_amount =
270 std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size);
271 const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
272
273 switch (page_table.attributes[page_index]) {
274 case Common::PageType::Unmapped: {
275 LOG_ERROR(HW_Memory,
276 "Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
277 current_vaddr, src_addr, size);
278 std::memset(dest_buffer, 0, copy_amount);
279 break;
280 }
281 case Common::PageType::Memory: {
282 DEBUG_ASSERT(page_table.pointers[page_index]);
283
284 const u8* const src_ptr =
285 page_table.pointers[page_index] + page_offset + (page_index << PAGE_BITS);
286 std::memcpy(dest_buffer, src_ptr, copy_amount);
287 break;
288 }
289 case Common::PageType::RasterizerCachedMemory: {
290 const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
246 std::memcpy(dest_buffer, host_ptr, copy_amount); 291 std::memcpy(dest_buffer, host_ptr, copy_amount);
247 break; 292 break;
248 } 293 }
@@ -261,6 +306,10 @@ struct Memory::Impl {
261 ReadBlock(*system.CurrentProcess(), src_addr, dest_buffer, size); 306 ReadBlock(*system.CurrentProcess(), src_addr, dest_buffer, size);
262 } 307 }
263 308
309 void ReadBlockUnsafe(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
310 ReadBlockUnsafe(*system.CurrentProcess(), src_addr, dest_buffer, size);
311 }
312
264 void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, 313 void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer,
265 const std::size_t size) { 314 const std::size_t size) {
266 const auto& page_table = process.VMManager().page_table; 315 const auto& page_table = process.VMManager().page_table;
@@ -290,7 +339,50 @@ struct Memory::Impl {
290 } 339 }
291 case Common::PageType::RasterizerCachedMemory: { 340 case Common::PageType::RasterizerCachedMemory: {
292 u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); 341 u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
293 system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount); 342 system.GPU().InvalidateRegion(current_vaddr, copy_amount);
343 std::memcpy(host_ptr, src_buffer, copy_amount);
344 break;
345 }
346 default:
347 UNREACHABLE();
348 }
349
350 page_index++;
351 page_offset = 0;
352 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
353 remaining_size -= copy_amount;
354 }
355 }
356
357 void WriteBlockUnsafe(const Kernel::Process& process, const VAddr dest_addr,
358 const void* src_buffer, const std::size_t size) {
359 const auto& page_table = process.VMManager().page_table;
360 std::size_t remaining_size = size;
361 std::size_t page_index = dest_addr >> PAGE_BITS;
362 std::size_t page_offset = dest_addr & PAGE_MASK;
363
364 while (remaining_size > 0) {
365 const std::size_t copy_amount =
366 std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size);
367 const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
368
369 switch (page_table.attributes[page_index]) {
370 case Common::PageType::Unmapped: {
371 LOG_ERROR(HW_Memory,
372 "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
373 current_vaddr, dest_addr, size);
374 break;
375 }
376 case Common::PageType::Memory: {
377 DEBUG_ASSERT(page_table.pointers[page_index]);
378
379 u8* const dest_ptr =
380 page_table.pointers[page_index] + page_offset + (page_index << PAGE_BITS);
381 std::memcpy(dest_ptr, src_buffer, copy_amount);
382 break;
383 }
384 case Common::PageType::RasterizerCachedMemory: {
385 u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
294 std::memcpy(host_ptr, src_buffer, copy_amount); 386 std::memcpy(host_ptr, src_buffer, copy_amount);
295 break; 387 break;
296 } 388 }
@@ -309,6 +401,10 @@ struct Memory::Impl {
309 WriteBlock(*system.CurrentProcess(), dest_addr, src_buffer, size); 401 WriteBlock(*system.CurrentProcess(), dest_addr, src_buffer, size);
310 } 402 }
311 403
404 void WriteBlockUnsafe(const VAddr dest_addr, const void* src_buffer, const std::size_t size) {
405 WriteBlockUnsafe(*system.CurrentProcess(), dest_addr, src_buffer, size);
406 }
407
312 void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { 408 void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) {
313 const auto& page_table = process.VMManager().page_table; 409 const auto& page_table = process.VMManager().page_table;
314 std::size_t remaining_size = size; 410 std::size_t remaining_size = size;
@@ -337,7 +433,7 @@ struct Memory::Impl {
337 } 433 }
338 case Common::PageType::RasterizerCachedMemory: { 434 case Common::PageType::RasterizerCachedMemory: {
339 u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); 435 u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
340 system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount); 436 system.GPU().InvalidateRegion(current_vaddr, copy_amount);
341 std::memset(host_ptr, 0, copy_amount); 437 std::memset(host_ptr, 0, copy_amount);
342 break; 438 break;
343 } 439 }
@@ -384,7 +480,7 @@ struct Memory::Impl {
384 } 480 }
385 case Common::PageType::RasterizerCachedMemory: { 481 case Common::PageType::RasterizerCachedMemory: {
386 const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); 482 const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
387 system.GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount); 483 system.GPU().FlushRegion(current_vaddr, copy_amount);
388 WriteBlock(process, dest_addr, host_ptr, copy_amount); 484 WriteBlock(process, dest_addr, host_ptr, copy_amount);
389 break; 485 break;
390 } 486 }
@@ -545,7 +641,7 @@ struct Memory::Impl {
545 break; 641 break;
546 case Common::PageType::RasterizerCachedMemory: { 642 case Common::PageType::RasterizerCachedMemory: {
547 const u8* const host_ptr = GetPointerFromVMA(vaddr); 643 const u8* const host_ptr = GetPointerFromVMA(vaddr);
548 system.GPU().FlushRegion(ToCacheAddr(host_ptr), sizeof(T)); 644 system.GPU().FlushRegion(vaddr, sizeof(T));
549 T value; 645 T value;
550 std::memcpy(&value, host_ptr, sizeof(T)); 646 std::memcpy(&value, host_ptr, sizeof(T));
551 return value; 647 return value;
@@ -587,7 +683,7 @@ struct Memory::Impl {
587 break; 683 break;
588 case Common::PageType::RasterizerCachedMemory: { 684 case Common::PageType::RasterizerCachedMemory: {
589 u8* const host_ptr{GetPointerFromVMA(vaddr)}; 685 u8* const host_ptr{GetPointerFromVMA(vaddr)};
590 system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), sizeof(T)); 686 system.GPU().InvalidateRegion(vaddr, sizeof(T));
591 std::memcpy(host_ptr, &data, sizeof(T)); 687 std::memcpy(host_ptr, &data, sizeof(T));
592 break; 688 break;
593 } 689 }
@@ -696,6 +792,15 @@ void Memory::ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_
696 impl->ReadBlock(src_addr, dest_buffer, size); 792 impl->ReadBlock(src_addr, dest_buffer, size);
697} 793}
698 794
795void Memory::ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr,
796 void* dest_buffer, const std::size_t size) {
797 impl->ReadBlockUnsafe(process, src_addr, dest_buffer, size);
798}
799
800void Memory::ReadBlockUnsafe(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
801 impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
802}
803
699void Memory::WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, 804void Memory::WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
700 std::size_t size) { 805 std::size_t size) {
701 impl->WriteBlock(process, dest_addr, src_buffer, size); 806 impl->WriteBlock(process, dest_addr, src_buffer, size);
@@ -705,6 +810,16 @@ void Memory::WriteBlock(const VAddr dest_addr, const void* src_buffer, const std
705 impl->WriteBlock(dest_addr, src_buffer, size); 810 impl->WriteBlock(dest_addr, src_buffer, size);
706} 811}
707 812
813void Memory::WriteBlockUnsafe(const Kernel::Process& process, VAddr dest_addr,
814 const void* src_buffer, std::size_t size) {
815 impl->WriteBlockUnsafe(process, dest_addr, src_buffer, size);
816}
817
818void Memory::WriteBlockUnsafe(const VAddr dest_addr, const void* src_buffer,
819 const std::size_t size) {
820 impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
821}
822
708void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) { 823void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) {
709 impl->ZeroBlock(process, dest_addr, size); 824 impl->ZeroBlock(process, dest_addr, size);
710} 825}
diff --git a/src/core/memory.h b/src/core/memory.h
index 8913a9da4..b92d678a4 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -295,6 +295,27 @@ public:
295 std::size_t size); 295 std::size_t size);
296 296
297 /** 297 /**
298 * Reads a contiguous block of bytes from a specified process' address space.
299 * This unsafe version does not trigger GPU flushing.
300 *
301 * @param process The process to read the data from.
302 * @param src_addr The virtual address to begin reading from.
303 * @param dest_buffer The buffer to place the read bytes into.
304 * @param size The amount of data to read, in bytes.
305 *
306 * @note If a size of 0 is specified, then this function reads nothing and
307 * no attempts to access memory are made at all.
308 *
309 * @pre dest_buffer must be at least size bytes in length, otherwise a
310 * buffer overrun will occur.
311 *
312 * @post The range [dest_buffer, size) contains the read bytes from the
313 * process' address space.
314 */
315 void ReadBlockUnsafe(const Kernel::Process& process, VAddr src_addr, void* dest_buffer,
316 std::size_t size);
317
318 /**
298 * Reads a contiguous block of bytes from the current process' address space. 319 * Reads a contiguous block of bytes from the current process' address space.
299 * 320 *
300 * @param src_addr The virtual address to begin reading from. 321 * @param src_addr The virtual address to begin reading from.
@@ -313,6 +334,25 @@ public:
313 void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size); 334 void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size);
314 335
315 /** 336 /**
337 * Reads a contiguous block of bytes from the current process' address space.
338 * This unsafe version does not trigger GPU flushing.
339 *
340 * @param src_addr The virtual address to begin reading from.
341 * @param dest_buffer The buffer to place the read bytes into.
342 * @param size The amount of data to read, in bytes.
343 *
344 * @note If a size of 0 is specified, then this function reads nothing and
345 * no attempts to access memory are made at all.
346 *
347 * @pre dest_buffer must be at least size bytes in length, otherwise a
348 * buffer overrun will occur.
349 *
350 * @post The range [dest_buffer, size) contains the read bytes from the
351 * current process' address space.
352 */
353 void ReadBlockUnsafe(VAddr src_addr, void* dest_buffer, std::size_t size);
354
355 /**
316 * Writes a range of bytes into a given process' address space at the specified 356 * Writes a range of bytes into a given process' address space at the specified
317 * virtual address. 357 * virtual address.
318 * 358 *
@@ -336,6 +376,26 @@ public:
336 std::size_t size); 376 std::size_t size);
337 377
338 /** 378 /**
379 * Writes a range of bytes into a given process' address space at the specified
380 * virtual address.
381 * This unsafe version does not invalidate GPU Memory.
382 *
383 * @param process The process to write data into the address space of.
384 * @param dest_addr The destination virtual address to begin writing the data at.
385 * @param src_buffer The data to write into the process' address space.
386 * @param size The size of the data to write, in bytes.
387 *
388 * @post The address range [dest_addr, size) in the process' address space
389 * contains the data that was within src_buffer.
390 *
391 * @post If an attempt is made to write into an unmapped region of memory, the writes
392 * will be ignored and an error will be logged.
393 *
394 */
395 void WriteBlockUnsafe(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
396 std::size_t size);
397
398 /**
339 * Writes a range of bytes into the current process' address space at the specified 399 * Writes a range of bytes into the current process' address space at the specified
340 * virtual address. 400 * virtual address.
341 * 401 *
@@ -357,6 +417,24 @@ public:
357 void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size); 417 void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size);
358 418
359 /** 419 /**
420 * Writes a range of bytes into the current process' address space at the specified
421 * virtual address.
422 * This unsafe version does not invalidate GPU Memory.
423 *
424 * @param dest_addr The destination virtual address to begin writing the data at.
425 * @param src_buffer The data to write into the current process' address space.
426 * @param size The size of the data to write, in bytes.
427 *
428 * @post The address range [dest_addr, size) in the current process' address space
429 * contains the data that was within src_buffer.
430 *
431 * @post If an attempt is made to write into an unmapped region of memory, the writes
432 * will be ignored and an error will be logged.
433 *
434 */
435 void WriteBlockUnsafe(VAddr dest_addr, const void* src_buffer, std::size_t size);
436
437 /**
360 * Fills the specified address range within a process' address space with zeroes. 438 * Fills the specified address range within a process' address space with zeroes.
361 * 439 *
362 * @param process The process that will have a portion of its memory zeroed out. 440 * @param process The process that will have a portion of its memory zeroed out.