mirror of
				https://github.com/yuzu-emu/yuzu-android.git
				synced 2025-11-04 09:24:57 +00:00 
			
		
		
		
	k_process: PageTable -> GetPageTable
This commit is contained in:
		
							parent
							
								
									04868ab9da
								
							
						
					
					
						commit
						a85ce8ea56
					
				| 
						 | 
				
			
			@ -556,7 +556,7 @@ void GDBStub::HandleQuery(std::string_view command) {
 | 
			
		|||
        } else {
 | 
			
		||||
            SendReply(fmt::format(
 | 
			
		||||
                "TextSeg={:x}",
 | 
			
		||||
                GetInteger(system.ApplicationProcess()->PageTable().GetCodeRegionStart())));
 | 
			
		||||
                GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart())));
 | 
			
		||||
        }
 | 
			
		||||
    } else if (command.starts_with("Xfer:libraries:read::")) {
 | 
			
		||||
        Loader::AppLoader::Modules modules;
 | 
			
		||||
| 
						 | 
				
			
			@ -731,7 +731,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
 | 
			
		|||
    std::string reply;
 | 
			
		||||
 | 
			
		||||
    auto* process = system.ApplicationProcess();
 | 
			
		||||
    auto& page_table = process->PageTable();
 | 
			
		||||
    auto& page_table = process->GetPageTable();
 | 
			
		||||
 | 
			
		||||
    const char* commands = "Commands:\n"
 | 
			
		||||
                           "  get fastmem\n"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddres
 | 
			
		|||
    m_owner = GetCurrentProcessPointer(m_kernel);
 | 
			
		||||
 | 
			
		||||
    // Get the owner page table.
 | 
			
		||||
    auto& page_table = m_owner->PageTable();
 | 
			
		||||
    auto& page_table = m_owner->GetPageTable();
 | 
			
		||||
 | 
			
		||||
    // Construct the page group.
 | 
			
		||||
    m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager());
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ void KCodeMemory::Finalize() {
 | 
			
		|||
    // Unlock.
 | 
			
		||||
    if (!m_is_mapped && !m_is_owner_mapped) {
 | 
			
		||||
        const size_t size = m_page_group->GetNumPages() * PageSize;
 | 
			
		||||
        m_owner->PageTable().UnlockForCodeMemory(m_address, size, *m_page_group);
 | 
			
		||||
        m_owner->GetPageTable().UnlockForCodeMemory(m_address, size, *m_page_group);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Close the page group.
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +75,7 @@ Result KCodeMemory::Map(KProcessAddress address, size_t size) {
 | 
			
		|||
    R_UNLESS(!m_is_mapped, ResultInvalidState);
 | 
			
		||||
 | 
			
		||||
    // Map the memory.
 | 
			
		||||
    R_TRY(GetCurrentProcess(m_kernel).PageTable().MapPageGroup(
 | 
			
		||||
    R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup(
 | 
			
		||||
        address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
 | 
			
		||||
 | 
			
		||||
    // Mark ourselves as mapped.
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ Result KCodeMemory::Unmap(KProcessAddress address, size_t size) {
 | 
			
		|||
    KScopedLightLock lk(m_lock);
 | 
			
		||||
 | 
			
		||||
    // Unmap the memory.
 | 
			
		||||
    R_TRY(GetCurrentProcess(m_kernel).PageTable().UnmapPageGroup(address, *m_page_group,
 | 
			
		||||
    R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group,
 | 
			
		||||
                                                                    KMemoryState::CodeOut));
 | 
			
		||||
 | 
			
		||||
    // Mark ourselves as unmapped.
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +126,7 @@ Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::Memory
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    // Map the memory.
 | 
			
		||||
    R_TRY(m_owner->PageTable().MapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode,
 | 
			
		||||
    R_TRY(m_owner->GetPageTable().MapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode,
 | 
			
		||||
                                               k_perm));
 | 
			
		||||
 | 
			
		||||
    // Mark ourselves as mapped.
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +143,8 @@ Result KCodeMemory::UnmapFromOwner(KProcessAddress address, size_t size) {
 | 
			
		|||
    KScopedLightLock lk(m_lock);
 | 
			
		||||
 | 
			
		||||
    // Unmap the memory.
 | 
			
		||||
    R_TRY(m_owner->PageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode));
 | 
			
		||||
    R_TRY(m_owner->GetPageTable().UnmapPageGroup(address, *m_page_group,
 | 
			
		||||
                                                 KMemoryState::GeneratedCode));
 | 
			
		||||
 | 
			
		||||
    // Mark ourselves as unmapped.
 | 
			
		||||
    m_is_owner_mapped = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ namespace {
 | 
			
		|||
 */
 | 
			
		||||
void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority,
 | 
			
		||||
                     KProcessAddress stack_top) {
 | 
			
		||||
    const KProcessAddress entry_point = owner_process.PageTable().GetCodeRegionStart();
 | 
			
		||||
    const KProcessAddress entry_point = owner_process.GetPageTable().GetCodeRegionStart();
 | 
			
		||||
    ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
 | 
			
		||||
 | 
			
		||||
    KThread* thread = KThread::Create(system.Kernel());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,16 +109,6 @@ public:
 | 
			
		|||
    static Result Initialize(KProcess* process, Core::System& system, std::string process_name,
 | 
			
		||||
                             ProcessType type, KResourceLimit* res_limit);
 | 
			
		||||
 | 
			
		||||
    /// Gets a reference to the process' page table.
 | 
			
		||||
    KPageTable& PageTable() {
 | 
			
		||||
        return m_page_table;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Gets const a reference to the process' page table.
 | 
			
		||||
    const KPageTable& PageTable() const {
 | 
			
		||||
        return m_page_table;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Gets a reference to the process' page table.
 | 
			
		||||
    KPageTable& GetPageTable() {
 | 
			
		||||
        return m_page_table;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,8 +90,8 @@ Result KSharedMemory::Map(KProcess& target_process, KProcessAddress address, std
 | 
			
		|||
        R_UNLESS(map_perm == test_perm, ResultInvalidNewMemoryPermission);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    R_RETURN(target_process.PageTable().MapPageGroup(address, *m_page_group, KMemoryState::Shared,
 | 
			
		||||
                                                     ConvertToKMemoryPermission(map_perm)));
 | 
			
		||||
    R_RETURN(target_process.GetPageTable().MapPageGroup(
 | 
			
		||||
        address, *m_page_group, KMemoryState::Shared, ConvertToKMemoryPermission(map_perm)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address,
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +100,7 @@ Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address,
 | 
			
		|||
    R_UNLESS(m_size == unmap_size, ResultInvalidSize);
 | 
			
		||||
 | 
			
		||||
    R_RETURN(
 | 
			
		||||
        target_process.PageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::Shared));
 | 
			
		||||
        target_process.GetPageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::Shared));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Kernel
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
 | 
			
		|||
 | 
			
		||||
    // Map the address in.
 | 
			
		||||
    const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf);
 | 
			
		||||
    R_TRY(m_owner->PageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr,
 | 
			
		||||
    R_TRY(m_owner->GetPageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr,
 | 
			
		||||
                                           KMemoryState::ThreadLocal,
 | 
			
		||||
                                           KMemoryPermission::UserReadWrite));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,11 +37,11 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
 | 
			
		|||
 | 
			
		||||
Result KThreadLocalPage::Finalize() {
 | 
			
		||||
    // Get the physical address of the page.
 | 
			
		||||
    const KPhysicalAddress phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr);
 | 
			
		||||
    const KPhysicalAddress phys_addr = m_owner->GetPageTable().GetPhysicalAddr(m_virt_addr);
 | 
			
		||||
    ASSERT(phys_addr);
 | 
			
		||||
 | 
			
		||||
    // Unmap the page.
 | 
			
		||||
    R_TRY(m_owner->PageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal));
 | 
			
		||||
    R_TRY(m_owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal));
 | 
			
		||||
 | 
			
		||||
    // Free the page.
 | 
			
		||||
    KPageBuffer::Free(*m_kernel, KPageBuffer::FromPhysicalAddress(m_kernel->System(), phys_addr));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad
 | 
			
		|||
    R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
 | 
			
		||||
    // Verify the region is within range.
 | 
			
		||||
    auto& page_table = process->PageTable();
 | 
			
		||||
    auto& page_table = process->GetPageTable();
 | 
			
		||||
    R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    // Perform the operation.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t
 | 
			
		|||
    SCOPE_EXIT({ code_mem->Close(); });
 | 
			
		||||
 | 
			
		||||
    // Verify that the region is in range.
 | 
			
		||||
    R_UNLESS(GetCurrentProcess(system.Kernel()).PageTable().Contains(address, size),
 | 
			
		||||
    R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size),
 | 
			
		||||
             ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    // Initialize the code memory.
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
 | 
			
		|||
    case CodeMemoryOperation::Map: {
 | 
			
		||||
        // Check that the region is in range.
 | 
			
		||||
        R_UNLESS(GetCurrentProcess(system.Kernel())
 | 
			
		||||
                     .PageTable()
 | 
			
		||||
                     .GetPageTable()
 | 
			
		||||
                     .CanContain(address, size, KMemoryState::CodeOut),
 | 
			
		||||
                 ResultInvalidMemoryRegion);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +105,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
 | 
			
		|||
    case CodeMemoryOperation::Unmap: {
 | 
			
		||||
        // Check that the region is in range.
 | 
			
		||||
        R_UNLESS(GetCurrentProcess(system.Kernel())
 | 
			
		||||
                     .PageTable()
 | 
			
		||||
                     .GetPageTable()
 | 
			
		||||
                     .CanContain(address, size, KMemoryState::CodeOut),
 | 
			
		||||
                 ResultInvalidMemoryRegion);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +117,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
 | 
			
		|||
    } break;
 | 
			
		||||
    case CodeMemoryOperation::MapToOwner: {
 | 
			
		||||
        // Check that the region is in range.
 | 
			
		||||
        R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size,
 | 
			
		||||
        R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size,
 | 
			
		||||
                                                                 KMemoryState::GeneratedCode),
 | 
			
		||||
                 ResultInvalidMemoryRegion);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +129,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
 | 
			
		|||
    } break;
 | 
			
		||||
    case CodeMemoryOperation::UnmapFromOwner: {
 | 
			
		||||
        // Check that the region is in range.
 | 
			
		||||
        R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size,
 | 
			
		||||
        R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size,
 | 
			
		||||
                                                                 KMemoryState::GeneratedCode),
 | 
			
		||||
                 ResultInvalidMemoryRegion);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -107,7 +107,7 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han
 | 
			
		|||
    R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
 | 
			
		||||
    // Validate that the process address is within range.
 | 
			
		||||
    auto& page_table = process->PageTable();
 | 
			
		||||
    auto& page_table = process->GetPageTable();
 | 
			
		||||
    R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    // Map.
 | 
			
		||||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han
 | 
			
		|||
    R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
 | 
			
		||||
    // Validate that the process address is within range.
 | 
			
		||||
    auto& page_table = process->PageTable();
 | 
			
		||||
    auto& page_table = process->GetPageTable();
 | 
			
		||||
    R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    // Map.
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +180,7 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p
 | 
			
		|||
    R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
 | 
			
		||||
    // Validate that the process address is within range.
 | 
			
		||||
    auto& page_table = process->PageTable();
 | 
			
		||||
    auto& page_table = process->GetPageTable();
 | 
			
		||||
    R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    R_RETURN(das->Unmap(std::addressof(page_table), process_address, size, device_address));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,35 +54,35 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
 | 
			
		|||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::AliasRegionAddress:
 | 
			
		||||
            *result = GetInteger(process->PageTable().GetAliasRegionStart());
 | 
			
		||||
            *result = GetInteger(process->GetPageTable().GetAliasRegionStart());
 | 
			
		||||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::AliasRegionSize:
 | 
			
		||||
            *result = process->PageTable().GetAliasRegionSize();
 | 
			
		||||
            *result = process->GetPageTable().GetAliasRegionSize();
 | 
			
		||||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::HeapRegionAddress:
 | 
			
		||||
            *result = GetInteger(process->PageTable().GetHeapRegionStart());
 | 
			
		||||
            *result = GetInteger(process->GetPageTable().GetHeapRegionStart());
 | 
			
		||||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::HeapRegionSize:
 | 
			
		||||
            *result = process->PageTable().GetHeapRegionSize();
 | 
			
		||||
            *result = process->GetPageTable().GetHeapRegionSize();
 | 
			
		||||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::AslrRegionAddress:
 | 
			
		||||
            *result = GetInteger(process->PageTable().GetAliasCodeRegionStart());
 | 
			
		||||
            *result = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
 | 
			
		||||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::AslrRegionSize:
 | 
			
		||||
            *result = process->PageTable().GetAliasCodeRegionSize();
 | 
			
		||||
            *result = process->GetPageTable().GetAliasCodeRegionSize();
 | 
			
		||||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::StackRegionAddress:
 | 
			
		||||
            *result = GetInteger(process->PageTable().GetStackRegionStart());
 | 
			
		||||
            *result = GetInteger(process->GetPageTable().GetStackRegionStart());
 | 
			
		||||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::StackRegionSize:
 | 
			
		||||
            *result = process->PageTable().GetStackRegionSize();
 | 
			
		||||
            *result = process->GetPageTable().GetStackRegionSize();
 | 
			
		||||
            R_SUCCEED();
 | 
			
		||||
 | 
			
		||||
        case InfoType::TotalMemorySize:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,7 +112,7 @@ Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPe
 | 
			
		|||
    R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
 | 
			
		||||
 | 
			
		||||
    // Validate that the region is in range for the current process.
 | 
			
		||||
    auto& page_table = GetCurrentProcess(system.Kernel()).PageTable();
 | 
			
		||||
    auto& page_table = GetCurrentProcess(system.Kernel()).GetPageTable();
 | 
			
		||||
    R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    // Set the memory attribute.
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +136,7 @@ Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask,
 | 
			
		|||
    R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination);
 | 
			
		||||
 | 
			
		||||
    // Validate that the region is in range for the current process.
 | 
			
		||||
    auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
 | 
			
		||||
    auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
 | 
			
		||||
    R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    // Set the memory attribute.
 | 
			
		||||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
 | 
			
		|||
    LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
 | 
			
		||||
              src_addr, size);
 | 
			
		||||
 | 
			
		||||
    auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
 | 
			
		||||
    auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
 | 
			
		||||
 | 
			
		||||
    if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
 | 
			
		||||
        result.IsError()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +163,7 @@ Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
 | 
			
		|||
    LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
 | 
			
		||||
              src_addr, size);
 | 
			
		||||
 | 
			
		||||
    auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
 | 
			
		||||
    auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
 | 
			
		||||
 | 
			
		||||
    if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
 | 
			
		||||
        result.IsError()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ Result SetHeapSize(Core::System& system, u64* out_address, u64 size) {
 | 
			
		|||
    R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
 | 
			
		||||
 | 
			
		||||
    // Set the heap size.
 | 
			
		||||
    R_RETURN(GetCurrentProcess(system.Kernel()).PageTable().SetHeapSize(out_address, size));
 | 
			
		||||
    R_RETURN(GetCurrentProcess(system.Kernel()).GetPageTable().SetHeapSize(out_address, size));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Maps memory at a desired address
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
 | 
			
		||||
    auto& page_table{current_process->PageTable()};
 | 
			
		||||
    auto& page_table{current_process->GetPageTable()};
 | 
			
		||||
 | 
			
		||||
    if (current_process->GetSystemResourceSize() == 0) {
 | 
			
		||||
        LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
 | 
			
		||||
    auto& page_table{current_process->PageTable()};
 | 
			
		||||
    auto& page_table{current_process->GetPageTable()};
 | 
			
		||||
 | 
			
		||||
    if (current_process->GetSystemResourceSize() == 0) {
 | 
			
		||||
        LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,7 +66,7 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
 | 
			
		|||
    auto& kernel = system.Kernel();
 | 
			
		||||
    const auto total_copy_size = out_process_ids_size * sizeof(u64);
 | 
			
		||||
 | 
			
		||||
    if (out_process_ids_size > 0 && !GetCurrentProcess(kernel).PageTable().IsInsideAddressSpace(
 | 
			
		||||
    if (out_process_ids_size > 0 && !GetCurrentProcess(kernel).GetPageTable().IsInsideAddressSpace(
 | 
			
		||||
                                        out_process_ids, total_copy_size)) {
 | 
			
		||||
        LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
 | 
			
		||||
                  out_process_ids, out_process_ids + total_copy_size);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,7 +49,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u
 | 
			
		|||
    R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
 | 
			
		||||
    // Validate that the address is in range.
 | 
			
		||||
    auto& page_table = process->PageTable();
 | 
			
		||||
    auto& page_table = process->GetPageTable();
 | 
			
		||||
    R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    // Set the memory permission.
 | 
			
		||||
| 
						 | 
				
			
			@ -77,8 +77,8 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha
 | 
			
		|||
    R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
 | 
			
		||||
    // Get the page tables.
 | 
			
		||||
    auto& dst_pt = dst_process->PageTable();
 | 
			
		||||
    auto& src_pt = src_process->PageTable();
 | 
			
		||||
    auto& dst_pt = dst_process->GetPageTable();
 | 
			
		||||
    auto& src_pt = src_process->GetPageTable();
 | 
			
		||||
 | 
			
		||||
    // Validate that the mapping is in range.
 | 
			
		||||
    R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
| 
						 | 
				
			
			@ -118,8 +118,8 @@ Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_
 | 
			
		|||
    R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
 | 
			
		||||
    // Get the page tables.
 | 
			
		||||
    auto& dst_pt = dst_process->PageTable();
 | 
			
		||||
    auto& src_pt = src_process->PageTable();
 | 
			
		||||
    auto& dst_pt = dst_process->GetPageTable();
 | 
			
		||||
    auto& src_pt = src_process->GetPageTable();
 | 
			
		||||
 | 
			
		||||
    // Validate that the mapping is in range.
 | 
			
		||||
    R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +178,7 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
 | 
			
		|||
        R_THROW(ResultInvalidHandle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& page_table = process->PageTable();
 | 
			
		||||
    auto& page_table = process->GetPageTable();
 | 
			
		||||
    if (!page_table.IsInsideAddressSpace(src_address, size)) {
 | 
			
		||||
        LOG_ERROR(Kernel_SVC,
 | 
			
		||||
                  "Source address range is not within the address space (src_address=0x{:016X}, "
 | 
			
		||||
| 
						 | 
				
			
			@ -246,7 +246,7 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
 | 
			
		|||
        R_THROW(ResultInvalidHandle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& page_table = process->PageTable();
 | 
			
		||||
    auto& page_table = process->GetPageTable();
 | 
			
		||||
    if (!page_table.IsInsideAddressSpace(src_address, size)) {
 | 
			
		||||
        LOG_ERROR(Kernel_SVC,
 | 
			
		||||
                  "Source address range is not within the address space (src_address=0x{:016X}, "
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    auto& current_memory{GetCurrentMemory(system.Kernel())};
 | 
			
		||||
    const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
 | 
			
		||||
    const auto memory_info{process->GetPageTable().QueryInfo(address).GetSvcMemoryInfo()};
 | 
			
		||||
 | 
			
		||||
    current_memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u
 | 
			
		|||
 | 
			
		||||
    // Get the current process.
 | 
			
		||||
    auto& process = GetCurrentProcess(system.Kernel());
 | 
			
		||||
    auto& page_table = process.PageTable();
 | 
			
		||||
    auto& page_table = process.GetPageTable();
 | 
			
		||||
 | 
			
		||||
    // Get the shared memory.
 | 
			
		||||
    KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +73,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address,
 | 
			
		|||
 | 
			
		||||
    // Get the current process.
 | 
			
		||||
    auto& process = GetCurrentProcess(system.Kernel());
 | 
			
		||||
    auto& page_table = process.PageTable();
 | 
			
		||||
    auto& page_table = process.GetPageTable();
 | 
			
		||||
 | 
			
		||||
    // Get the shared memory.
 | 
			
		||||
    KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -236,7 +236,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
 | 
			
		|||
    const auto total_copy_size = out_thread_ids_size * sizeof(u64);
 | 
			
		||||
 | 
			
		||||
    if (out_thread_ids_size > 0 &&
 | 
			
		||||
        !current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) {
 | 
			
		||||
        !current_process->GetPageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) {
 | 
			
		||||
        LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
 | 
			
		||||
                  out_thread_ids, out_thread_ids + total_copy_size);
 | 
			
		||||
        R_THROW(ResultInvalidCurrentMemory);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64
 | 
			
		|||
    SCOPE_EXIT({ trmem->Close(); });
 | 
			
		||||
 | 
			
		||||
    // Ensure that the region is in range.
 | 
			
		||||
    R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
    R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory);
 | 
			
		||||
 | 
			
		||||
    // Initialize the transfer memory.
 | 
			
		||||
    R_TRY(trmem->Initialize(address, size, map_perm));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -358,7 +358,7 @@ public:
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) {
 | 
			
		||||
        auto& page_table{process->PageTable()};
 | 
			
		||||
        auto& page_table{process->GetPageTable()};
 | 
			
		||||
        VAddr addr{};
 | 
			
		||||
 | 
			
		||||
        for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -382,7 +382,7 @@ public:
 | 
			
		|||
    ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size,
 | 
			
		||||
                            VAddr bss_addr, std::size_t bss_size, std::size_t size) {
 | 
			
		||||
        for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
 | 
			
		||||
            auto& page_table{process->PageTable()};
 | 
			
		||||
            auto& page_table{process->GetPageTable()};
 | 
			
		||||
            VAddr addr{};
 | 
			
		||||
 | 
			
		||||
            CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size));
 | 
			
		||||
| 
						 | 
				
			
			@ -437,12 +437,12 @@ public:
 | 
			
		|||
        CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
 | 
			
		||||
                 nro_header.segment_headers[DATA_INDEX].memory_size);
 | 
			
		||||
 | 
			
		||||
        CASCADE_CODE(process->PageTable().SetProcessMemoryPermission(
 | 
			
		||||
        CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
 | 
			
		||||
            text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute));
 | 
			
		||||
        CASCADE_CODE(process->PageTable().SetProcessMemoryPermission(
 | 
			
		||||
        CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
 | 
			
		||||
            ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read));
 | 
			
		||||
 | 
			
		||||
        return process->PageTable().SetProcessMemoryPermission(
 | 
			
		||||
        return process->GetPageTable().SetProcessMemoryPermission(
 | 
			
		||||
            data_start, bss_end_addr - data_start, Kernel::Svc::MemoryPermission::ReadWrite);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -571,7 +571,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    Result UnmapNro(const NROInfo& info) {
 | 
			
		||||
        // Each region must be unmapped separately to validate memory state
 | 
			
		||||
        auto& page_table{system.ApplicationProcess()->PageTable()};
 | 
			
		||||
        auto& page_table{system.ApplicationProcess()->GetPageTable()};
 | 
			
		||||
 | 
			
		||||
        if (info.bss_size != 0) {
 | 
			
		||||
            CASCADE_CODE(page_table.UnmapCodeMemory(
 | 
			
		||||
| 
						 | 
				
			
			@ -643,7 +643,7 @@ public:
 | 
			
		|||
 | 
			
		||||
        initialized = true;
 | 
			
		||||
        current_map_addr =
 | 
			
		||||
            GetInteger(system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart());
 | 
			
		||||
            GetInteger(system.ApplicationProcess()->GetPageTable().GetAliasCodeRegionStart());
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,7 +128,7 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) {
 | 
			
		|||
    }
 | 
			
		||||
    bool is_out_io{};
 | 
			
		||||
    ASSERT(system.ApplicationProcess()
 | 
			
		||||
               ->PageTable()
 | 
			
		||||
               ->GetPageTable()
 | 
			
		||||
               .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address,
 | 
			
		||||
                                             handle_description->size,
 | 
			
		||||
                                             Kernel::KMemoryPermission::None, true, false)
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +255,7 @@ NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) {
 | 
			
		|||
    if (auto freeInfo{file.FreeHandle(params.handle, false)}) {
 | 
			
		||||
        if (freeInfo->can_unlock) {
 | 
			
		||||
            ASSERT(system.ApplicationProcess()
 | 
			
		||||
                       ->PageTable()
 | 
			
		||||
                       ->GetPageTable()
 | 
			
		||||
                       .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size)
 | 
			
		||||
                       .IsSuccess());
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
 | 
			
		|||
 | 
			
		||||
    // Load NSO modules
 | 
			
		||||
    modules.clear();
 | 
			
		||||
    const VAddr base_address{GetInteger(process.PageTable().GetCodeRegionStart())};
 | 
			
		||||
    const VAddr base_address{GetInteger(process.GetPageTable().GetCodeRegionStart())};
 | 
			
		||||
    VAddr next_load_addr{base_address};
 | 
			
		||||
    const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
 | 
			
		||||
                                   system.GetContentProvider()};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,7 +96,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    codeset.memory = std::move(program_image);
 | 
			
		||||
    const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart());
 | 
			
		||||
    const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart());
 | 
			
		||||
    process.LoadModule(std::move(codeset), base_address);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -203,7 +203,7 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data)
 | 
			
		|||
 | 
			
		||||
    // Load codeset for current process
 | 
			
		||||
    codeset.memory = std::move(program_image);
 | 
			
		||||
    process.LoadModule(std::move(codeset), process.PageTable().GetCodeRegionStart());
 | 
			
		||||
    process.LoadModule(std::move(codeset), process.GetPageTable().GetCodeRegionStart());
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -167,7 +167,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S
 | 
			
		|||
    modules.clear();
 | 
			
		||||
 | 
			
		||||
    // Load module
 | 
			
		||||
    const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart());
 | 
			
		||||
    const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart());
 | 
			
		||||
    if (!LoadModule(process, system, *file, base_address, true, true)) {
 | 
			
		||||
        return {ResultStatus::ErrorLoadingNSO, {}};
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,10 +31,10 @@ struct Memory::Impl {
 | 
			
		|||
    explicit Impl(Core::System& system_) : system{system_} {}
 | 
			
		||||
 | 
			
		||||
    void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) {
 | 
			
		||||
        current_page_table = &process.PageTable().PageTableImpl();
 | 
			
		||||
        current_page_table = &process.GetPageTable().PageTableImpl();
 | 
			
		||||
        current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
 | 
			
		||||
 | 
			
		||||
        const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth();
 | 
			
		||||
        const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth();
 | 
			
		||||
 | 
			
		||||
        system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +186,7 @@ struct Memory::Impl {
 | 
			
		|||
    void WalkBlock(const Kernel::KProcess& process, const Common::ProcessAddress addr,
 | 
			
		||||
                   const std::size_t size, auto on_unmapped, auto on_memory, auto on_rasterizer,
 | 
			
		||||
                   auto increment) {
 | 
			
		||||
        const auto& page_table = process.PageTable().PageTableImpl();
 | 
			
		||||
        const auto& page_table = process.GetPageTable().PageTableImpl();
 | 
			
		||||
        std::size_t remaining_size = size;
 | 
			
		||||
        std::size_t page_index = addr >> YUZU_PAGEBITS;
 | 
			
		||||
        std::size_t page_offset = addr & YUZU_PAGEMASK;
 | 
			
		||||
| 
						 | 
				
			
			@ -808,7 +808,7 @@ void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress b
 | 
			
		|||
 | 
			
		||||
bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
 | 
			
		||||
    const Kernel::KProcess& process = *system.ApplicationProcess();
 | 
			
		||||
    const auto& page_table = process.PageTable().PageTableImpl();
 | 
			
		||||
    const auto& page_table = process.GetPageTable().PageTableImpl();
 | 
			
		||||
    const size_t page = vaddr >> YUZU_PAGEBITS;
 | 
			
		||||
    if (page >= page_table.pointers.size()) {
 | 
			
		||||
        return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -177,8 +177,8 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
 | 
			
		|||
 | 
			
		||||
CheatEngine::CheatEngine(System& system_, std::vector<CheatEntry> cheats_,
 | 
			
		||||
                         const std::array<u8, 0x20>& build_id_)
 | 
			
		||||
    : vm{std::make_unique<StandardVmCallbacks>(system_, metadata)},
 | 
			
		||||
      cheats(std::move(cheats_)), core_timing{system_.CoreTiming()}, system{system_} {
 | 
			
		||||
    : vm{std::make_unique<StandardVmCallbacks>(system_, metadata)}, cheats(std::move(cheats_)),
 | 
			
		||||
      core_timing{system_.CoreTiming()}, system{system_} {
 | 
			
		||||
    metadata.main_nso_build_id = build_id_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -199,7 +199,7 @@ void CheatEngine::Initialize() {
 | 
			
		|||
    metadata.process_id = system.ApplicationProcess()->GetProcessId();
 | 
			
		||||
    metadata.title_id = system.GetApplicationProcessProgramID();
 | 
			
		||||
 | 
			
		||||
    const auto& page_table = system.ApplicationProcess()->PageTable();
 | 
			
		||||
    const auto& page_table = system.ApplicationProcess()->GetPageTable();
 | 
			
		||||
    metadata.heap_extents = {
 | 
			
		||||
        .base = GetInteger(page_table.GetHeapRegionStart()),
 | 
			
		||||
        .size = page_table.GetHeapRegionSize(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -117,8 +117,8 @@ json GetProcessorStateDataAuto(Core::System& system) {
 | 
			
		|||
    arm.SaveContext(context);
 | 
			
		||||
 | 
			
		||||
    return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
 | 
			
		||||
                                 GetInteger(process->PageTable().GetCodeRegionStart()), context.sp,
 | 
			
		||||
                                 context.pc, context.pstate, context.cpu_registers);
 | 
			
		||||
                                 GetInteger(process->GetPageTable().GetCodeRegionStart()),
 | 
			
		||||
                                 context.sp, context.pc, context.pstate, context.cpu_registers);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
json GetBacktraceData(Core::System& system) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue