mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 10:21:21 +00:00
sys_rsx: Improve allocations and error checks
* allow sys_rsx_device_map to be called twice: in this case the DEVICE address retrived from the previous call returned * Add ENOMEM checks for sys_rsx_memory_allocate and sys_rsx_context_allocate * add EINVAL check for sys_rsx_context_allocate if memory handle is not found * Separate sys_rsx_device_map allocation from sys_rsx_context_allocate's * Implement sys_rsx_memory_free; used by cellGcmInit upon failure * Added context_id checks * Throw if sys_rsx_context_allocate was called twice.
This commit is contained in:
parent
90aaaceba0
commit
730e9cde84
@ -389,11 +389,9 @@ s32 _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> context, u32
|
||||
gcm_cfg->current_config.coreFrequency = 500000000;
|
||||
|
||||
// Create contexts
|
||||
auto ctx_area = vm::find_map(0x10000000, 0x10000000, 0x403);
|
||||
u32 rsx_ctxaddr = ctx_area ? ctx_area->addr : 0;
|
||||
|
||||
if (!rsx_ctxaddr || vm::falloc(rsx_ctxaddr, 0x400000) != rsx_ctxaddr)
|
||||
fmt::throw_exception("Failed to alloc rsx context.");
|
||||
const auto area = vm::reserve_map(vm::rsx_context, 0, 0x10000000, 0x403);
|
||||
const u32 rsx_ctxaddr = area ? area->alloc(0x400000) : 0;
|
||||
verify(HERE), rsx_ctxaddr != 0;
|
||||
|
||||
g_defaultCommandBufferBegin = ioAddress;
|
||||
g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024);
|
||||
@ -429,7 +427,7 @@ s32 _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> context, u32
|
||||
render->intr_thread->state -= cpu_flag::stop;
|
||||
render->isHLE = true;
|
||||
render->label_addr = gcm_cfg->gcm_info.label_addr;
|
||||
render->ctxt_addr = gcm_cfg->gcm_info.context_addr;
|
||||
render->device_addr = gcm_cfg->gcm_info.context_addr;
|
||||
render->init(gcm_cfg->gcm_info.control_addr - 0x40);
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -68,10 +68,14 @@ error_code sys_rsx_memory_allocate(vm::ptr<u32> mem_handle, vm::ptr<u64> mem_add
|
||||
{
|
||||
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);
|
||||
|
||||
*mem_handle = 0x5a5a5a5b;
|
||||
*mem_addr = vm::falloc(rsx::constants::local_mem_base, size, vm::video);
|
||||
if (u32 addr = vm::falloc(rsx::constants::local_mem_base, size, vm::video))
|
||||
{
|
||||
*mem_addr = addr;
|
||||
*mem_handle = 0x5a5a5a5b;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -80,7 +84,22 @@ error_code sys_rsx_memory_allocate(vm::ptr<u32> mem_handle, vm::ptr<u64> mem_add
|
||||
*/
|
||||
error_code sys_rsx_memory_free(u32 mem_handle)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_memory_free(mem_handle=0x%x)", mem_handle);
|
||||
sys_rsx.warning("sys_rsx_memory_free(mem_handle=0x%x)", mem_handle);
|
||||
|
||||
if (!vm::check_addr(rsx::constants::local_mem_base))
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
if (g_fxo->get<lv2_rsx_config>()->context_base)
|
||||
{
|
||||
fmt::throw_exception("Attempting to dealloc rsx memory when the context is still being used" HERE);
|
||||
}
|
||||
|
||||
if (!vm::dealloc(rsx::constants::local_mem_base))
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -99,18 +118,32 @@ error_code sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u64> lpar_d
|
||||
sys_rsx.warning("sys_rsx_context_allocate(context_id=*0x%x, lpar_dma_control=*0x%x, lpar_driver_info=*0x%x, lpar_reports=*0x%x, mem_ctx=0x%llx, system_mode=0x%llx)",
|
||||
context_id, lpar_dma_control, lpar_driver_info, lpar_reports, mem_ctx, system_mode);
|
||||
|
||||
auto rsx_cfg = g_fxo->get<lv2_rsx_config>();
|
||||
|
||||
if (!rsx_cfg->state)
|
||||
if (!vm::check_addr(rsx::constants::local_mem_base))
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
*context_id = 0x55555555;
|
||||
auto rsx_cfg = g_fxo->get<lv2_rsx_config>();
|
||||
|
||||
*lpar_dma_control = rsx_cfg->rsx_context_addr + 0x100000;
|
||||
*lpar_driver_info = rsx_cfg->rsx_context_addr + 0x200000;
|
||||
*lpar_reports = rsx_cfg->rsx_context_addr + 0x300000;
|
||||
std::lock_guard lock(s_rsxmem_mtx);
|
||||
|
||||
if (rsx_cfg->context_base)
|
||||
{
|
||||
// We currently do not support multiple contexts
|
||||
fmt::throw_exception("sys_rsx_context_allocate was called twice" HERE);
|
||||
}
|
||||
|
||||
const auto area = vm::reserve_map(vm::rsx_context, 0, 0x10000000, 0x403);
|
||||
const u32 context_base = area ? area->alloc(0x300000) : 0;
|
||||
|
||||
if (!context_base)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
*lpar_dma_control = context_base;
|
||||
*lpar_driver_info = context_base + 0x100000;
|
||||
*lpar_reports = context_base + 0x200000;
|
||||
|
||||
auto &reports = vm::_ref<RsxReports>(*lpar_reports);
|
||||
std::memset(&reports, 0, sizeof(RsxReports));
|
||||
@ -147,7 +180,7 @@ error_code sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u64> lpar_d
|
||||
driverInfo.systemModeFlags = system_mode;
|
||||
driverInfo.hardware_channel = 1; // * i think* this 1 for games, 0 for vsh
|
||||
|
||||
rsx_cfg->driverInfo = *lpar_driver_info;
|
||||
rsx_cfg->driver_info = *lpar_driver_info;
|
||||
|
||||
auto &dmaControl = vm::_ref<RsxDmaControl>(*lpar_dma_control);
|
||||
dmaControl.get = 0;
|
||||
@ -175,9 +208,12 @@ error_code sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u64> lpar_d
|
||||
render->display_buffers_count = 0;
|
||||
render->current_display_buffer = 0;
|
||||
render->label_addr = *lpar_reports;
|
||||
render->ctxt_addr = rsx_cfg->rsx_context_addr;
|
||||
render->device_addr = rsx_cfg->device_addr;
|
||||
render->init(*lpar_dma_control);
|
||||
|
||||
rsx_cfg->context_base = context_base;
|
||||
*context_id = 0x55555555;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -189,6 +225,15 @@ error_code sys_rsx_context_free(u32 context_id)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_context_free(context_id=0x%x)", context_id);
|
||||
|
||||
std::scoped_lock lock(s_rsxmem_mtx);
|
||||
|
||||
auto rsx_cfg = g_fxo->get<lv2_rsx_config>();
|
||||
|
||||
if (context_id != 0x55555555 || !rsx_cfg->context_base)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -205,7 +250,7 @@ error_code sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 f
|
||||
sys_rsx.warning("sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx)", context_id, io, ea, size, flags);
|
||||
|
||||
if (!size || io & 0xFFFFF || ea + u64{size} > rsx::constants::local_mem_base || ea & 0xFFFFF || size & 0xFFFFF ||
|
||||
rsx::get_current_renderer()->main_mem_size < io + u64{size})
|
||||
context_id != 0x55555555 || rsx::get_current_renderer()->main_mem_size < io + u64{size})
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -244,7 +289,8 @@ error_code sys_rsx_context_iounmap(u32 context_id, u32 io, u32 size)
|
||||
{
|
||||
sys_rsx.warning("sys_rsx_context_iounmap(context_id=0x%x, io=0x%x, size=0x%x)", context_id, io, size);
|
||||
|
||||
if (!size || size & 0xFFFFF || io & 0xFFFFF || rsx::get_current_renderer()->main_mem_size < io + u64{size})
|
||||
if (!size || size & 0xFFFFF || io & 0xFFFFF || context_id != 0x55555555 ||
|
||||
rsx::get_current_renderer()->main_mem_size < io + u64{size})
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -273,7 +319,7 @@ error_code sys_rsx_context_iounmap(u32 context_id, u32 io, u32 size)
|
||||
* @param a5 (IN):
|
||||
* @param a6 (IN):
|
||||
*/
|
||||
error_code sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6)
|
||||
error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6)
|
||||
{
|
||||
// Flip/queue/reset flip/flip event/user command/vblank as trace to help with log spam
|
||||
if (package_id == 0x102 || package_id == 0x103 || package_id == 0x10a || package_id == 0xFEC || package_id == 0xFED || package_id == 0xFEF)
|
||||
@ -287,12 +333,12 @@ error_code sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64
|
||||
|
||||
auto rsx_cfg = g_fxo->get<lv2_rsx_config>();
|
||||
|
||||
if (!rsx_cfg->state)
|
||||
if (!rsx_cfg->context_base || context_id != 0x55555555)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
auto &driverInfo = vm::_ref<RsxDriverInfo>(rsx_cfg->driverInfo);
|
||||
auto &driverInfo = vm::_ref<RsxDriverInfo>(rsx_cfg->driver_info);
|
||||
switch (package_id)
|
||||
{
|
||||
case 0x001: // FIFO
|
||||
@ -502,7 +548,7 @@ error_code sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64
|
||||
|
||||
case 0xFED: // hack: vblank command
|
||||
// todo: this is wrong and should be 'second' vblank handler and freq, but since currently everything is reported as being 59.94, this should be fine
|
||||
vm::_ref<u32>(render->ctxt_addr + 0x30) = 1;
|
||||
vm::_ref<u32>(render->device_addr + 0x30) = 1;
|
||||
driverInfo.head[a3].vBlankCount++;
|
||||
driverInfo.head[a3].lastSecondVTime = rsxTimeStamp();
|
||||
sys_event_port_send(rsx_cfg->rsx_event_port, 0, (1 << 1), 0);
|
||||
@ -530,7 +576,7 @@ error_code sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64
|
||||
/*
|
||||
* lv2 SysCall 675 (0x2A3): sys_rsx_device_map
|
||||
* @param a1 (OUT): rsx device map address : 0x40000000, 0x50000000.. 0xB0000000
|
||||
* @param a2 (OUT): Unused?
|
||||
* @param a2 (OUT): Unused
|
||||
* @param dev_id (IN): An immediate value and always 8. (cellGcmInitPerfMon uses 11, 10, 9, 7, 12 successively).
|
||||
*/
|
||||
error_code sys_rsx_device_map(vm::ptr<u64> dev_addr, vm::ptr<u64> a2, u32 dev_id)
|
||||
@ -542,25 +588,27 @@ error_code sys_rsx_device_map(vm::ptr<u64> dev_addr, vm::ptr<u64> a2, u32 dev_id
|
||||
fmt::throw_exception("sys_rsx_device_map: Invalid dev_id %d", dev_id);
|
||||
}
|
||||
|
||||
// a2 seems to not be referenced in cellGcmSys, tests show this arg is ignored
|
||||
//*a2 = 0;
|
||||
|
||||
auto rsx_cfg = g_fxo->get<lv2_rsx_config>();
|
||||
|
||||
// TODO
|
||||
if (!rsx_cfg->state.compare_and_swap_test(0, 1))
|
||||
{
|
||||
return CELL_EINVAL; // sys_rsx_device_map called twice
|
||||
}
|
||||
static shared_mutex device_map_mtx;
|
||||
std::scoped_lock lock(device_map_mtx);
|
||||
|
||||
if (const auto area = vm::find_map(0x10000000, 0x10000000, 0x403))
|
||||
if (!rsx_cfg->device_addr)
|
||||
{
|
||||
vm::falloc(area->addr, 0x400000);
|
||||
rsx_cfg->rsx_context_addr = *dev_addr = area->addr;
|
||||
const auto area = vm::reserve_map(vm::rsx_context, 0, 0x10000000, 0x403);
|
||||
const u32 addr = area ? area->alloc(0x100000) : 0;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
rsx_cfg->device_addr = *dev_addr = addr;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_ENOMEM;
|
||||
*dev_addr = rsx_cfg->device_addr;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,6 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
|
||||
@ -105,10 +103,10 @@ struct RsxDisplayInfo
|
||||
|
||||
struct lv2_rsx_config
|
||||
{
|
||||
atomic_t<u32> state = 0;
|
||||
u32 rsx_event_port = 0;
|
||||
u32 driverInfo = 0;
|
||||
u32 rsx_context_addr = 0;
|
||||
u32 rsx_event_port{};
|
||||
u32 context_base{};
|
||||
u32 device_addr{};
|
||||
u32 driver_info{};
|
||||
};
|
||||
|
||||
// SysCalls
|
||||
@ -120,7 +118,7 @@ error_code sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u64> lpar_d
|
||||
error_code sys_rsx_context_free(u32 context_id);
|
||||
error_code sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags);
|
||||
error_code sys_rsx_context_iounmap(u32 context_id, u32 io, u32 size);
|
||||
error_code sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6);
|
||||
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(vm::ptr<u64> dev_addr, vm::ptr<u64> a2, u32 dev_id);
|
||||
error_code sys_rsx_device_unmap(u32 dev_id);
|
||||
error_code sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5);
|
||||
|
@ -1087,6 +1087,7 @@ namespace vm
|
||||
std::make_shared<block_t>(0x00010000, 0x1FFF0000, 0x200), // main
|
||||
std::make_shared<block_t>(0x20000000, 0x10000000, 0x201), // user 64k pages
|
||||
nullptr, // user 1m pages
|
||||
nullptr, // rsx context
|
||||
std::make_shared<block_t>(0xC0000000, 0x10000000), // video
|
||||
std::make_shared<block_t>(0xD0000000, 0x10000000, 0x111), // stack
|
||||
std::make_shared<block_t>(0xE0000000, 0x20000000), // SPU reserved
|
||||
|
@ -22,6 +22,7 @@ namespace vm
|
||||
main,
|
||||
user64k,
|
||||
user1m,
|
||||
rsx_context,
|
||||
video,
|
||||
stack,
|
||||
spu,
|
||||
|
@ -91,10 +91,10 @@ namespace rsx
|
||||
return get_current_renderer()->label_addr + offset;
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_DEVICE_RW:
|
||||
return get_current_renderer()->ctxt_addr + offset;
|
||||
return get_current_renderer()->device_addr + offset;
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_DEVICE_R:
|
||||
return get_current_renderer()->ctxt_addr + offset;
|
||||
return get_current_renderer()->device_addr + offset;
|
||||
|
||||
default:
|
||||
{
|
||||
|
@ -564,7 +564,7 @@ namespace rsx
|
||||
RsxDisplayInfo display_buffers[8];
|
||||
u32 display_buffers_count{0};
|
||||
u32 current_display_buffer{0};
|
||||
u32 ctxt_addr;
|
||||
u32 device_addr;
|
||||
u32 label_addr;
|
||||
|
||||
u32 main_mem_size{0};
|
||||
|
@ -74,7 +74,7 @@ namespace rsx
|
||||
const auto& sema = vm::_ref<atomic_be_t<u32>>(addr);
|
||||
|
||||
// TODO: Remove vblank semaphore hack
|
||||
if (sema == arg || addr == rsx->ctxt_addr + 0x30) return;
|
||||
if (sema == arg || addr == rsx->device_addr + 0x30) return;
|
||||
|
||||
rsx->flush_fifo();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user