Merge branch 'shadps4-emu:main' into mapmemory-assert-remove

This commit is contained in:
Stephen Miller 2025-05-12 13:40:06 -05:00 committed by GitHub
commit 582766f78e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 176 additions and 10 deletions

View File

@ -481,6 +481,59 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags)
return memory->PoolDecommit(pool_addr, len);
}
s32 PS4_SYSV_ABI sceKernelMemoryPoolBatch(const OrbisKernelMemoryPoolBatchEntry* entries, s32 count,
s32* num_processed, s32 flags) {
if (entries == nullptr) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
s32 result = ORBIS_OK;
s32 processed = 0;
for (s32 i = 0; i < count; i++, processed++) {
OrbisKernelMemoryPoolBatchEntry entry = entries[i];
switch (entry.opcode) {
case OrbisKernelMemoryPoolOpcode::Commit: {
result = sceKernelMemoryPoolCommit(entry.commit_params.addr, entry.commit_params.len,
entry.commit_params.type, entry.commit_params.prot,
entry.flags);
break;
}
case OrbisKernelMemoryPoolOpcode::Decommit: {
result = sceKernelMemoryPoolDecommit(entry.decommit_params.addr,
entry.decommit_params.len, entry.flags);
break;
}
case OrbisKernelMemoryPoolOpcode::Protect: {
result = sceKernelMProtect(entry.protect_params.addr, entry.protect_params.len,
entry.protect_params.prot);
break;
}
case OrbisKernelMemoryPoolOpcode::TypeProtect: {
result = sceKernelMTypeProtect(
entry.type_protect_params.addr, entry.type_protect_params.len,
entry.type_protect_params.type, entry.type_protect_params.prot);
break;
}
case OrbisKernelMemoryPoolOpcode::Move: {
UNREACHABLE_MSG("Unimplemented sceKernelMemoryPoolBatch opcode Move");
}
default: {
result = ORBIS_KERNEL_ERROR_EINVAL;
break;
}
}
if (result != ORBIS_OK) {
break;
}
}
if (num_processed != nullptr) {
*num_processed = processed;
}
return result;
}
int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset,
void** res) {
LOG_INFO(Kernel_Vmm, "called addr = {}, len = {}, prot = {}, flags = {}, fd = {}, offset = {}",
@ -612,6 +665,7 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("pU-QydtGcGY", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolReserve);
LIB_FUNCTION("Vzl66WmfLvk", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolCommit);
LIB_FUNCTION("LXo1tpFqJGs", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolDecommit);
LIB_FUNCTION("YN878uKRBbE", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolBatch);
LIB_FUNCTION("BPE9s9vQQXo", "libkernel", 1, "libkernel", 1, 1, posix_mmap);
LIB_FUNCTION("BPE9s9vQQXo", "libScePosix", 1, "libkernel", 1, 1, posix_mmap);

View File

@ -81,6 +81,48 @@ struct OrbisKernelBatchMapEntry {
int operation;
};
enum class OrbisKernelMemoryPoolOpcode : u32 {
Commit = 1,
Decommit = 2,
Protect = 3,
TypeProtect = 4,
Move = 5,
};
struct OrbisKernelMemoryPoolBatchEntry {
OrbisKernelMemoryPoolOpcode opcode;
u32 flags;
union {
struct {
void* addr;
u64 len;
u8 prot;
u8 type;
} commit_params;
struct {
void* addr;
u64 len;
} decommit_params;
struct {
void* addr;
u64 len;
u8 prot;
} protect_params;
struct {
void* addr;
u64 len;
u8 prot;
u8 type;
} type_protect_params;
struct {
void* dest_addr;
void* src_addr;
u64 len;
} move_params;
uintptr_t padding[3];
};
};
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize();
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
u64 alignment, int memoryType, s64* physAddrOut);
@ -130,6 +172,8 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t ali
void** addrOut);
s32 PS4_SYSV_ABI sceKernelMemoryPoolCommit(void* addr, size_t len, int type, int prot, int flags);
s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags);
s32 PS4_SYSV_ABI sceKernelMemoryPoolBatch(const OrbisKernelMemoryPoolBatchEntry* entries, s32 count,
s32* num_processed, s32 flags);
int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len);

View File

