Suspend

When the system is suspended, it enters a low power state where the main application processor is turned off. The main DRAM state is preserved so upon resume, the kernel does not have to be reloaded.

Suspending
To suspend the system, PS Vita saves the current context into a buffer and sends it to Syscon. Then it issues a Syscon request to enter the low-power state.

Saving Context
The context buffer defined above is built and the physical address of the context buffer is written to Syscon memory at offset  i.e it calls sceSysconWriteForDriver with. Then it issues the syscon command to suspend the device.

Early boot process
When resume is launched, Syscon starts first_loader, which runs second_loader, like a cold boot.

The physical address of the context buffer is read from Syscon memory at offset  i.e second_loader calls. This physical address is written to KBL Param.

SKBL
Upon power up, the Boot Sequence is the same until the point where the SKBL would jump into the non-secure kernel bootloader at. Instead, it checks the suspendinfo address is valid, then copies resume code (from SKBL ) to the scratchpad (physical address  ), the Suspend Info to   and creates a SceKernelResumeInfo at , then enters Non-secure state at.

check
SKBL performs a sanity check on  before attempting to resume with it. The address must be properly aligned, and belong in a specific range of physical address space (namely Non-Secure DRAM). If the check fails, SKBL enters an infinite loop and the boot process halts. The following table details the specifics for different firmwares.

SKBL Resume code
This code starts in Non-secure state, Supervisor mode, with the MMU and all caches disabled.

This code has changed in the following firmwares:

Entrypoint
The entrypoint is very short. It disables interrupts, clears exclusive access requests then jumps to a little thunk at   which simply jumps to the cleanup function at   (alias of  ).

Cleanup function
This function sets  to 0, clears the Branch Predictor, TLB and Instruction/Data caches, disables alignement check with SCTLR (clear bit 0x2 - this is redundant as 0 was written to SCTLR earlier), then sets up a MMU context before restoring SCTLR (, re-enables MMU) and jumping to the restore function at virtual address   (physical address  ). This is important as it means TTBR1 now backs the executed code.

The MMU configuration is the following: The L1 Page Table is located at  and only contains 3 Section (1MiB) mappings in domain 0:
 * is set to
 * and  are set to
 * is set to  (all domains accessible, permissions checked)
 * is set to
 * is identity mapped
 * is mapped to physical address
 * is identity mapped as Strongly Ordered memory

Restore function
This function restores (almost) all the registers from the Suspend Info, then copies the  to the buffer in Suspend Info, sets   to   and jumps to the resume function pointed to by the Suspend Info.

NOTE: It is highly plausible that a Suspend Info with  will crash when   is restored in this step, as   is backing this routine.

In FW 0.931.010, no arguments are provided to the resume function ( are   and the resume function is  ). In FWs 0.940-0.990, DACR is not provided to the resume function. is  and the resume function is  ).

Non-restored registers
The following registers from the Suspend Info are not restored:

Rebooting with Patches
By abusing the way resume works, we can reboot the device into a custom firmware by patching the non-secure kernel bootloader. The general framework to do this is: first, patch the kernel bootloader in RAM to accept unsigned SELFs and load a custom kprx after. It could be the case that by the time your exploit runs the DRAM region containing the kernel loader has been wiped/reused. If so, you must use a lower level exploit to dump the loader. It may even be possible to dump the compressed version, in that case you wouldn't even need to perform cleanup. Your custom krpx will be loaded after the bare essential kernel modules are loaded (memory management, threads, file IO, etc) and it can then patch the full module loader (SceSblAuthMgr) to accept unsigned SELFs as well as any other patches.

Cleaning up non-secure Kernel Bootloader
Ideally, if we can get the original ARZL compressed version of the non-secure kernel bootloader that is extracted from, we can extract it (see ARZL), then we can load that to memory and jump to it from our resume function. However, by the time the system is in a state we control, usually that data would be corrupted. What we are left with is the non-secure kernel bootloader in the state after bootup is completed. In order to get it to run successfully again in our resume function, we need to clean up the data it uses.