CPU Paravirtualization

Discuss development specific to the Pi version of ADFFS
Post Reply
JonAbbott
Posts: 1736
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex

CPU Paravirtualization

Post by JonAbbott » Fri Nov 11, 2016 9:05 pm

Within the terms of ADFFS, CPU Paravirtualization means preventing code elevation, so the Hypervisor is always at a higher security level than the code running under it. In short, IRQ, FIQ and SVC code running under the JIT is actually running in USER, with the Hypervisor handling the banked registers (R13-R14 for USER/IRQ/SVC, and R8-R14 for FIQ).

To add full VMM support, the Hypervisor also needs to implement localized page tables and page table access levels. Access levels could be implemented fairly easily by having two sets of page tables for privileged and non-privileged cpu modes.

There's a few games that require CPU Paravirtualization to work unaltered, including:
  • Adventures, classic complication
  • Axis (although this has been patched via the Boot script, to prevent it using FIQ for extra registers)
  • Blitz!
  • SWIV
Changes required:
  1. OS_EnterOS needs Hypervising (coded)
  2. Use of MSR CPSR_cf/CPSR_all, Rx within codelets need to instead use SWI ADFFS_MSRRx - where x is the register that contains the new PSR (coded)
  3. Use of MRS Rx, CPSR within codelets need to instead use SWI ADFFS_MRSRx - where x is the register that needs to contain the current PSR (coded)
  4. ARMv4 PSR conversion code within codelets need removing as ADFFS_MSRRx /ADFFS_MRSRx can implement the ARMv3 PSR (coded)
  5. ADFFS_MSRR0 .. R3 need implementing (coded)
  6. ADFFS_MRSR0 .. R3 need implementing (coded)
  7. Needs space allocating within the VM to store R8-R14 for all four CPU modes (ie 4 x 8 x 4 = 128 bytes) (coded)
  8. Needs to store the current PSR in the banked USER R15 (coded)
  9. Vector_Claim_Handlers need to switch to USER, using the paravirtualized cpu mode registers
  10. IRQ_Vector_stack/OIRQ_Vector_stack need to move from a DA to the VM and use the VM's paravirtualized R13's
  11. GOARM3JIT needs to use the local USER stack before jumping into user code
  12. OS_FSControl needs to use the local USER stack before jumping into user code
  13. BASIC needs to be localized
  14. LDRT needs coding
  15. STRT needs coding
  16. LDM Rx,{<reglist>}^ needs to load user registers if PC not present in <reglist>
  17. STM Rx,{<reglist>}^ needs to store user registers if PC not present in <reglist>
  18. tmp_Module_stack/Otmp_Module_stack need to move from a DA to the VM and use the VM's paravirtualized R13's (optional)
  19. IOC_IRQ_stack needs to move from a DA to the VM and use the VM's paravirtualized R13's (optional)
ADFFS_MSRR0 .. 3 (coded)
Need coding as follows:
  1. If currently in FIQ, store R8-R14 to FIQ register bank, for all other modes store R8-R12 to USER register bank and R13-R14 to current CPU mode register bank
  2. If switching to FIQ restore R8-R14 from FIQ register bank, for all other modes, restore R8-R12 from USER register bank and R13-R14 from new CPU mode bank
  3. Set NZCV and IRQ/FIQ bits accordingly in SPSR
  4. Exit back via LDMFD R13!, {PC}^ to return in USER with CF bits set accordingly
ADFFS_MRSR0 .. 3 (coded)
Need coding as follows:
  • Rx=(SPSR & (%1111 << 28)) | ((SPSR & %11000000) << 20) | <new CPU mode>
Note that using SWI's isn't optimal, but does allow quick implementation. A better method would be to store R14 on entry to the codelet and BL to a codelet containing the MSR/MRS code.

For full VMM support, it would be preferable to replace instructions that require codelets with Hypercalls and then emulate the instruction. This would be substantially slower, but removes the complication of codelet management.

Post Reply