Skip to content

Commit 884f164

Browse files
committed
vm/sys_memory: Remove VM locking in sys_memory_get_page_attribute
1 parent ba2518f commit 884f164

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

rpcs3/Emu/Cell/lv2/sys_memory.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "Emu/CPU/CPUThread.h"
66
#include "Emu/Cell/ErrorCodes.h"
77
#include "Emu/Cell/SPUThread.h"
8+
#include "Emu/Cell/PPUThread.h"
89
#include "Emu/IdManager.h"
910

1011
#include "util/asm.hpp"
@@ -247,17 +248,37 @@ error_code sys_memory_free(cpu_thread& cpu, u32 addr)
247248
return CELL_OK;
248249
}
249250

250-
error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr)
251+
error_code sys_memory_get_page_attribute(ppu_thread& ppu, u32 addr, vm::ptr<sys_page_attr_t> attr)
251252
{
252-
cpu.state += cpu_flag::wait;
253+
ppu.state += cpu_flag::wait;
253254

254255
sys_memory.trace("sys_memory_get_page_attribute(addr=0x%x, attr=*0x%x)", addr, attr);
255256

256-
vm::writer_lock rlock;
257+
if ((addr >> 28) == (ppu.stack_addr >> 28))
258+
{
259+
// Stack address: fast path
260+
if (!(addr >= ppu.stack_addr && addr < ppu.stack_addr + ppu.stack_size) && !vm::check_addr(addr))
261+
{
262+
return { CELL_EINVAL, addr };
263+
}
264+
265+
if (!vm::check_addr(attr.addr(), vm::page_readable, attr.size()))
266+
{
267+
return CELL_EFAULT;
268+
}
257269

258-
if (!vm::check_addr(addr) || addr >= SPU_FAKE_BASE_ADDR)
270+
attr->attribute = 0x40000ull; // SYS_MEMORY_PROT_READ_WRITEs
271+
attr->access_right = SYS_MEMORY_ACCESS_RIGHT_PPU_THR;
272+
attr->page_size = 4096;
273+
attr->pad = 0; // Always write 0
274+
return CELL_OK;
275+
}
276+
277+
const auto [ok, vm_flags] = vm::get_addr_flags(addr);
278+
279+
if (!ok || addr >= SPU_FAKE_BASE_ADDR)
259280
{
260-
return CELL_EINVAL;
281+
return { CELL_EINVAL, addr };
261282
}
262283

263284
if (!vm::check_addr(attr.addr(), vm::page_readable, attr.size()))
@@ -266,19 +287,20 @@ error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_
266287
}
267288

268289
attr->attribute = 0x40000ull; // SYS_MEMORY_PROT_READ_WRITE (TODO)
269-
attr->access_right = addr >> 28 == 0xdu ? SYS_MEMORY_ACCESS_RIGHT_PPU_THR : SYS_MEMORY_ACCESS_RIGHT_ANY;// (TODO)
290+
attr->access_right = SYS_MEMORY_ACCESS_RIGHT_ANY; // TODO: Report accurately
270291

271-
if (vm::check_addr(addr, vm::page_1m_size))
292+
if (vm_flags & vm::page_1m_size)
272293
{
273294
attr->page_size = 0x100000;
274295
}
275-
else if (vm::check_addr(addr, vm::page_64k_size))
296+
else if (vm_flags & vm::page_64k_size)
276297
{
277298
attr->page_size = 0x10000;
278299
}
279300
else
280301
{
281-
attr->page_size = 4096;
302+
//attr->page_size = 4096;
303+
fmt::throw_exception("Unreachable");
282304
}
283305

284306
attr->pad = 0; // Always write 0

rpcs3/Emu/Cell/lv2/sys_memory.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Emu/Cell/ErrorCodes.h"
55

66
class cpu_thread;
7+
class ppu_thread;
78

89
enum lv2_mem_container_id : u32
910
{
@@ -131,7 +132,7 @@ struct sys_memory_user_memory_stat_t
131132
error_code sys_memory_allocate(cpu_thread& cpu, u64 size, u64 flags, vm::ptr<u32> alloc_addr);
132133
error_code sys_memory_allocate_from_container(cpu_thread& cpu, u64 size, u32 cid, u64 flags, vm::ptr<u32> alloc_addr);
133134
error_code sys_memory_free(cpu_thread& cpu, u32 start_addr);
134-
error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr);
135+
error_code sys_memory_get_page_attribute(ppu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr);
135136
error_code sys_memory_get_user_memory_size(cpu_thread& cpu, vm::ptr<sys_memory_info_t> mem_info);
136137
error_code sys_memory_get_user_memory_stat(cpu_thread& cpu, vm::ptr<sys_memory_user_memory_stat_t> mem_stat);
137138
error_code sys_memory_container_create(cpu_thread& cpu, vm::ptr<u32> cid, u64 size);

rpcs3/Emu/Memory/vm.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ namespace vm
8181
bool check_addr(u32 addr, u8 flags, u32 size);
8282

8383
template <u32 Size = 1>
84-
bool check_addr(u32 addr, u8 flags = page_readable)
84+
inline bool check_addr(u32 addr, u8 flags = page_readable)
8585
{
8686
extern std::array<memory_page, 0x100000000 / 4096> g_pages;
8787

@@ -94,6 +94,16 @@ namespace vm
9494
return !(~g_pages[addr / 4096] & (flags | page_allocated));
9595
}
9696

97+
// Like check_addr but should only be used in lock-free context with care
98+
inline std::pair<bool, u8> get_addr_flags(u32 addr) noexcept
99+
{
100+
extern std::array<memory_page, 0x100000000 / 4096> g_pages;
101+
102+
const u8 flags = g_pages[addr / 4096].load();
103+
104+
return std::make_pair(!!(flags & page_allocated), flags);
105+
}
106+
97107
// Read string in a safe manner (page aware) (bool true = if null-termination)
98108
bool read_string(u32 addr, u32 max_size, std::string& out_string, bool check_pages = true) noexcept;
99109

0 commit comments

Comments
 (0)