diff options
| author | 2022-01-26 17:54:20 -0800 | |
|---|---|---|
| committer | 2022-01-26 17:54:20 -0800 | |
| commit | adcac857f8b14c8a57d6c4e8eca373521cddf422 (patch) | |
| tree | 0f2df96f2626eb167f98c6191e033007b5e49f14 /src | |
| parent | Merge pull request #7780 from lioncash/macro (diff) | |
| parent | core: hle: kernel: KPageTable: Various improvements to MapPages and UnmapPages. (diff) | |
| download | yuzu-adcac857f8b14c8a57d6c4e8eca373521cddf422.tar.gz yuzu-adcac857f8b14c8a57d6c4e8eca373521cddf422.tar.xz yuzu-adcac857f8b14c8a57d6c4e8eca373521cddf422.zip | |
Merge pull request #7762 from bunnei/un-map-improve
Kernel Memory Updates (Part 4): Improve Un/MapPages, and more.
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 204 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.h | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 4 |
3 files changed, 108 insertions, 111 deletions
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index b650ea31d..2ebbc0819 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -276,22 +276,23 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_ | |||
| 276 | 276 | ||
| 277 | ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemoryState state, | 277 | ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemoryState state, |
| 278 | KMemoryPermission perm) { | 278 | KMemoryPermission perm) { |
| 279 | std::lock_guard lock{page_table_lock}; | ||
| 280 | |||
| 281 | const u64 size{num_pages * PageSize}; | 279 | const u64 size{num_pages * PageSize}; |
| 282 | 280 | ||
| 283 | if (!CanContain(addr, size, state)) { | 281 | // Validate the mapping request. |
| 284 | return ResultInvalidCurrentMemory; | 282 | R_UNLESS(this->CanContain(addr, size, state), ResultInvalidCurrentMemory); |
| 285 | } | ||
| 286 | 283 | ||
| 287 | if (IsRegionMapped(addr, size)) { | 284 | // Lock the table. |
| 288 | return ResultInvalidCurrentMemory; | 285 | std::lock_guard lock{page_table_lock}; |
| 289 | } | 286 | |
| 287 | // Verify that the destination memory is unmapped. | ||
| 288 | R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, KMemoryState::Free, | ||
| 289 | KMemoryPermission::None, KMemoryPermission::None, | ||
| 290 | KMemoryAttribute::None, KMemoryAttribute::None)); | ||
| 290 | 291 | ||
| 291 | KPageLinkedList page_linked_list; | 292 | KPageLinkedList page_linked_list; |
| 292 | CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool, | 293 | R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool, |
| 293 | allocation_option)); | 294 | allocation_option)); |
| 294 | CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup)); | 295 | R_TRY(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup)); |
| 295 | 296 | ||
| 296 | block_manager->Update(addr, num_pages, state, perm); | 297 | block_manager->Update(addr, num_pages, state, perm); |
| 297 | 298 | ||
| @@ -395,39 +396,12 @@ ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size, | |||
| 395 | 396 | ||
| 396 | return ResultSuccess; | 397 | return ResultSuccess; |
| 397 | } | 398 | } |
| 398 | void KPageTable::MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end) { | ||
| 399 | auto node{page_linked_list.Nodes().begin()}; | ||
| 400 | PAddr map_addr{node->GetAddress()}; | ||
| 401 | std::size_t src_num_pages{node->GetNumPages()}; | ||
| 402 | |||
| 403 | block_manager->IterateForRange(start, end, [&](const KMemoryInfo& info) { | ||
| 404 | if (info.state != KMemoryState::Free) { | ||
| 405 | return; | ||
| 406 | } | ||
| 407 | |||
| 408 | std::size_t dst_num_pages{GetSizeInRange(info, start, end) / PageSize}; | ||
| 409 | VAddr dst_addr{GetAddressInRange(info, start)}; | ||
| 410 | |||
| 411 | while (dst_num_pages) { | ||
| 412 | if (!src_num_pages) { | ||
| 413 | node = std::next(node); | ||
| 414 | map_addr = node->GetAddress(); | ||
| 415 | src_num_pages = node->GetNumPages(); | ||
| 416 | } | ||
| 417 | |||
| 418 | const std::size_t num_pages{std::min(src_num_pages, dst_num_pages)}; | ||
| 419 | Operate(dst_addr, num_pages, KMemoryPermission::UserReadWrite, OperationType::Map, | ||
| 420 | map_addr); | ||
| 421 | |||
| 422 | dst_addr += num_pages * PageSize; | ||
| 423 | map_addr += num_pages * PageSize; | ||
| 424 | src_num_pages -= num_pages; | ||
| 425 | dst_num_pages -= num_pages; | ||
| 426 | } | ||
| 427 | }); | ||
| 428 | } | ||
| 429 | 399 | ||
| 430 | ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { | 400 | ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { |
| 401 | // Lock the physical memory lock. | ||
| 402 | std::lock_guard phys_lk(map_physical_memory_lock); | ||
| 403 | |||
| 404 | // Lock the table. | ||
| 431 | std::lock_guard lock{page_table_lock}; | 405 | std::lock_guard lock{page_table_lock}; |
| 432 | 406 | ||
| 433 | std::size_t mapped_size{}; | 407 | std::size_t mapped_size{}; |
| @@ -463,7 +437,35 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 463 | // We succeeded, so commit the memory reservation. | 437 | // We succeeded, so commit the memory reservation. |
| 464 | memory_reservation.Commit(); | 438 | memory_reservation.Commit(); |
| 465 | 439 | ||
| 466 | MapPhysicalMemory(page_linked_list, addr, end_addr); | 440 | // Map the memory. |
| 441 | auto node{page_linked_list.Nodes().begin()}; | ||
| 442 | PAddr map_addr{node->GetAddress()}; | ||
| 443 | std::size_t src_num_pages{node->GetNumPages()}; | ||
| 444 | block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) { | ||
| 445 | if (info.state != KMemoryState::Free) { | ||
| 446 | return; | ||
| 447 | } | ||
| 448 | |||
| 449 | std::size_t dst_num_pages{GetSizeInRange(info, addr, end_addr) / PageSize}; | ||
| 450 | VAddr dst_addr{GetAddressInRange(info, addr)}; | ||
| 451 | |||
| 452 | while (dst_num_pages) { | ||
| 453 | if (!src_num_pages) { | ||
| 454 | node = std::next(node); | ||
| 455 | map_addr = node->GetAddress(); | ||
| 456 | src_num_pages = node->GetNumPages(); | ||
| 457 | } | ||
| 458 | |||
| 459 | const std::size_t num_pages{std::min(src_num_pages, dst_num_pages)}; | ||
| 460 | Operate(dst_addr, num_pages, KMemoryPermission::UserReadWrite, OperationType::Map, | ||
| 461 | map_addr); | ||
| 462 | |||
| 463 | dst_addr += num_pages * PageSize; | ||
| 464 | map_addr += num_pages * PageSize; | ||
| 465 | src_num_pages -= num_pages; | ||
| 466 | dst_num_pages -= num_pages; | ||
| 467 | } | ||
| 468 | }); | ||
| 467 | 469 | ||
| 468 | mapped_physical_memory_size += remaining_size; | 470 | mapped_physical_memory_size += remaining_size; |
| 469 | 471 | ||
| @@ -503,23 +505,8 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 503 | return ResultSuccess; | 505 | return ResultSuccess; |
| 504 | } | 506 | } |
| 505 | 507 | ||
| 506 | CASCADE_CODE(UnmapMemory(addr, size)); | ||
| 507 | |||
| 508 | auto process{system.Kernel().CurrentProcess()}; | ||
| 509 | process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size); | ||
| 510 | mapped_physical_memory_size -= mapped_size; | ||
| 511 | |||
| 512 | return ResultSuccess; | ||
| 513 | } | ||
| 514 | |||
| 515 | ResultCode KPageTable::UnmapMemory(VAddr addr, std::size_t size) { | ||
| 516 | std::lock_guard lock{page_table_lock}; | ||
| 517 | |||
| 518 | const VAddr end_addr{addr + size}; | ||
| 519 | ResultCode result{ResultSuccess}; | ||
| 520 | KPageLinkedList page_linked_list; | ||
| 521 | |||
| 522 | // Unmap each region within the range | 508 | // Unmap each region within the range |
| 509 | KPageLinkedList page_linked_list; | ||
| 523 | block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) { | 510 | block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) { |
| 524 | if (info.state == KMemoryState::Normal) { | 511 | if (info.state == KMemoryState::Normal) { |
| 525 | const std::size_t block_size{GetSizeInRange(info, addr, end_addr)}; | 512 | const std::size_t block_size{GetSizeInRange(info, addr, end_addr)}; |
| @@ -535,7 +522,6 @@ ResultCode KPageTable::UnmapMemory(VAddr addr, std::size_t size) { | |||
| 535 | } | 522 | } |
| 536 | } | 523 | } |
| 537 | }); | 524 | }); |
| 538 | |||
| 539 | if (result.IsError()) { | 525 | if (result.IsError()) { |
| 540 | return result; | 526 | return result; |
| 541 | } | 527 | } |
| @@ -546,10 +532,14 @@ ResultCode KPageTable::UnmapMemory(VAddr addr, std::size_t size) { | |||
| 546 | 532 | ||
| 547 | block_manager->Update(addr, num_pages, KMemoryState::Free); | 533 | block_manager->Update(addr, num_pages, KMemoryState::Free); |
| 548 | 534 | ||
| 535 | auto process{system.Kernel().CurrentProcess()}; | ||
| 536 | process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size); | ||
| 537 | mapped_physical_memory_size -= mapped_size; | ||
| 538 | |||
| 549 | return ResultSuccess; | 539 | return ResultSuccess; |
| 550 | } | 540 | } |
| 551 | 541 | ||
| 552 | ResultCode KPageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) { | 542 | ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { |
| 553 | std::lock_guard lock{page_table_lock}; | 543 | std::lock_guard lock{page_table_lock}; |
| 554 | 544 | ||
| 555 | KMemoryState src_state{}; | 545 | KMemoryState src_state{}; |
| @@ -588,7 +578,7 @@ ResultCode KPageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) { | |||
| 588 | return ResultSuccess; | 578 | return ResultSuccess; |
| 589 | } | 579 | } |
| 590 | 580 | ||
| 591 | ResultCode KPageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) { | 581 | ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { |
| 592 | std::lock_guard lock{page_table_lock}; | 582 | std::lock_guard lock{page_table_lock}; |
| 593 | 583 | ||
| 594 | KMemoryState src_state{}; | 584 | KMemoryState src_state{}; |
| @@ -652,24 +642,26 @@ ResultCode KPageTable::MapPages(VAddr addr, const KPageLinkedList& page_linked_l | |||
| 652 | return ResultSuccess; | 642 | return ResultSuccess; |
| 653 | } | 643 | } |
| 654 | 644 | ||
| 655 | ResultCode KPageTable::MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, | 645 | ResultCode KPageTable::MapPages(VAddr address, KPageLinkedList& page_linked_list, |
| 656 | KMemoryPermission perm) { | 646 | KMemoryState state, KMemoryPermission perm) { |
| 657 | std::lock_guard lock{page_table_lock}; | 647 | // Check that the map is in range. |
| 658 | |||
| 659 | const std::size_t num_pages{page_linked_list.GetNumPages()}; | 648 | const std::size_t num_pages{page_linked_list.GetNumPages()}; |
| 660 | const std::size_t size{num_pages * PageSize}; | 649 | const std::size_t size{num_pages * PageSize}; |
| 650 | R_UNLESS(this->CanContain(address, size, state), ResultInvalidCurrentMemory); | ||
| 661 | 651 | ||
| 662 | if (!CanContain(addr, size, state)) { | 652 | // Lock the table. |
| 663 | return ResultInvalidCurrentMemory; | 653 | std::lock_guard lock{page_table_lock}; |
| 664 | } | ||
| 665 | 654 | ||
| 666 | if (IsRegionMapped(addr, num_pages * PageSize)) { | 655 | // Check the memory state. |
| 667 | return ResultInvalidCurrentMemory; | 656 | R_TRY(this->CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free, |
| 668 | } | 657 | KMemoryPermission::None, KMemoryPermission::None, |
| 658 | KMemoryAttribute::None, KMemoryAttribute::None)); | ||
| 669 | 659 | ||
| 670 | CASCADE_CODE(MapPages(addr, page_linked_list, perm)); | 660 | // Map the pages. |
| 661 | R_TRY(MapPages(address, page_linked_list, perm)); | ||
| 671 | 662 | ||
| 672 | block_manager->Update(addr, num_pages, state, perm); | 663 | // Update the blocks. |
| 664 | block_manager->Update(address, num_pages, state, perm); | ||
| 673 | 665 | ||
| 674 | return ResultSuccess; | 666 | return ResultSuccess; |
| 675 | } | 667 | } |
| @@ -693,21 +685,23 @@ ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked | |||
| 693 | 685 | ||
| 694 | ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, | 686 | ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, |
| 695 | KMemoryState state) { | 687 | KMemoryState state) { |
| 696 | std::lock_guard lock{page_table_lock}; | 688 | // Check that the unmap is in range. |
| 697 | |||
| 698 | const std::size_t num_pages{page_linked_list.GetNumPages()}; | 689 | const std::size_t num_pages{page_linked_list.GetNumPages()}; |
| 699 | const std::size_t size{num_pages * PageSize}; | 690 | const std::size_t size{num_pages * PageSize}; |
| 691 | R_UNLESS(this->Contains(addr, size), ResultInvalidCurrentMemory); | ||
| 700 | 692 | ||
| 701 | if (!CanContain(addr, size, state)) { | 693 | // Lock the table. |
| 702 | return ResultInvalidCurrentMemory; | 694 | std::lock_guard lock{page_table_lock}; |
| 703 | } | ||
| 704 | 695 | ||
| 705 | if (IsRegionMapped(addr, num_pages * PageSize)) { | 696 | // Check the memory state. |
| 706 | return ResultInvalidCurrentMemory; | 697 | R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, state, KMemoryPermission::None, |
| 707 | } | 698 | KMemoryPermission::None, KMemoryAttribute::All, |
| 699 | KMemoryAttribute::None)); | ||
| 708 | 700 | ||
| 709 | CASCADE_CODE(UnmapPages(addr, page_linked_list)); | 701 | // Perform the unmap. |
| 702 | R_TRY(UnmapPages(addr, page_linked_list)); | ||
| 710 | 703 | ||
| 704 | // Update the blocks. | ||
| 711 | block_manager->Update(addr, num_pages, state, KMemoryPermission::None); | 705 | block_manager->Update(addr, num_pages, state, KMemoryPermission::None); |
| 712 | 706 | ||
| 713 | return ResultSuccess; | 707 | return ResultSuccess; |
| @@ -765,7 +759,6 @@ ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size, | |||
| 765 | 759 | ||
| 766 | // Ensure cache coherency, if we're setting pages as executable. | 760 | // Ensure cache coherency, if we're setting pages as executable. |
| 767 | if (is_x) { | 761 | if (is_x) { |
| 768 | // Memory execution state is changing, invalidate CPU cache range | ||
| 769 | system.InvalidateCpuInstructionCacheRange(addr, size); | 762 | system.InvalidateCpuInstructionCacheRange(addr, size); |
| 770 | } | 763 | } |
| 771 | 764 | ||
| @@ -793,12 +786,12 @@ ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemo | |||
| 793 | KMemoryState state{}; | 786 | KMemoryState state{}; |
| 794 | KMemoryAttribute attribute{}; | 787 | KMemoryAttribute attribute{}; |
| 795 | 788 | ||
| 796 | CASCADE_CODE(CheckMemoryState( | 789 | R_TRY(CheckMemoryState(&state, nullptr, &attribute, nullptr, addr, size, |
| 797 | &state, nullptr, &attribute, nullptr, addr, size, | 790 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, |
| 798 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, | 791 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, |
| 799 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::All, | 792 | KMemoryPermission::All, KMemoryPermission::UserReadWrite, |
| 800 | KMemoryPermission::UserReadWrite, KMemoryAttribute::Mask, KMemoryAttribute::None, | 793 | KMemoryAttribute::Mask, KMemoryAttribute::None, |
| 801 | KMemoryAttribute::IpcAndDeviceMapped)); | 794 | KMemoryAttribute::IpcAndDeviceMapped)); |
| 802 | 795 | ||
| 803 | block_manager->Update(addr, size / PageSize, state, perm, attribute | KMemoryAttribute::Locked); | 796 | block_manager->Update(addr, size / PageSize, state, perm, attribute | KMemoryAttribute::Locked); |
| 804 | 797 | ||
| @@ -810,12 +803,11 @@ ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) { | |||
| 810 | 803 | ||
| 811 | KMemoryState state{}; | 804 | KMemoryState state{}; |
| 812 | 805 | ||
| 813 | CASCADE_CODE( | 806 | R_TRY(CheckMemoryState(&state, nullptr, nullptr, nullptr, addr, size, |
| 814 | CheckMemoryState(&state, nullptr, nullptr, nullptr, addr, size, | 807 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, |
| 815 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, | 808 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, |
| 816 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, | 809 | KMemoryPermission::None, KMemoryPermission::None, KMemoryAttribute::Mask, |
| 817 | KMemoryPermission::None, KMemoryPermission::None, KMemoryAttribute::Mask, | 810 | KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); |
| 818 | KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); | ||
| 819 | 811 | ||
| 820 | block_manager->Update(addr, size / PageSize, state, KMemoryPermission::UserReadWrite); | 812 | block_manager->Update(addr, size / PageSize, state, KMemoryPermission::UserReadWrite); |
| 821 | return ResultSuccess; | 813 | return ResultSuccess; |
| @@ -871,8 +863,9 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask | |||
| 871 | AttributeTestMask, KMemoryAttribute::None, ~AttributeTestMask)); | 863 | AttributeTestMask, KMemoryAttribute::None, ~AttributeTestMask)); |
| 872 | 864 | ||
| 873 | // Determine the new attribute. | 865 | // Determine the new attribute. |
| 874 | const auto new_attr = ((old_attr & static_cast<KMemoryAttribute>(~mask)) | | 866 | const KMemoryAttribute new_attr = |
| 875 | static_cast<KMemoryAttribute>(attr & mask)); | 867 | static_cast<KMemoryAttribute>(((old_attr & static_cast<KMemoryAttribute>(~mask)) | |
| 868 | static_cast<KMemoryAttribute>(attr & mask))); | ||
| 876 | 869 | ||
| 877 | // Perform operation. | 870 | // Perform operation. |
| 878 | this->Operate(addr, num_pages, old_perm, OperationType::ChangePermissionsAndRefresh); | 871 | this->Operate(addr, num_pages, old_perm, OperationType::ChangePermissionsAndRefresh); |
| @@ -896,6 +889,9 @@ ResultCode KPageTable::SetMaxHeapSize(std::size_t size) { | |||
| 896 | } | 889 | } |
| 897 | 890 | ||
| 898 | ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) { | 891 | ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) { |
| 892 | // Lock the physical memory lock. | ||
| 893 | std::lock_guard phys_lk(map_physical_memory_lock); | ||
| 894 | |||
| 899 | // Try to perform a reduction in heap, instead of an extension. | 895 | // Try to perform a reduction in heap, instead of an extension. |
| 900 | VAddr cur_address{}; | 896 | VAddr cur_address{}; |
| 901 | std::size_t allocation_size{}; | 897 | std::size_t allocation_size{}; |
| @@ -1025,12 +1021,12 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, | |||
| 1025 | } | 1021 | } |
| 1026 | 1022 | ||
| 1027 | if (is_map_only) { | 1023 | if (is_map_only) { |
| 1028 | CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); | 1024 | R_TRY(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); |
| 1029 | } else { | 1025 | } else { |
| 1030 | KPageLinkedList page_group; | 1026 | KPageLinkedList page_group; |
| 1031 | CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, | 1027 | R_TRY(system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, memory_pool, |
| 1032 | memory_pool, allocation_option)); | 1028 | allocation_option)); |
| 1033 | CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup)); | 1029 | R_TRY(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup)); |
| 1034 | } | 1030 | } |
| 1035 | 1031 | ||
| 1036 | block_manager->Update(addr, needed_num_pages, state, perm); | 1032 | block_manager->Update(addr, needed_num_pages, state, perm); |
| @@ -1186,7 +1182,7 @@ VAddr KPageTable::AllocateVirtualMemory(VAddr start, std::size_t region_num_page | |||
| 1186 | 1182 | ||
| 1187 | ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, const KPageLinkedList& page_group, | 1183 | ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, const KPageLinkedList& page_group, |
| 1188 | OperationType operation) { | 1184 | OperationType operation) { |
| 1189 | std::lock_guard lock{page_table_lock}; | 1185 | ASSERT(this->IsLockedByCurrentThread()); |
| 1190 | 1186 | ||
| 1191 | ASSERT(Common::IsAligned(addr, PageSize)); | 1187 | ASSERT(Common::IsAligned(addr, PageSize)); |
| 1192 | ASSERT(num_pages > 0); | 1188 | ASSERT(num_pages > 0); |
| @@ -1211,7 +1207,7 @@ ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, const KPageLin | |||
| 1211 | 1207 | ||
| 1212 | ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm, | 1208 | ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm, |
| 1213 | OperationType operation, PAddr map_addr) { | 1209 | OperationType operation, PAddr map_addr) { |
| 1214 | std::lock_guard lock{page_table_lock}; | 1210 | ASSERT(this->IsLockedByCurrentThread()); |
| 1215 | 1211 | ||
| 1216 | ASSERT(num_pages > 0); | 1212 | ASSERT(num_pages > 0); |
| 1217 | ASSERT(Common::IsAligned(addr, PageSize)); | 1213 | ASSERT(Common::IsAligned(addr, PageSize)); |
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index f67986e91..60ae9b9e8 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -37,9 +37,8 @@ public: | |||
| 37 | VAddr src_addr); | 37 | VAddr src_addr); |
| 38 | ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); | 38 | ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); |
| 39 | ResultCode UnmapPhysicalMemory(VAddr addr, std::size_t size); | 39 | ResultCode UnmapPhysicalMemory(VAddr addr, std::size_t size); |
| 40 | ResultCode UnmapMemory(VAddr addr, std::size_t size); | 40 | ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); |
| 41 | ResultCode Map(VAddr dst_addr, VAddr src_addr, std::size_t size); | 41 | ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); |
| 42 | ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size); | ||
| 43 | ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, | 42 | ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, |
| 44 | KMemoryPermission perm); | 43 | KMemoryPermission perm); |
| 45 | ResultCode UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state); | 44 | ResultCode UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state); |
| @@ -88,7 +87,6 @@ private: | |||
| 88 | ResultCode MapPages(VAddr addr, const KPageLinkedList& page_linked_list, | 87 | ResultCode MapPages(VAddr addr, const KPageLinkedList& page_linked_list, |
| 89 | KMemoryPermission perm); | 88 | KMemoryPermission perm); |
| 90 | ResultCode UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list); | 89 | ResultCode UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list); |
| 91 | void MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end); | ||
| 92 | bool IsRegionMapped(VAddr address, u64 size); | 90 | bool IsRegionMapped(VAddr address, u64 size); |
| 93 | bool IsRegionContiguous(VAddr addr, u64 size) const; | 91 | bool IsRegionContiguous(VAddr addr, u64 size) const; |
| 94 | void AddRegionToPages(VAddr start, std::size_t num_pages, KPageLinkedList& page_linked_list); | 92 | void AddRegionToPages(VAddr start, std::size_t num_pages, KPageLinkedList& page_linked_list); |
| @@ -148,6 +146,7 @@ private: | |||
| 148 | } | 146 | } |
| 149 | 147 | ||
| 150 | std::recursive_mutex page_table_lock; | 148 | std::recursive_mutex page_table_lock; |
| 149 | std::mutex map_physical_memory_lock; | ||
| 151 | std::unique_ptr<KMemoryBlockManager> block_manager; | 150 | std::unique_ptr<KMemoryBlockManager> block_manager; |
| 152 | 151 | ||
| 153 | public: | 152 | public: |
| @@ -249,7 +248,9 @@ public: | |||
| 249 | return !IsOutsideASLRRegion(address, size); | 248 | return !IsOutsideASLRRegion(address, size); |
| 250 | } | 249 | } |
| 251 | constexpr PAddr GetPhysicalAddr(VAddr addr) { | 250 | constexpr PAddr GetPhysicalAddr(VAddr addr) { |
| 252 | return page_table_impl.backing_addr[addr >> PageBits] + addr; | 251 | const auto backing_addr = page_table_impl.backing_addr[addr >> PageBits]; |
| 252 | ASSERT(backing_addr); | ||
| 253 | return backing_addr + addr; | ||
| 253 | } | 254 | } |
| 254 | constexpr bool Contains(VAddr addr) const { | 255 | constexpr bool Contains(VAddr addr) const { |
| 255 | return address_space_start <= addr && addr <= address_space_end - 1; | 256 | return address_space_start <= addr && addr <= address_space_end - 1; |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c7f5140f4..40bb893ac 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -230,7 +230,7 @@ static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr | |||
| 230 | return result; | 230 | return result; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | return page_table.Map(dst_addr, src_addr, size); | 233 | return page_table.MapMemory(dst_addr, src_addr, size); |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { | 236 | static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { |
| @@ -249,7 +249,7 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad | |||
| 249 | return result; | 249 | return result; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | return page_table.Unmap(dst_addr, src_addr, size); | 252 | return page_table.UnmapMemory(dst_addr, src_addr, size); |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { | 255 | static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { |