From b617874724c461cba270a00c0f8e67fc4a6d553a Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 10 Nov 2021 17:37:17 +0100 Subject: Common: implement MultiLevelPageTable. --- src/common/multi_level_page_table.inc | 83 +++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/common/multi_level_page_table.inc (limited to 'src/common/multi_level_page_table.inc') diff --git a/src/common/multi_level_page_table.inc b/src/common/multi_level_page_table.inc new file mode 100644 index 000000000..a75e61f9d --- /dev/null +++ b/src/common/multi_level_page_table.inc @@ -0,0 +1,83 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "common/assert.h" +#include "common/multi_level_page_table.h" + +namespace Common { + +template +MultiLevelPageTable::MultiLevelPageTable(std::size_t address_space_bits_, + std::size_t first_level_bits_, + std::size_t page_bits_) + : address_space_bits{address_space_bits_}, + first_level_bits{first_level_bits_}, page_bits{page_bits_} { + first_level_shift = address_space_bits - first_level_bits; + first_level_chunk_size = 1ULL << (first_level_shift - page_bits); + alloc_size = (1ULL << (address_space_bits - page_bits)) * sizeof(BaseAddr); + std::size_t first_level_size = 1ULL << first_level_bits; + first_level_map.resize(first_level_size, nullptr); +#ifdef _WIN32 + void* base{VirtualAlloc(nullptr, alloc_size, MEM_RESERVE, PAGE_READWRITE)}; +#else + void* base{mmap(nullptr, alloc_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)}; + + if (base == MAP_FAILED) { + base = nullptr; + } +#endif + + ASSERT(base); + base_ptr = reinterpret_cast(base); +} + +template +MultiLevelPageTable::~MultiLevelPageTable() noexcept { + if (!base_ptr) { + return; + } +#ifdef _WIN32 + ASSERT(VirtualFree(base_ptr, 0, MEM_RELEASE)); +#else + ASSERT(munmap(base_ptr, alloc_size) == 0); +#endif +} + +template +void MultiLevelPageTable::ReserveRange(u64 start, std::size_t size) { + const u64 new_start = start >> first_level_shift; + const u64 new_end = + (start + size + (first_level_chunk_size << page_bits) - 1) >> first_level_shift; + for (u64 i = new_start; i <= new_end; i++) { + if (!first_level_map[i]) { + AllocateLevel(i); + } + } +} + +template +void MultiLevelPageTable::AllocateLevel(u64 level) { + void* ptr = reinterpret_cast(base_ptr) + level * first_level_chunk_size; +#ifdef _WIN32 + void* base{VirtualAlloc(ptr, first_level_chunk_size, MEM_COMMIT, PAGE_READWRITE)}; +#else + void* base{mmap(ptr, first_level_chunk_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)}; + + if (base == MAP_FAILED) { + base = nullptr; + } +#endif + ASSERT(base); + + first_level_map[level] = base; +} + +} // namespace Common -- cgit v1.2.3 From cbaf3fb433a351f7d9509f17f88d4896ba66afd1 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 11 Nov 2021 21:24:40 +0100 Subject: VideoCore: Update MemoryManager --- src/common/multi_level_page_table.inc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/common/multi_level_page_table.inc') diff --git a/src/common/multi_level_page_table.inc b/src/common/multi_level_page_table.inc index a75e61f9d..7fbcb908a 100644 --- a/src/common/multi_level_page_table.inc +++ b/src/common/multi_level_page_table.inc @@ -20,7 +20,7 @@ MultiLevelPageTable::MultiLevelPageTable(std::size_t address_space_bit : address_space_bits{address_space_bits_}, first_level_bits{first_level_bits_}, page_bits{page_bits_} { first_level_shift = address_space_bits - first_level_bits; - first_level_chunk_size = 1ULL << (first_level_shift - page_bits); + first_level_chunk_size = (1ULL << (first_level_shift - page_bits)) * sizeof(BaseAddr); alloc_size = (1ULL << (address_space_bits - page_bits)) * sizeof(BaseAddr); std::size_t first_level_size = 1ULL << first_level_bits; first_level_map.resize(first_level_size, nullptr); @@ -53,8 +53,7 @@ MultiLevelPageTable::~MultiLevelPageTable() noexcept { template void MultiLevelPageTable::ReserveRange(u64 start, std::size_t size) { const u64 new_start = start >> first_level_shift; - const u64 new_end = - (start + size + (first_level_chunk_size << page_bits) - 1) >> first_level_shift; + const u64 new_end = (start + size) >> first_level_shift; for (u64 i = new_start; i <= new_end; i++) { if (!first_level_map[i]) { AllocateLevel(i); @@ -64,7 +63,7 @@ void MultiLevelPageTable::ReserveRange(u64 start, std::size_t size) { template void MultiLevelPageTable::AllocateLevel(u64 level) { - void* ptr = reinterpret_cast(base_ptr) + level * first_level_chunk_size; + void* ptr = reinterpret_cast(base_ptr) + level * first_level_chunk_size; #ifdef _WIN32 void* base{VirtualAlloc(ptr, first_level_chunk_size, MEM_COMMIT, PAGE_READWRITE)}; #else -- cgit v1.2.3 From 4d60410dd979fb688de7735d2b4b25a557bdeac7 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 5 Feb 2022 18:15:26 +0100 Subject: MemoryManager: initial multi paging system implementation. --- src/common/multi_level_page_table.inc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/common/multi_level_page_table.inc') diff --git a/src/common/multi_level_page_table.inc b/src/common/multi_level_page_table.inc index 7fbcb908a..9a68cad93 100644 --- a/src/common/multi_level_page_table.inc +++ b/src/common/multi_level_page_table.inc @@ -19,6 +19,9 @@ MultiLevelPageTable::MultiLevelPageTable(std::size_t address_space_bit std::size_t page_bits_) : address_space_bits{address_space_bits_}, first_level_bits{first_level_bits_}, page_bits{page_bits_} { + if (page_bits == 0) { + return; + } first_level_shift = address_space_bits - first_level_bits; first_level_chunk_size = (1ULL << (first_level_shift - page_bits)) * sizeof(BaseAddr); alloc_size = (1ULL << (address_space_bits - page_bits)) * sizeof(BaseAddr); -- cgit v1.2.3 From afab6c143cb486c7d14f1509cd04049ad08d3a65 Mon Sep 17 00:00:00 2001 From: Liam White Date: Wed, 13 Apr 2022 21:02:55 +0200 Subject: General: Fix compilation for GCC --- src/common/multi_level_page_table.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/common/multi_level_page_table.inc') diff --git a/src/common/multi_level_page_table.inc b/src/common/multi_level_page_table.inc index 9a68cad93..4def6dba8 100644 --- a/src/common/multi_level_page_table.inc +++ b/src/common/multi_level_page_table.inc @@ -30,7 +30,7 @@ MultiLevelPageTable::MultiLevelPageTable(std::size_t address_space_bit #ifdef _WIN32 void* base{VirtualAlloc(nullptr, alloc_size, MEM_RESERVE, PAGE_READWRITE)}; #else - void* base{mmap(nullptr, alloc_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)}; + void* base{mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)}; if (base == MAP_FAILED) { base = nullptr; -- cgit v1.2.3 From fedd983f96bcbcc0c39f651db1cca0503d582fd9 Mon Sep 17 00:00:00 2001 From: Morph Date: Wed, 29 Jun 2022 19:27:49 -0400 Subject: general: Format licenses as per SPDX guidelines --- src/common/multi_level_page_table.inc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/common/multi_level_page_table.inc') diff --git a/src/common/multi_level_page_table.inc b/src/common/multi_level_page_table.inc index 4def6dba8..8ac506fa0 100644 --- a/src/common/multi_level_page_table.inc +++ b/src/common/multi_level_page_table.inc @@ -1,6 +1,5 @@ -// Copyright 2021 yuzu Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #ifdef _WIN32 #include -- cgit v1.2.3