vm/sys_memory: Remove VM locking in sys_memory_get_page_attribute

This commit is contained in:
Elad 2025-10-31 07:58:45 +02:00
parent de914247be
commit ddecade935
3 changed files with 45 additions and 12 deletions

View file

@ -5,6 +5,7 @@
#include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/Cell/PPUThread.h"
#include "Emu/IdManager.h"
#include "util/asm.hpp"
@ -249,17 +250,37 @@ error_code sys_memory_free(cpu_thread& cpu, u32 addr)
return CELL_OK;
}
error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr)
error_code sys_memory_get_page_attribute(ppu_thread& ppu, u32 addr, vm::ptr<sys_page_attr_t> attr)
{
cpu.state += cpu_flag::wait;
ppu.state += cpu_flag::wait;
sys_memory.trace("sys_memory_get_page_attribute(addr=0x%x, attr=*0x%x)", addr, attr);
vm::writer_lock rlock;
if (!vm::check_addr(addr) || addr >= SPU_FAKE_BASE_ADDR)
if ((addr >> 28) == (ppu.stack_addr >> 28))
{
return CELL_EINVAL;
// Stack address: fast path
if (!(addr >= ppu.stack_addr && addr < ppu.stack_addr + ppu.stack_size) && !vm::check_addr(addr))
{
return { CELL_EINVAL, addr };
}
if (!vm::check_addr(attr.addr(), vm::page_readable, attr.size()))
{
return CELL_EFAULT;
}
attr->attribute = 0x40000ull; // SYS_MEMORY_PROT_READ_WRITE
attr->access_right = SYS_MEMORY_ACCESS_RIGHT_PPU_THR;
attr->page_size = 4096;
attr->pad = 0; // Always write 0
return CELL_OK;
}
const auto [ok, vm_flags] = vm::get_addr_flags(addr);
if (!ok || addr >= SPU_FAKE_BASE_ADDR)
{
return { CELL_EINVAL, addr };
}
if (!vm::check_addr(attr.addr(), vm::page_readable, attr.size()))
@ -268,19 +289,20 @@ error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_
}
attr->attribute = 0x40000ull; // SYS_MEMORY_PROT_READ_WRITE (TODO)
attr->access_right = addr >> 28 == 0xdu ? SYS_MEMORY_ACCESS_RIGHT_PPU_THR : SYS_MEMORY_ACCESS_RIGHT_ANY;// (TODO)
attr->access_right = SYS_MEMORY_ACCESS_RIGHT_ANY; // TODO: Report accurately
if (vm::check_addr(addr, vm::page_1m_size))
if (vm_flags & vm::page_1m_size)
{
attr->page_size = 0x100000;
}
else if (vm::check_addr(addr, vm::page_64k_size))
else if (vm_flags & vm::page_64k_size)
{
attr->page_size = 0x10000;
}
else
{
attr->page_size = 4096;
//attr->page_size = 4096;
fmt::throw_exception("Unreachable");
}
attr->pad = 0; // Always write 0

View file

@ -4,6 +4,7 @@
#include "Emu/Cell/ErrorCodes.h"
class cpu_thread;
class ppu_thread;
enum lv2_mem_container_id : u32
{
@ -131,7 +132,7 @@ struct sys_memory_user_memory_stat_t
error_code sys_memory_allocate(cpu_thread& cpu, u64 size, u64 flags, vm::ptr<u32> alloc_addr);
error_code sys_memory_allocate_from_container(cpu_thread& cpu, u64 size, u32 cid, u64 flags, vm::ptr<u32> alloc_addr);
error_code sys_memory_free(cpu_thread& cpu, u32 start_addr);
error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr);
error_code sys_memory_get_page_attribute(ppu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr);
error_code sys_memory_get_user_memory_size(cpu_thread& cpu, vm::ptr<sys_memory_info_t> mem_info);
error_code sys_memory_get_user_memory_stat(cpu_thread& cpu, vm::ptr<sys_memory_user_memory_stat_t> mem_stat);
error_code sys_memory_container_create(cpu_thread& cpu, vm::ptr<u32> cid, u64 size);

View file

@ -81,7 +81,7 @@ namespace vm
bool check_addr(u32 addr, u8 flags, u32 size);
template <u32 Size = 1>
bool check_addr(u32 addr, u8 flags = page_readable)
inline bool check_addr(u32 addr, u8 flags = page_readable)
{
extern std::array<memory_page, 0x100000000 / 4096> g_pages;
@ -94,6 +94,16 @@ namespace vm
return !(~g_pages[addr / 4096] & (flags | page_allocated));
}
// Like check_addr but should only be used in lock-free context with care
inline std::pair<bool, u8> get_addr_flags(u32 addr) noexcept
{
extern std::array<memory_page, 0x100000000 / 4096> g_pages;
const u8 flags = g_pages[addr / 4096].load();
return std::make_pair(!!(flags & page_allocated), flags);
}
// Read string in a safe manner (page aware) (bool true = if null-termination)
bool read_string(u32 addr, u32 max_size, std::string& out_string, bool check_pages = true) noexcept;