| 611 | } |
| 612 | |
| 613 | void KMemory::performOnMemory(U32 address, U32 len, bool readOnly, std::function<bool(U8* ram, U32 len)> callback) { |
| 614 | if (!len) { |
| 615 | return; |
| 616 | } |
| 617 | U32 pageIndex = address >> K_PAGE_SHIFT; |
| 618 | Page* page = data->getPage(pageIndex); |
| 619 | U32 offset = address & K_PAGE_MASK; |
| 620 | U32 todo = len; |
| 621 | if (todo > K_PAGE_SIZE - offset) { |
| 622 | todo = K_PAGE_SIZE - offset; |
| 623 | } |
| 624 | |
| 625 | U8* ram = page->getRamPtr(&data->mmu[pageIndex], pageIndex, !readOnly, true, offset, todo); |
| 626 | if (!ram) { |
| 627 | kpanic("KMemory::performOnMemory failed to get ram"); |
| 628 | } |
| 629 | if (!callback(ram, todo)) { |
| 630 | return; |
| 631 | } |
| 632 | address += todo; |
| 633 | len -= todo; |
| 634 | |
| 635 | while (len > K_PAGE_SIZE) { |
| 636 | pageIndex++; |
| 637 | page = data->getPage(pageIndex); |
| 638 | ram = page->getRamPtr(&data->mmu[pageIndex], pageIndex, !readOnly, true, 0, K_PAGE_SIZE); |
| 639 | if (!ram) { |
| 640 | kpanic("KMemory::performOnMemory failed to get ram"); |
| 641 | } |
| 642 | if (!callback(ram, K_PAGE_SIZE)) { |
| 643 | return; |
| 644 | } |
| 645 | address += K_PAGE_SIZE; |
| 646 | len -= K_PAGE_SIZE; |
| 647 | } |
| 648 | |
| 649 | if (len > 0) { |
| 650 | pageIndex++; |
| 651 | page = data->getPage(pageIndex); |
| 652 | ram = page->getRamPtr(&data->mmu[pageIndex], pageIndex, !readOnly, true, 0, len); |
| 653 | if (!ram) { |
| 654 | kpanic("KMemory::performOnMemory failed to get ram"); |
| 655 | } |
| 656 | callback(ram, len); |
| 657 | } |
| 658 | } |
| 659 | |
| 660 | // This doesn't mean the data can't be changed by another thread, it just means the pointer will stay valid |
| 661 | U8* KMemory::lockReadOnlyMemory(U32 address, U32 len) { |
no test coverage detected