sys_rsx: Fix IOMAP syscalls argument types

This commit is contained in:
Elad 2026-06-17 12:00:49 +03:00
parent e429f8cf05
commit c1263eeb79
4 changed files with 49 additions and 25 deletions

View File

@ -18,7 +18,7 @@ LOG_CHANNEL(sys_rsx);
// Unknown error code returned by sys_rsx_context_attribute
enum sys_rsx_error : s32
{
SYS_RSX_CONTEXT_ATTRIBUTE_ERROR = -17
LV1_ILLEGAL_PARAMETER_VALUE = -17
};
template<>
@ -28,7 +28,7 @@ void fmt_class_string<sys_rsx_error>::format(std::string& out, u64 arg)
{
switch (error)
{
STR_CASE(SYS_RSX_CONTEXT_ATTRIBUTE_ERROR);
STR_CASE(LV1_ILLEGAL_PARAMETER_VALUE);
}
return unknown;
@ -169,12 +169,28 @@ error_code sys_rsx_device_close(cpu_thread& cpu)
* @param a6 (IN): E.g. Immediate value passed in cellGcmSys is 16.
* @param a7 (IN): E.g. Immediate value passed in cellGcmSys is 8.
*/
error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7)
error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u64 size, u64 flags, u64 a5, u64 a6, u64 a7)
{
cpu.state += cpu_flag::wait;
sys_rsx.warning("sys_rsx_memory_allocate(mem_handle=*0x%x, mem_addr=*0x%x, size=0x%x, flags=0x%llx, a5=0x%llx, a6=0x%llx, a7=0x%llx)", mem_handle, mem_addr, size, flags, a5, a6, a7);
// size == 0 yields available size, unimplemented
ensure(size != 0);
if (size & 0xFFFFF)
{
return LV1_ILLEGAL_PARAMETER_VALUE;
}
// This is a result from how the argument is treated internally
size %= 0x100000 * 0x1'0000'00000;
if (size > 0x1000'0000)
{
return LV1_ILLEGAL_PARAMETER_VALUE;
}
cpu.state += cpu_flag::wait;
if (vm::falloc(rsx::constants::local_mem_base, size, vm::video))
{
rsx::get_current_renderer()->local_mem_size = size;
@ -395,7 +411,7 @@ error_code sys_rsx_context_free(ppu_thread& ppu, u32 context_id)
* @param size (IN): Size of mapping area in bytes. E.g. 0x00200000
* @param flags (IN):
*/
error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u32 io, u32 ea, u32 size, u64 flags)
error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u64 io, u64 ea, u64 size, u64 flags)
{
cpu.state += cpu_flag::wait;
@ -403,8 +419,12 @@ error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u32 io, u32 ea
const auto render = rsx::get_current_renderer();
if (!size || io & 0xFFFFF || ea + u64{size} > rsx::constants::local_mem_base || ea & 0xFFFFF || size & 0xFFFFF ||
context_id != 0x55555555 || render->main_mem_size < io + u64{size})
if (!size || io & 0xFFFFF || size > 0x200'00000 || size > std::min<u64>(~io, ~size) || ea & 0xFFFFF || size & 0xFFFFF)
{
return CELL_EINVAL;
}
if (context_id != 0x55555555 || render->main_mem_size < io + size)
{
return CELL_EINVAL;
}
@ -419,7 +439,7 @@ error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u32 io, u32 ea
vm::writer_lock rlock;
for (u32 addr = ea, end = ea + size; addr < end; addr += 0x100000)
for (u64 addr = ea, end = ea + size; addr < end; addr += 0x100000)
{
if (!vm::check_addr(addr, vm::page_readable | (addr < 0x20000000 ? 0 : vm::page_1m_size)))
{
@ -458,7 +478,7 @@ error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u32 io, u32 ea
* @param io (IN): IO address. E.g. 0x00600000 (Start page 6)
* @param size (IN): Size to unmap in byte. E.g. 0x00200000
*/
error_code sys_rsx_context_iounmap(cpu_thread& cpu, u32 context_id, u32 io, u32 size)
error_code sys_rsx_context_iounmap(cpu_thread& cpu, u32 context_id, u64 io, u64 size)
{
cpu.state += cpu_flag::wait;
@ -466,8 +486,12 @@ error_code sys_rsx_context_iounmap(cpu_thread& cpu, u32 context_id, u32 io, u32
const auto render = rsx::get_current_renderer();
if (!size || size & 0xFFFFF || io & 0xFFFFF || context_id != 0x55555555 ||
render->main_mem_size < io + u64{size})
if (!size || size & 0xFFFFF || io & 0xFFFFF || size > 0x200'00000 || size > ~io)
{
return CELL_EINVAL;
}
if (context_id != 0x55555555 || render->main_mem_size < io + size)
{
return CELL_EINVAL;
}
@ -481,7 +505,7 @@ error_code sys_rsx_context_iounmap(cpu_thread& cpu, u32 context_id, u32 io, u32
std::scoped_lock lock(render->sys_rsx_mtx);
for (const u32 end = (io >>= 20) + (size >>= 20); io < end;)
for (const u64 end = (io >>= 20) + (size >>= 20); io < end;)
{
auto& table = render->iomap_table;
@ -626,7 +650,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
const u8 id = a3 & 0xFF;
if (id > 7)
{
return SYS_RSX_CONTEXT_ATTRIBUTE_ERROR;
return LV1_ILLEGAL_PARAMETER_VALUE;
}
std::lock_guard lock(render->sys_rsx_mtx);
@ -676,7 +700,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
{
if (a3 > 7)
{
return SYS_RSX_CONTEXT_ATTRIBUTE_ERROR;
return LV1_ILLEGAL_PARAMETER_VALUE;
}
// NOTE: There currently seem to only be 2 active heads on PS3
@ -784,7 +808,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
if (a3 >= std::size(render->zculls))
{
return SYS_RSX_CONTEXT_ATTRIBUTE_ERROR;
return LV1_ILLEGAL_PARAMETER_VALUE;
}
if (!render->is_fifo_idle())

View File

@ -127,12 +127,12 @@ struct RsxDisplayInfo
// SysCalls
error_code sys_rsx_device_open(cpu_thread& cpu);
error_code sys_rsx_device_close(cpu_thread& cpu);
error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7);
error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u64 size, u64 flags, u64 a5, u64 a6, u64 a7);
error_code sys_rsx_memory_free(cpu_thread& cpu, u32 mem_handle);
error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm::ptr<u64> lpar_dma_control, vm::ptr<u64> lpar_driver_info, vm::ptr<u64> lpar_reports, u64 mem_ctx, u64 system_mode);
error_code sys_rsx_context_free(ppu_thread& ppu, u32 context_id);
error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u32 io, u32 ea, u32 size, u64 flags);
error_code sys_rsx_context_iounmap(cpu_thread& cpu, u32 context_id, u32 io, u32 size);
error_code sys_rsx_context_iomap(cpu_thread& cpu, u32 context_id, u64 io, u64 ea, u64 size, u64 flags);
error_code sys_rsx_context_iounmap(cpu_thread& cpu, u32 context_id, u64 io, u64 size);
error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6);
error_code sys_rsx_device_map(cpu_thread& cpu, vm::ptr<u64> dev_addr, vm::ptr<u64> a2, u32 dev_id);
error_code sys_rsx_device_unmap(cpu_thread& cpu, u32 dev_id);

View File

@ -1070,15 +1070,15 @@ namespace vm
return size;
}
bool check_addr(u32 addr, u8 flags, u32 size)
bool check_addr(u64 addr, u8 flags, u32 size)
{
if (size == 0)
{
return true;
}
// Overflow checking
if (0x10000'0000ull - addr < size)
// u64 addressing is not supported at the moment
if (addr > u32{umax} || 0x10000'0000ull - addr < size)
{
return false;
}
@ -1086,7 +1086,7 @@ namespace vm
// Always check this flag
flags |= page_allocated;
for (u32 i = addr / 4096, max = (addr + size - 1) / 4096; i <= max;)
for (u64 i = addr / 4096, max = (addr + size - 1) / 4096; i <= max;)
{
auto state = +g_pages[i];

View File

@ -78,10 +78,10 @@ namespace vm
bool page_protect(u32 addr, u32 size, u8 flags_test = 0, u8 flags_set = 0, u8 flags_clear = 0);
// Check flags for specified memory range (unsafe)
bool check_addr(u32 addr, u8 flags, u32 size);
bool check_addr(u64 addr, u8 flags, u32 size);
template <u32 Size = 1>
inline bool check_addr(u32 addr, u8 flags = page_readable)
inline bool check_addr(u64 addr, u8 flags = page_readable)
{
extern std::array<memory_page, 0x100000000 / 4096> g_pages;