On Windows the guest arena ended at 0x72_0000_0000: #231 kept its
448 GiB size after #153 had moved its start down to 0x2_0000_0000.
Titles map fixed addresses up to the application map area end,
0xFC_0000_0000 (SCE_KERNEL_APP_MAP_AREA_END_ADDR on the PS4), and a
direct memory mapping above the old end threw "shared mapping outside
the guest arena".
The arena is now reserved up to 0xFC_0000_0000. The out-of-arena
errors name the address and length, and a fixed mapping over a used
arena range says whether it hit a host region. guest_memory maps
direct memory at the last two pages below the end, reads it through
an alias and checks that a mapping at the end is refused.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Format through the shared wide formatter, truncate to the buffer and
return the full length, as C11 K.3.9.1.3 specifies. A null buffer or
format, a zero or oversized n, %n and a null %s argument are
runtime-constraint violations that return a negative value.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A store the driver makes with the CPU into watched guest memory (a
GuestMemory::Write, a changed-bytes write-back, a completion action's label
store, the copy HLE's CPU path) faults its pages dirty in the write watch and
stamps the range with MarkWritten. The faults stayed behind: collects are
memoized per packet, so the next walk over those pages came later and stamped
them again, as a CPU write made after every check in between.
PPSA21564 fast-clears its normal G-buffer every frame with a register DCC key
fill on the GPU. While that fill is still pending, the first draw into the
target materializes the clear with a CPU store of the clear texels and a
refresh of the resident image. A dozen draws later a walk found the store's
faults, the target read as changed, and the image was uploaded again from
guest memory, dropping the draws recorded in between. Lighting then sampled
cleared normals and the level's moon and rocks went unlit in about half the
frames.
The driver's stores now consume those faults themselves: a walk before the
store stamps earlier CPU writes as such, a walk after it takes the store's
own faults as a driver store, and the range is stamped as before.
On Windows the arena's range also holds host regions that were already in
use when it was reserved (heaps, thread stacks). They are not write-watched,
so a store into one is stamped as before, without a walk.
GCC gives C code built with -fexceptions, and cleanup-only functions
after link-time optimization, the C personality __gcc_personality_v0.
The unwinder accepted only its own C++ personality, so an exception
thrown through such a frame was never caught.
libc now provides the C personality, which never catches and installs
the frame's cleanup landing pad in the cleanup phase, and the unwinder
calls it for those frames.
A file read into guest memory is a host write: before the I/O it pins the shared pages it
covers, which reopens any page armed for write tracking and keeps write tracking from arming
it again until the read ends, when the pages count as written. A destination the guest cannot
write fails with EFAULT before any I/O; read and pread throw as for any failed read, AIO
reports SCE_KERNEL_ERROR_EFAULT, and APR throws. APR also throws when a read ends before the
requested size.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The arena is always [0x200000000, 0x7200000000). Every free, allocation-granularity-aligned
piece of the range is reserved as a placeholder; what lies between the pieces (thread stacks
and other reservations Windows made before libc starts, unaligned slivers) and the
system-reserved range are holes, used ranges a release never frees. A failed query or
reservation of the range throws.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>