vm: Flag names (refactoring)

This commit is contained in:
Nick Renieris 2021-04-06 10:44:50 +03:00 committed by Ivan
parent f64a7bb820
commit 396c129d41
3 changed files with 70 additions and 37 deletions

View file

@ -26,8 +26,9 @@ enum : u64
enum : u64 enum : u64
{ {
SYS_MEMORY_PAGE_SIZE_1M = 0x400ull, SYS_MEMORY_PAGE_SIZE_4K = 0x100ull,
SYS_MEMORY_PAGE_SIZE_64K = 0x200ull, SYS_MEMORY_PAGE_SIZE_64K = 0x200ull,
SYS_MEMORY_PAGE_SIZE_1M = 0x400ull,
SYS_MEMORY_PAGE_SIZE_MASK = 0xf00ull, SYS_MEMORY_PAGE_SIZE_MASK = 0xf00ull,
}; };

View file

@ -9,7 +9,6 @@
#include "Utilities/Thread.h" #include "Utilities/Thread.h"
#include "Utilities/address_range.h" #include "Utilities/address_range.h"
#include "Emu/CPU/CPUThread.h" #include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/RSX/RSXThread.h" #include "Emu/RSX/RSXThread.h"
#include "Emu/Cell/SPURecompiler.h" #include "Emu/Cell/SPURecompiler.h"
#include "Emu/perf_meter.hpp" #include "Emu/perf_meter.hpp"
@ -1056,10 +1055,10 @@ namespace vm
} }
} }
const u32 page_addr = addr + (this->flags & 0x10 ? 0x1000 : 0); const u32 page_addr = addr + (this->flags & stack_guarded ? 0x1000 : 0);
const u32 page_size = size - (this->flags & 0x10 ? 0x2000 : 0); const u32 page_size = size - (this->flags & stack_guarded ? 0x2000 : 0);
if (this->flags & 0x10) if (this->flags & stack_guarded)
{ {
// Mark overflow/underflow guard pages as allocated // Mark overflow/underflow guard pages as allocated
ensure(!g_pages[addr / 4096].exchange(page_allocated)); ensure(!g_pages[addr / 4096].exchange(page_allocated));
@ -1074,7 +1073,7 @@ namespace vm
std::remove_reference_t<decltype(map)>::value_type* result = nullptr; std::remove_reference_t<decltype(map)>::value_type* result = nullptr;
// Check eligibility // Check eligibility
if (!_this || !(SYS_MEMORY_PAGE_SIZE_MASK & _this->flags) || _this->addr < 0x20000000 || _this->addr >= 0xC0000000) if (!_this || !(page_size_mask & _this->flags) || _this->addr < 0x20000000 || _this->addr >= 0xC0000000)
{ {
return result; return result;
} }
@ -1092,7 +1091,7 @@ namespace vm
}); });
// Fill stack guards with STACKGRD // Fill stack guards with STACKGRD
if (this->flags & 0x10) if (this->flags & stack_guarded)
{ {
auto fill64 = [](u8* ptr, u64 data, usz count) auto fill64 = [](u8* ptr, u64 data, usz count)
{ {
@ -1122,7 +1121,7 @@ namespace vm
, size(size) , size(size)
, flags(flags) , flags(flags)
{ {
if (flags & 0x100 || flags & 0x20) if (flags & page_size_4k || flags & preallocated)
{ {
// Special path for whole-allocated areas allowing 4k granularity // Special path for whole-allocated areas allowing 4k granularity
m_common = std::make_shared<utils::shm>(size); m_common = std::make_shared<utils::shm>(size);
@ -1164,10 +1163,10 @@ namespace vm
} }
// Determine minimal alignment // Determine minimal alignment
const u32 min_page_size = flags & 0x100 ? 0x1000 : 0x10000; const u32 min_page_size = flags & page_size_4k ? 0x1000 : 0x10000;
// Align to minimal page size // Align to minimal page size
const u32 size = utils::align(orig_size, min_page_size) + (flags & 0x10 ? 0x2000 : 0); const u32 size = utils::align(orig_size, min_page_size) + (flags & stack_guarded ? 0x2000 : 0);
// Check alignment (it's page allocation, so passing small values there is just silly) // Check alignment (it's page allocation, so passing small values there is just silly)
if (align < min_page_size || align != (0x80000000u >> std::countl_zero(align))) if (align < min_page_size || align != (0x80000000u >> std::countl_zero(align)))
@ -1181,13 +1180,13 @@ namespace vm
return 0; return 0;
} }
u8 pflags = flags & 0x1000 ? 0 : page_readable | page_writable; u8 pflags = flags & page_hidden ? 0 : page_readable | page_writable;
if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K) if ((flags & page_size_64k) == page_size_64k)
{ {
pflags |= page_64k_size; pflags |= page_64k_size;
} }
else if (!(flags & (SYS_MEMORY_PAGE_SIZE_MASK & ~SYS_MEMORY_PAGE_SIZE_1M))) else if (!(flags & (page_size_mask & ~page_size_1m)))
{ {
pflags |= page_1m_size; pflags |= page_1m_size;
} }
@ -1211,7 +1210,7 @@ namespace vm
{ {
if (try_alloc(addr, pflags, size, std::move(shm))) if (try_alloc(addr, pflags, size, std::move(shm)))
{ {
return addr + (flags & 0x10 ? 0x1000 : 0); return addr + (flags & stack_guarded ? 0x1000 : 0);
} }
} }
@ -1227,7 +1226,7 @@ namespace vm
} }
// Determine minimal alignment // Determine minimal alignment
const u32 min_page_size = flags & 0x100 ? 0x1000 : 0x10000; const u32 min_page_size = flags & page_size_4k ? 0x1000 : 0x10000;
// Take address misalignment into account // Take address misalignment into account
const u32 size0 = orig_size + addr % min_page_size; const u32 size0 = orig_size + addr % min_page_size;
@ -1235,10 +1234,15 @@ namespace vm
// Align to minimal page size // Align to minimal page size
const u32 size = utils::align(size0, min_page_size); const u32 size = utils::align(size0, min_page_size);
// return if addr or size is invalid // Return if addr or size is invalid
// If shared memory is provided, addr/size must be aligned // If shared memory is provided, addr/size must be aligned
if (!size || addr < this->addr || orig_size > size0 || orig_size > size || if (!size ||
(addr - addr % min_page_size) + u64{size} > this->addr + u64{this->size} || (src && (orig_size | addr) % min_page_size) || flags & 0x10) addr < this->addr ||
orig_size > size0 ||
orig_size > size ||
(addr - addr % min_page_size) + u64{size} > this->addr + u64{this->size} ||
(src && (orig_size | addr) % min_page_size) ||
flags & stack_guarded)
{ {
return 0; return 0;
} }
@ -1246,13 +1250,13 @@ namespace vm
// Force aligned address // Force aligned address
addr -= addr % min_page_size; addr -= addr % min_page_size;
u8 pflags = flags & 0x1000 ? 0 : page_readable | page_writable; u8 pflags = flags & page_hidden ? 0 : page_readable | page_writable;
if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K) if ((flags & page_size_64k) == page_size_64k)
{ {
pflags |= page_64k_size; pflags |= page_64k_size;
} }
else if (!(flags & (SYS_MEMORY_PAGE_SIZE_MASK & ~SYS_MEMORY_PAGE_SIZE_1M))) else if (!(flags & (page_size_mask & ~page_size_1m)))
{ {
pflags |= page_1m_size; pflags |= page_1m_size;
} }
@ -1285,7 +1289,7 @@ namespace vm
{ {
vm::writer_lock lock(0); vm::writer_lock lock(0);
const auto found = m_map.find(addr - (flags & 0x10 ? 0x1000 : 0)); const auto found = m_map.find(addr - (flags & stack_guarded ? 0x1000 : 0));
if (found == m_map.end()) if (found == m_map.end())
{ {
@ -1298,9 +1302,9 @@ namespace vm
} }
// Get allocation size // Get allocation size
const auto size = found->second.first - (flags & 0x10 ? 0x2000 : 0); const auto size = found->second.first - (flags & stack_guarded ? 0x2000 : 0);
if (flags & 0x10) if (flags & stack_guarded)
{ {
// Clear guard pages // Clear guard pages
ensure(g_pages[addr / 4096 - 1].exchange(0) == page_allocated); ensure(g_pages[addr / 4096 - 1].exchange(0) == page_allocated);
@ -1311,7 +1315,7 @@ namespace vm
ensure(size == _page_unmap(addr, size, found->second.second.get())); ensure(size == _page_unmap(addr, size, found->second.second.get()));
// Clear stack guards // Clear stack guards
if (flags & 0x10) if (flags & stack_guarded)
{ {
std::memset(g_sudo_addr + addr - 4096, 0, 4096); std::memset(g_sudo_addr + addr - 4096, 0, 4096);
std::memset(g_sudo_addr + addr + size, 0, 4096); std::memset(g_sudo_addr + addr + size, 0, 4096);
@ -1371,7 +1375,7 @@ namespace vm
for (auto& entry : (m.*block_map)()) for (auto& entry : (m.*block_map)())
{ {
result += entry.second.first - (flags & 0x10 ? 0x2000 : 0); result += entry.second.first - (flags & stack_guarded ? 0x2000 : 0);
} }
return result; return result;
@ -1515,12 +1519,12 @@ namespace vm
{ {
if (*it && (*it)->addr == addr) if (*it && (*it)->addr == addr)
{ {
if (must_be_empty && (*it)->flags & 0x3) if (must_be_empty && (*it)->flags & bf0_mask)
{ {
continue; continue;
} }
if (!must_be_empty && ((*it)->flags & 0x3) != 2) if (!must_be_empty && ((*it)->flags & bf0_mask) != bf0_0x2)
{ {
continue; continue;
} }
@ -1641,13 +1645,13 @@ namespace vm
g_locations = g_locations =
{ {
std::make_shared<block_t>(0x00010000, 0x1FFF0000, 0x220), // main std::make_shared<block_t>(0x00010000, 0x1FFF0000, page_size_64k | preallocated), // main
std::make_shared<block_t>(0x20000000, 0x10000000, 0x201), // user 64k pages std::make_shared<block_t>(0x20000000, 0x10000000, page_size_64k | bf0_0x1), // user 64k pages
nullptr, // user 1m pages nullptr, // user 1m pages
nullptr, // rsx context nullptr, // rsx context
std::make_shared<block_t>(0xC0000000, 0x10000000, 0x220), // video std::make_shared<block_t>(0xC0000000, 0x10000000, page_size_64k | preallocated), // video
std::make_shared<block_t>(0xD0000000, 0x10000000, 0x131), // stack std::make_shared<block_t>(0xD0000000, 0x10000000, page_size_4k | preallocated | stack_guarded | bf0_0x1), // stack
std::make_shared<block_t>(0xE0000000, 0x20000000, 0x200), // SPU reserved std::make_shared<block_t>(0xE0000000, 0x20000000, page_size_64k), // SPU reserved
}; };
std::memset(g_reservations, 0, sizeof(g_reservations)); std::memset(g_reservations, 0, sizeof(g_reservations));

View file

@ -90,6 +90,31 @@ namespace vm
// utils::memory_lock wrapper for locking sudo memory // utils::memory_lock wrapper for locking sudo memory
void lock_sudo(u32 addr, u32 size); void lock_sudo(u32 addr, u32 size);
enum block_flags_3
{
page_hidden = 0x1000,
};
enum block_flags_2_page_size
{
page_size_4k = 0x100, // SYS_MEMORY_PAGE_SIZE_4K
page_size_64k = 0x200, // SYS_MEMORY_PAGE_SIZE_64K
page_size_1m = 0x400, // SYS_MEMORY_PAGE_SIZE_1M
page_size_mask = 0xF00, // SYS_MEMORY_PAGE_SIZE_MASK
};
enum block_flags_1
{
stack_guarded = 0x10,
preallocated = 0x20, // nonshareable
};
enum block_flags_0
{
bf0_0x1 = 0x1, // TODO: document
bf0_0x2 = 0x2, // TODO: document
bf0_mask = bf0_0x1 | bf0_0x2,
};
// Object that handles memory allocations inside specific constant bounds ("location") // Object that handles memory allocations inside specific constant bounds ("location")
class block_t final class block_t final
{ {
@ -108,7 +133,10 @@ namespace vm
public: public:
const u32 addr; // Start address const u32 addr; // Start address
const u32 size; // Total size const u32 size; // Total size
const u64 flags; // Currently unused const u64 flags; // Byte 0xF000: block_flags_3
// Byte 0x0F00: block_flags_2_page_size (SYS_MEMORY_PAGE_SIZE_*)
// Byte 0x00F0: block_flags_1
// Byte 0x000F: block_flags_0
// Search and map memory (min alignment is 0x10000) // Search and map memory (min alignment is 0x10000)
u32 alloc(u32 size, const std::shared_ptr<utils::shm>* = nullptr, u32 align = 0x10000, u64 flags = 0); u32 alloc(u32 size, const std::shared_ptr<utils::shm>* = nullptr, u32 align = 0x10000, u64 flags = 0);
@ -142,7 +170,7 @@ namespace vm
std::shared_ptr<block_t> get(memory_location_t location, u32 addr = 0); std::shared_ptr<block_t> get(memory_location_t location, u32 addr = 0);
// Allocate segment at specified location, does nothing if exists already // Allocate segment at specified location, does nothing if exists already
std::shared_ptr<block_t> reserve_map(memory_location_t location, u32 addr, u32 area_size, u64 flags = 0x200); std::shared_ptr<block_t> reserve_map(memory_location_t location, u32 addr, u32 area_size, u64 flags = page_size_64k);
// Get PS3 virtual memory address from the provided pointer (nullptr or pointer from outside is always converted to 0) // Get PS3 virtual memory address from the provided pointer (nullptr or pointer from outside is always converted to 0)
// Super memory is allowed as well // Super memory is allowed as well