ME: Let kernel code on the main CPU reach RAM and VRAM through kseg1

Yabause-PSP's me.prx ORs 0xA0000000 onto its own addresses to share a
buffer with the ME uncached, which is 0xA8xxxxxx for a module in kernel
RAM. The main CPU's space has no views there, so it crashed.

All of kernel segment 1 (0xA0000000-0xBFFFFFFF) now counts as MMIO, and a
device below the hardware registers maps RAM and VRAM onto their uncached
mirrors at 0x40000000. The main CPU's native kernel loads and stores send
the whole segment to that path; the ME keeps 0xBC000000 as the boundary,
since its space maps the rest.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-21 12:50:46 +02:00
1 parent e906b9f700
commit 657e99fcbf
4 files changed
+54 -7

No files matched your search

+9 -3
View File
@@ -411,7 +411,8 @@ void Arm64JitBackend::CompIR_LoadShift(IRInst inst) {
}
// Memory directly, or through the fixed code for a hardware register (0xBC000000-0xBFFFFFFF), where
// the address may also be one the CPU has no memory at.
// the address may also be one the CPU has no memory at. The main CPU has no views anywhere in kernel
// segment 1 (0xA0000000-0xBFFFFFFF), so all of it goes there (see Memory::IsMMIOAccess).
void Arm64JitBackend::CompIR_KernelLoadStore(IRInst inst) {
CONDITIONAL_DISABLE;
@@ -420,8 +421,13 @@ void Arm64JitBackend::CompIR_KernelLoadStore(IRInst inst) {
ADDI2R(SCRATCH1, regs_.R(inst.src1), inst.constant, SCRATCH2);
const ARM64Reg reg = isStore ? regs_.R(inst.src3) : regs_.R(inst.dest);
LSR(SCRATCH2, SCRATCH1, 26);
CMPI2R(SCRATCH2, 0xBC000000 >> 26);
if (mips_->IsMediaEngine()) {
LSR(SCRATCH2, SCRATCH1, 26);
CMPI2R(SCRATCH2, 0xBC000000 >> 26);
} else {
LSR(SCRATCH2, SCRATCH1, 29);
CMPI2R(SCRATCH2, 0xA0000000 >> 29);
}
FixupBranch memory = B(CC_NEQ);
if (isStore)
MOV(SCRATCH2, reg);