feat(libkernel): accept the audio coprocessor memory protection bits
A title maps direct memory with protection 0x3f2, which adds bits 0x100 and 0x200 to the CPU, GPU and AMPR bits, and the mapping threw. They are the audio coprocessor (ACP) read and write bits, as named in the KytyPS5 and etaHEN headers. The coprocessor work runs on the host CPU, so they map to host read and read/write access like the GPU bits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9ab937b261
commit
b567bb8eed
|
|
@ -194,13 +194,13 @@ void ValidateRange(const void* addr, size_t len, size_t alignment) {
|
|||
}
|
||||
|
||||
int LinuxProtFromSce(int prot) {
|
||||
if ((prot & ~0xF7) != 0) {
|
||||
if ((prot & ~0x3F7) != 0) {
|
||||
// return SCE_KERNEL_ERROR_EINVAL;
|
||||
throw std::invalid_argument("Unsupported memory protection bits: " + std::to_string(prot));
|
||||
}
|
||||
int result = PROT_NONE;
|
||||
if (prot & 0x13) result |= PROT_READ;
|
||||
if (prot & 0x22) result |= PROT_READ | PROT_WRITE;
|
||||
if (prot & 0x113) result |= PROT_READ;
|
||||
if (prot & 0x222) result |= PROT_READ | PROT_WRITE;
|
||||
if (prot & 4) result |= PROT_READ | PROT_EXEC;
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,6 +125,23 @@ static void CheckNamedAndHintedMappings() {
|
|||
Require(sceKernelMunmap(first, length) == 0);
|
||||
}
|
||||
|
||||
static void CheckAudioCoprocessorProtection() {
|
||||
constexpr std::size_t length = 0x4000;
|
||||
void* writable = nullptr;
|
||||
Require(sceKernelMapFlexibleMemory(&writable, length, 0x200, 0) == 0);
|
||||
static_cast<volatile unsigned char*>(writable)[length - 1] = 7;
|
||||
Require(static_cast<volatile unsigned char*>(writable)[length - 1] == 7);
|
||||
Require(sceKernelMprotect(writable, length, 0x100) == 0);
|
||||
Require(static_cast<volatile unsigned char*>(writable)[length - 1] == 7);
|
||||
Require(sceKernelMprotect(writable, length, 0x3f2) == 0);
|
||||
static_cast<volatile unsigned char*>(writable)[0] = 9;
|
||||
Require(sceKernelMunmap(writable, length) == 0);
|
||||
bool rejected = false;
|
||||
void* undefined = nullptr;
|
||||
try { sceKernelMapFlexibleMemory(&undefined, length, 0x400, 0); } catch (const std::invalid_argument&) { rejected = true; }
|
||||
Require(rejected && undefined == nullptr);
|
||||
}
|
||||
|
||||
static void CheckInternalNamedFlexibleMapping() {
|
||||
constexpr std::size_t length = 0x10000;
|
||||
std::size_t before = 0;
|
||||
|
|
@ -921,6 +938,7 @@ int main() {
|
|||
CheckInternalNamedFlexibleMapping();
|
||||
CheckBatchMapStopsAtInvalidEntry();
|
||||
CheckCheckedReleaseDirectMemory();
|
||||
CheckAudioCoprocessorProtection();
|
||||
CheckDirectMemoryFollowsPhysicalPages();
|
||||
CheckReleaseDirectMemoryClearsMappings();
|
||||
CheckFixedVirtualReservation();
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [sceKernelInternalMemoryGetModuleSegmentInfo](../../core/libs/prx/libkernel/Module/src/Module.cpp) (libkernel) - unknown signature
|
||||
- [sceKernelGetModuleInfoFromAddr](../../core/libs/prx/libkernel/Module/src/ModuleInfo.cpp) (libkernel) - the 0x1A8-byte info layout follows the [shadPS4](https://github.com/shadps4-emu/shadPS4) reimplementation; a title's `libc.prx` reads only `id` (PPSA14632). The meaning of `flags` is unknown; only 2 is accepted, as is only the full `st_size`. The id is the `sceKernelLoadStartModule` handle of an image opened through the loader and otherwise a stable id from the same range. The name is the host file name without `.guest.prx`. An image with more than 4 load segments (the converted executable has 7) reports its first 4. `tls_offset` is 0 and `ref_count` is 1, as the host loader exposes neither. Not implemented on Windows
|
||||
- [sceKernelReleaseFlexibleMemory](../../core/libs/prx/libkernel/DirectMemory/Export.cpp) (libkernel) - unmaps the range like sceKernelMunmap, as fpPS4 and prosper do; whether the console keeps the virtual range reserved after releasing its pages is unverified
|
||||
- [Memory protection bits 0x100 and 0x200](../../core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp) (libkernel) - taken as audio coprocessor (ACP) read and write, as in the [KytyPS5](https://github.com/KytyPS5/KytyPS5) and [etaHEN](https://github.com/etaHEN/etaHEN) headers; the coprocessor work runs on the host CPU, so they grant host read and read/write access like the GPU bits
|
||||
- [sceKernelSyncOnAddressWait](../../core/libs/prx/libkernel/SyncOnAddress/src/SyncOnAddress.cpp) (libkernel) - the only known caller passes a null timeout and a name string as the fourth argument; the timeout is assumed to point to microseconds like the other kernel waits, and the name is ignored
|
||||
- [sceKernelSyncOnAddressWait8 / sceKernelSyncOnAddressWait16 / sceKernelSyncOnAddressWait32 / sceKernelSyncOnAddressWait64](../../core/libs/prx/libkernel/SyncOnAddress/src/SyncOnAddress.cpp) (libkernel) - libc's `__std_atomic_wait_direct_8/16/32/64` pass a microsecond timeout or null and ignore the result; the by-value comparand, return values and the 2- and 8-byte alignment of Wait16 and Wait64 are assumed
|
||||
- [sceKernelAioSubmitReadCommandsMultiple / sceKernelAioSubmitWriteCommandsMultiple / sceKernelAioWaitRequests / sceKernelAioCancelRequest / sceKernelAioCancelRequests / sceKernelAioDeleteRequests](../../core/libs/prx/libkernel/Aio/src/Aio.cpp) (libkernel) - behaviour from shadPS4 (one id per request for the Multiple submits, cancel turns any request aborted and id 0 reports processing, wait mode 2 returns once one request completed); the 128 requests or ids per batch limit is from SharpProspero, with an unknown error, so larger batches throw; wait modes other than 1 (and) and 2 (or) throw; null pointers, negative counts and invalid ids return the codes the single-request siblings use, checked before any state is written
|
||||
|
|
|
|||
Loading…
Reference in New Issue