mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-29 00:33:01 +00:00
Implements sys_fs_fcntl 0xC0000008 & 0xC000001A (#11957)
This commit is contained in:
parent
a2623b1a9a
commit
da6434a65a
@ -1850,7 +1850,7 @@ bool ppu_load_exec(const ppu_exec_object& elf)
|
||||
g_fxo->init<lv2_memory_container>(mem_size);
|
||||
}
|
||||
|
||||
g_fxo->get<lv2_memory_container>().used += primary_stacksize;
|
||||
ensure(g_fxo->get<lv2_memory_container>().take(primary_stacksize));
|
||||
|
||||
ppu->cmd_push({ppu_cmd::initialize, 0});
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "sys_sync.h"
|
||||
#include "sys_fs.h"
|
||||
#include "sys_memory.h"
|
||||
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
@ -865,6 +866,22 @@ error_code sys_fs_close(ppu_thread& ppu, u32 fd)
|
||||
sys_fs.warning("%s: %s", FD_state_log, *file);
|
||||
}
|
||||
|
||||
// Free memory associated with fd if any
|
||||
if (file->ct_id && file->ct_used)
|
||||
{
|
||||
auto& default_container = g_fxo->get<default_sys_fs_container>();
|
||||
std::lock_guard lock(default_container.mutex);
|
||||
|
||||
if (auto ct = idm::get<lv2_memory_container>(file->ct_id))
|
||||
{
|
||||
ct->free(file->ct_used);
|
||||
if (default_container.id == file->ct_id)
|
||||
{
|
||||
default_container.used -= file->ct_used;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure Host file handle won't be kept open after this syscall
|
||||
file->file.close();
|
||||
}
|
||||
@ -1653,7 +1670,7 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||
|
||||
case 0xc0000007: // cellFsArcadeHddSerialNumber
|
||||
{
|
||||
const auto arg = vm::static_ptr_cast<lv2_file_c000007>(_arg);
|
||||
const auto arg = vm::static_ptr_cast<lv2_file_c0000007>(_arg);
|
||||
// TODO populate arg-> unk1+2
|
||||
arg->out_code = CELL_OK;
|
||||
return CELL_OK;
|
||||
@ -1661,7 +1678,86 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||
|
||||
case 0xc0000008: // cellFsSetDefaultContainer, cellFsSetIoBuffer, cellFsSetIoBufferFromDefaultContainer
|
||||
{
|
||||
break;
|
||||
// Allocates memory from a container/default container to a specific fd or default IO processing
|
||||
const auto arg = vm::static_ptr_cast<lv2_file_c0000008>(_arg);
|
||||
auto& default_container = g_fxo->get<default_sys_fs_container>();
|
||||
|
||||
std::lock_guard def_container_lock(default_container.mutex);
|
||||
|
||||
if (fd == 0xFFFFFFFF)
|
||||
{
|
||||
// No check on container is done when setting default container
|
||||
default_container.id = arg->size ? ::narrow<u32>(arg->container_id) : 0u;
|
||||
default_container.cap = arg->size;
|
||||
default_container.used = 0;
|
||||
|
||||
arg->out_code = CELL_OK;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
auto file = idm::get<lv2_fs_object, lv2_file>(fd);
|
||||
if (!file)
|
||||
{
|
||||
return CELL_EBADF;
|
||||
}
|
||||
|
||||
if (auto ct = idm::get<lv2_memory_container>(file->ct_id))
|
||||
{
|
||||
ct->free(file->ct_used);
|
||||
if (default_container.id == file->ct_id)
|
||||
{
|
||||
default_container.used -= file->ct_used;
|
||||
}
|
||||
}
|
||||
|
||||
file->ct_id = 0;
|
||||
file->ct_used = 0;
|
||||
|
||||
// Aligns on lower bound
|
||||
u32 actual_size = arg->size - (arg->size % ((arg->page_type & CELL_FS_IO_BUFFER_PAGE_SIZE_64KB) ? 0x10000 : 0x100000));
|
||||
|
||||
if (!actual_size)
|
||||
{
|
||||
arg->out_code = CELL_OK;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
u32 new_container_id = arg->container_id == 0xFFFFFFFF ? default_container.id : ::narrow<u32>(arg->container_id);
|
||||
if (default_container.id == new_container_id && (default_container.used + actual_size) > default_container.cap)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
const auto ct = idm::get<lv2_memory_container>(new_container_id, [&](lv2_memory_container& ct) -> CellError
|
||||
{
|
||||
if (!ct.take(actual_size))
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
return {};
|
||||
});
|
||||
|
||||
if (!ct)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (ct.ret)
|
||||
{
|
||||
return ct.ret;
|
||||
}
|
||||
|
||||
if (default_container.id == new_container_id)
|
||||
{
|
||||
default_container.used += actual_size;
|
||||
}
|
||||
|
||||
file->ct_id = new_container_id;
|
||||
file->ct_used = actual_size;
|
||||
|
||||
arg->out_code = CELL_OK;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
case 0xc0000015: // USB Vid/Pid lookup - Used by arcade games on dev_usbXXX
|
||||
@ -1735,7 +1831,8 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||
|
||||
case 0xc000001a: // cellFsSetDiscReadRetrySetting, 5731DF45
|
||||
{
|
||||
break;
|
||||
[[maybe_unused]] const auto arg = vm::static_ptr_cast<lv2_file_c000001a>(_arg);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
case 0xc000001c: // USB Vid/Pid/Serial lookup
|
||||
|
@ -67,6 +67,12 @@ enum : u8
|
||||
CELL_FS_TYPE_SYMLINK = 3,
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
CELL_FS_IO_BUFFER_PAGE_SIZE_64KB = 0x0002,
|
||||
CELL_FS_IO_BUFFER_PAGE_SIZE_1MB = 0x0004,
|
||||
};
|
||||
|
||||
struct CellFsDirent
|
||||
{
|
||||
u8 d_type;
|
||||
@ -203,6 +209,9 @@ struct lv2_file final : lv2_fs_object
|
||||
std::string real_path;
|
||||
const lv2_file_type type;
|
||||
|
||||
// IO Container
|
||||
u32 ct_id{}, ct_used{};
|
||||
|
||||
// Stream lock
|
||||
atomic_t<u32> lock{0};
|
||||
|
||||
@ -435,7 +444,7 @@ struct lv2_file_c0000006 : lv2_file_op
|
||||
|
||||
CHECK_SIZE(lv2_file_c0000006, 0x20);
|
||||
|
||||
struct lv2_file_c000007 : lv2_file_op
|
||||
struct lv2_file_c0000007 : lv2_file_op
|
||||
{
|
||||
be_t<u32> out_code;
|
||||
vm::bcptr<char> name;
|
||||
@ -446,7 +455,24 @@ struct lv2_file_c000007 : lv2_file_op
|
||||
be_t<u32> unk2_size; //0x21
|
||||
};
|
||||
|
||||
CHECK_SIZE(lv2_file_c000007, 0x1c);
|
||||
CHECK_SIZE(lv2_file_c0000007, 0x1c);
|
||||
|
||||
struct lv2_file_c0000008 : lv2_file_op
|
||||
{
|
||||
u8 _x0[4];
|
||||
be_t<u32> op; // 0xC0000008
|
||||
u8 _x8[8];
|
||||
be_t<u64> container_id;
|
||||
be_t<u32> size;
|
||||
be_t<u32> page_type; // 0x4000 for cellFsSetDefaultContainer
|
||||
// 0x4000 | page_type given by user, valid values seem to be:
|
||||
// CELL_FS_IO_BUFFER_PAGE_SIZE_64KB 0x0002
|
||||
// CELL_FS_IO_BUFFER_PAGE_SIZE_1MB 0x0004
|
||||
be_t<u32> out_code;
|
||||
u8 _x24[4];
|
||||
};
|
||||
|
||||
CHECK_SIZE(lv2_file_c0000008, 0x28);
|
||||
|
||||
struct lv2_file_c0000015 : lv2_file_op
|
||||
{
|
||||
@ -463,6 +489,19 @@ struct lv2_file_c0000015 : lv2_file_op
|
||||
|
||||
CHECK_SIZE(lv2_file_c0000015, 0x20);
|
||||
|
||||
struct lv2_file_c000001a : lv2_file_op
|
||||
{
|
||||
be_t<u32> disc_retry_type; // CELL_FS_DISC_READ_RETRY_NONE results in a 0 here
|
||||
// CELL_FS_DISC_READ_RETRY_DEFAULT results in a 0x63 here
|
||||
be_t<u32> _x4; // 0
|
||||
be_t<u32> _x8; // 0x000186A0
|
||||
be_t<u32> _xC; // 0
|
||||
be_t<u32> _x10; // 0
|
||||
be_t<u32> _x14; // 0
|
||||
};
|
||||
|
||||
CHECK_SIZE(lv2_file_c000001a, 0x18);
|
||||
|
||||
struct lv2_file_c000001c : lv2_file_op
|
||||
{
|
||||
be_t<u32> size; // 0x20
|
||||
@ -507,6 +546,18 @@ struct CellFsMountInfo
|
||||
|
||||
CHECK_SIZE(CellFsMountInfo, 0x94);
|
||||
|
||||
// Default IO container
|
||||
struct default_sys_fs_container
|
||||
{
|
||||
default_sys_fs_container(const default_sys_fs_container&) = delete;
|
||||
default_sys_fs_container& operator=(const default_sys_fs_container&) = delete;
|
||||
|
||||
shared_mutex mutex;
|
||||
u32 id = 0;
|
||||
u32 cap = 0;
|
||||
u32 used = 0;
|
||||
};
|
||||
|
||||
// Syscalls
|
||||
|
||||
error_code sys_fs_test(ppu_thread& ppu, u32 arg1, u32 arg2, vm::ptr<u32> arg3, u32 arg4, vm::ptr<char> buf, u32 buf_size);
|
||||
|
@ -83,7 +83,7 @@ error_code sys_memory_allocate(cpu_thread& cpu, u32 size, u64 flags, vm::ptr<u32
|
||||
}
|
||||
}
|
||||
|
||||
dct.used -= size;
|
||||
dct.free(size);
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ error_code sys_memory_allocate_from_container(cpu_thread& cpu, u32 size, u32 cid
|
||||
}
|
||||
}
|
||||
|
||||
ct->used -= size;
|
||||
ct->free(size);
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ error_code sys_memory_free(cpu_thread& cpu, u32 addr)
|
||||
}
|
||||
|
||||
const auto size = (ensure(vm::dealloc(addr)));
|
||||
reader_lock{id_manager::g_mutex}, ct->used -= size;
|
||||
reader_lock{id_manager::g_mutex}, ct->free(size);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ error_code sys_memory_container_create(cpu_thread& cpu, vm::ptr<u32> cid, u32 si
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
dct.used -= size;
|
||||
dct.free(size);
|
||||
return CELL_EAGAIN;
|
||||
}
|
||||
|
||||
@ -311,7 +311,7 @@ error_code sys_memory_container_destroy(cpu_thread& cpu, u32 cid)
|
||||
}
|
||||
|
||||
// Return "physical memory" to the default container
|
||||
g_fxo->get<lv2_memory_container>().used -= ct->size;
|
||||
g_fxo->get<lv2_memory_container>().free(ct->size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -89,6 +89,25 @@ struct lv2_memory_container
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 free(u64 amount)
|
||||
{
|
||||
auto [_, result] = used.fetch_op([&](u32& value) -> u32
|
||||
{
|
||||
if (value >= amount)
|
||||
{
|
||||
value -= static_cast<u32>(amount);
|
||||
return static_cast<u32>(amount);
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Sanity check
|
||||
ensure(result == amount);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct sys_memory_user_memory_stat_t
|
||||
|
@ -529,7 +529,7 @@ error_code sys_mmapper_free_shared_memory(ppu_thread& ppu, u32 mem_id)
|
||||
if (!mem.exists)
|
||||
{
|
||||
// Return "physical memory" to the memory container
|
||||
mem.ct->used -= mem.size;
|
||||
mem.ct->free(mem.size);
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -45,7 +45,7 @@ void ppu_thread_exit(ppu_thread& ppu, ppu_opcode_t, be_t<u32>*, struct ppu_intrp
|
||||
|
||||
if (auto& dct = g_fxo->get<lv2_memory_container>(); !Emu.IsStopped())
|
||||
{
|
||||
dct.used -= ppu.stack_size;
|
||||
dct.free(ppu.stack_size);
|
||||
}
|
||||
|
||||
if (ppu.call_history.index)
|
||||
@ -418,7 +418,7 @@ error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::p
|
||||
|
||||
if (!stack_base)
|
||||
{
|
||||
dct.used -= stack_size;
|
||||
dct.free(stack_size);
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
@ -447,7 +447,7 @@ error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::p
|
||||
if (!tid)
|
||||
{
|
||||
vm::dealloc(stack_base);
|
||||
dct.used -= stack_size;
|
||||
dct.free(stack_size);
|
||||
return CELL_EAGAIN;
|
||||
}
|
||||
|
||||
|
@ -780,7 +780,7 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||
|
||||
if (!limits.check(use_scheduler ? limits_data{.controllable = num} : limits_data{.physical = num}))
|
||||
{
|
||||
ct->used -= mem_size;
|
||||
ct->free(mem_size);
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
@ -788,7 +788,7 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||
|
||||
if (!group)
|
||||
{
|
||||
ct->used -= mem_size;
|
||||
ct->free(mem_size);
|
||||
return CELL_EAGAIN;
|
||||
}
|
||||
|
||||
@ -823,7 +823,7 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id)
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
group.ct->used -= group.mem_size;
|
||||
group.ct->free(group.mem_size);
|
||||
return {};
|
||||
});
|
||||
|
||||
|
@ -85,7 +85,7 @@ error_code sys_vm_memory_map(ppu_thread& ppu, u32 vsize, u32 psize, u32 cid, u64
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
ct->used -= psize;
|
||||
ct->free(psize);
|
||||
g_fxo->get<sys_vm_global_t>().total_vsize -= vsize;
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
@ -119,7 +119,7 @@ error_code sys_vm_unmap(ppu_thread& ppu, u32 addr)
|
||||
ensure(vm::unmap(addr).second);
|
||||
|
||||
// Return memory
|
||||
vmo.ct->used -= vmo.psize;
|
||||
vmo.ct->free(vmo.psize);
|
||||
g_fxo->get<sys_vm_global_t>().total_vsize -= vmo.size;
|
||||
});
|
||||
|
||||
@ -205,7 +205,7 @@ error_code sys_vm_return_memory(ppu_thread& ppu, u32 addr, u32 size)
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
vmo.ct->used -= size;
|
||||
vmo.ct->free(size);
|
||||
return {};
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user