@ -17,6 +17,12 @@ int PS4_SYSV_ABI posix_pthread_attr_init(PthreadAttrT* attr);
int PS4_SYSV_ABI posix_pthread_attr_destroy(PthreadAttrT* attr);
int PS4_SYSV_ABI posix_pthread_attr_getaffinity_np(const PthreadAttrT* pattr, size_t cpusetsize,
Cpuset* cpusetp);
int PS4_SYSV_ABI posix_pthread_attr_setaffinity_np(PthreadAttrT* pattr, size_t cpusetsize,
const Cpuset* cpusetp);
int PS4_SYSV_ABI posix_pthread_create(PthreadT* thread, const PthreadAttrT* attr,
PthreadEntryFunc start_routine, void* arg);
@ -35,7 +41,7 @@ public:
this->func = std::move(func);
PthreadAttrT attr{};
posix_pthread_attr_init(&attr);
posix_pthread_create(&thread, &attr, RunWrapper, this);
posix_pthread_create(&thread, &attr, HOST_CALL(RunWrapper), this);
posix_pthread_attr_destroy(&attr);
}

View File

@ -6,6 +6,7 @@
#include "core/debug_state.h"
#include "core/libraries/kernel/kernel.h"
#include "core/libraries/kernel/posix_error.h"
#include "core/libraries/kernel/threads.h"
#include "core/libraries/kernel/threads/pthread.h"
#include "core/libraries/kernel/threads/thread_state.h"
#include "core/libraries/libs.h"
@ -535,8 +536,6 @@ int Pthread::SetAffinity(const Cpuset* cpuset) {
return POSIX_EINVAL;
}
u64 mask = cpuset->bits;
uintptr_t handle = native_thr.GetHandle();
if (handle == 0) {
return POSIX_ESRCH;
@ -545,6 +544,7 @@ int Pthread::SetAffinity(const Cpuset* cpuset) {
// We don't use this currently because some games gets performance problems
// when applying affinity even on strong hardware
/*
u64 mask = cpuset->bits;
#ifdef _WIN64
DWORD_PTR affinity_mask = static_cast<DWORD_PTR>(mask);
if (!SetThreadAffinityMask(reinterpret_cast<HANDLE>(handle), affinity_mask)) {
@ -572,13 +572,33 @@ int Pthread::SetAffinity(const Cpuset* cpuset) {
return 0;
}
int PS4_SYSV_ABI posix_pthread_getaffinity_np(PthreadT thread, size_t cpusetsize, Cpuset* cpusetp) {
if (thread == nullptr || cpusetp == nullptr) {
return POSIX_EINVAL;
}
auto* attr_ptr = &thread->attr;
return posix_pthread_attr_getaffinity_np(&attr_ptr, cpusetsize, cpusetp);
}
int PS4_SYSV_ABI posix_pthread_setaffinity_np(PthreadT thread, size_t cpusetsize,
const Cpuset* cpusetp) {
if (thread == nullptr || cpusetp == nullptr) {
return POSIX_EINVAL;
}
thread->attr.cpusetsize = cpusetsize;
return thread->SetAffinity(cpusetp);
auto* attr_ptr = &thread->attr;
if (const auto ret = posix_pthread_attr_setaffinity_np(&attr_ptr, cpusetsize, cpusetp)) {
return ret;
}
return thread->SetAffinity(thread->attr.cpuset);
}
int PS4_SYSV_ABI scePthreadGetaffinity(PthreadT thread, u64* mask) {
Cpuset cpuset;
const int ret = posix_pthread_getaffinity_np(thread, sizeof(Cpuset), &cpuset);
if (ret == 0) {
*mask = cpuset.bits;
}
return ret;
}
int PS4_SYSV_ABI scePthreadSetaffinity(PthreadT thread, const u64 mask) {
@ -609,6 +629,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_once);
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_create);
LIB_FUNCTION("Jb2uGFMr688", "libkernel", 1, "libkernel", 1, 1, posix_pthread_getaffinity_np);
LIB_FUNCTION("5KWrg7-ZqvE", "libkernel", 1, "libkernel", 1, 1, posix_pthread_setaffinity_np);
// Orbis
@ -632,6 +653,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_setprio));
LIB_FUNCTION("rNhWz+lvOMU", "libkernel", 1, "libkernel", 1, 1, _sceKernelSetThreadDtors);
LIB_FUNCTION("6XG4B33N09g", "libkernel", 1, "libkernel", 1, 1, sched_yield);
LIB_FUNCTION("rcrVFJsQWRY", "libkernel", 1, "libkernel", 1, 1, ORBIS(scePthreadGetaffinity));
LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, ORBIS(scePthreadSetaffinity));
}

View File

@ -268,13 +268,13 @@ int PS4_SYSV_ABI posix_pthread_attr_setaffinity_np(PthreadAttrT* pattr, size_t c
attr->cpuset = static_cast<Cpuset*>(calloc(1, sizeof(Cpuset)));
attr->cpusetsize = sizeof(Cpuset);
}
memcpy(attr->cpuset, cpusetp, cpusetsize);
memcpy(attr->cpuset, cpusetp, std::min(cpusetsize, sizeof(Cpuset)));
return 0;
}
int PS4_SYSV_ABI scePthreadAttrGetaffinity(PthreadAttrT* param_1, u64* mask) {
int PS4_SYSV_ABI scePthreadAttrGetaffinity(PthreadAttrT* attr, u64* mask) {
Cpuset cpuset;
const int ret = posix_pthread_attr_getaffinity_np(param_1, sizeof(Cpuset), &cpuset);
const int ret = posix_pthread_attr_getaffinity_np(attr, sizeof(Cpuset), &cpuset);
if (ret == 0) {
*mask = cpuset.bits;
}

View File

@ -5,6 +5,7 @@
#include "core/loader/elf.h"
#include "core/loader/symbols_resolver.h"
#include "core/tls.h"
#define LIB_FUNCTION(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \
{ \
@ -16,7 +17,7 @@
sr.module_version_major = moduleVersionMajor; \
sr.module_version_minor = moduleVersionMinor; \
sr.type = Core::Loader::SymbolType::Function; \
auto func = reinterpret_cast<u64>(function); \
auto func = reinterpret_cast<u64>(HOST_CALL(function)); \
sym->AddSymbol(sr, func); \
}

View File

@ -58,4 +58,16 @@ ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&
return func(std::forward<CallArgs>(args)...);
}
template <class F, F f>
struct HostCallWrapperImpl;
template <class ReturnType, class... Args, PS4_SYSV_ABI ReturnType (*func)(Args...)>
struct HostCallWrapperImpl<PS4_SYSV_ABI ReturnType (*)(Args...), func> {
static ReturnType PS4_SYSV_ABI wrap(Args... args) {
return func(args...);
}
};
#define HOST_CALL(func) (Core::HostCallWrapperImpl<decltype(&(func)), func>::wrap)
} // namespace Core

View File

@ -62,7 +62,14 @@ struct BufferResource {
}
bool IsStorage(const AmdGpu::Buffer& buffer, const Profile& profile) const noexcept {
return buffer.GetSize() > profile.max_ubo_size || is_written;
// When using uniform buffers, a size is required at compilation time, so we need to
// either compile a lot of shader specializations to handle each size or just force it to
// the maximum possible size always. However, for some vendors the shader-supplied size is
// used for bounds checking uniform buffer accesses, so the latter would effectively turn
// off buffer robustness behavior. Instead, force storage buffers which are bounds checked
// using the actual buffer size. We are assuming the performance hit from this is
// acceptable.
return true; // buffer.GetSize() > profile.max_ubo_size || is_written;
}
[[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept;

View File

@ -864,6 +864,11 @@ Liverpool::Task Liverpool::ProcessCompute(const u32* acb, u32 acb_dwords, u32 vq
}
break;
}
case PM4ItOpcode::SetQueueReg: {
const auto* set_data = reinterpret_cast<const PM4CmdSetQueueReg*>(header);
UNREACHABLE_MSG("Encountered compute SetQueueReg: vqid = {}, reg_offset = {:#x}",
set_data->vqid.Value(), set_data->reg_offset.Value());
}
case PM4ItOpcode::DispatchDirect: {
const auto* dispatch_direct = reinterpret_cast<const PM4CmdDispatchDirect*>(header);
auto& cs_program = GetCsRegs();

View File

@ -211,6 +211,21 @@ struct PM4CmdSetData {
}
};
struct PM4CmdSetQueueReg {
PM4Type3Header header;
union {
u32 raw;
BitField<0, 8, u32> reg_offset; ///< Offset in DWords from the register base address
BitField<15, 1, u32> defer_exec; ///< Defer execution
BitField<16, 10, u32> vqid; ///< Queue ID
};
u32 data[0];
[[nodiscard]] u32 Size() const {
return header.count << 2u;
}
};
struct PM4CmdNop {
PM4Type3Header header;
u32 data_block[0];