This patchset cleans up our usage of cpsr_write() somewhat, and in particular its handling of attempts to change the MODE bits. Currently we use cpsr_write() for multiple purposes: * writes on inbound migration and sync with KVM, where we want a raw "just write these bits" and have to actively mess with uncached_cpsr before the write to avoid it doing a register bank switch * writes caused by guest instructions MSR and CPS * writes caused by guest 32-bit exception returns * a few other things like the gdb stub
However the required handling differs for these different cases; in particular the set of conditions which are architecturally defined to be an illegal mode switch is different for writes due to MSR/CPS versus writes due to exception returns. To fix this we add an extra argument to cpsr_write() which is an enum indicating what kind of write is being performed. This allows us to drop the irritating "manually write the mode bits before the call" code in KVM/migration (and fix a bug where we missed this out in 32-bit KVM!). We can also add the various missing conditions: * changes to hyp mode * changes from hyp mode by MSR/CPS * changes to Mon from Secure EL1 * changes from Mon to NS PL1 when HCR.TGE is set Finally we can implement the v8 behaviour of setting PSTATE.IL for illegal mode changes. The series also fixes the behaviour of attempted illegal mode changes from the gdb stub -- we ignore them, but don't set PSTATE.IL. (Previously we had a slightly weird setup where we would permit changes from User to the PL1 modes but not to Mon.) Not permitting illegal changes from the debugger: * means we don't have to consider weird "transition is possible but only for the debugger" corner cases * matches the behaviour of a JTAG debugger doing external debug on real ARM hardware, where architecturally the illegal state transitions are enforced PS: we don't currently implement the PSTATE.IL "any attempt to execute an insn will UNDEF" behaviour, but it would not be hard to add. thanks -- PMM Peter Maydell (11): target-arm: Give CPSR setting on 32-bit exception return its own helper target-arm: Add write_type argument to cpsr_write() target-arm: Raw CPSR writes should skip checks and bank switching linux-user: Use restrictive mask when calling cpsr_write() target-arm: In cpsr_write() ignore mode switches from User mode target-arm: Add comment about not implementing NSACR.RFR target-arm: Add Hyp mode checks to bad_mode_switch() target-arm: Forbid mode switch to Mon from Secure EL1 target-arm: In v8, make illegal AArch32 mode changes set PSTATE.IL target-arm: Make mode switches from Hyp via CPS and MRS illegal target-arm: Make Monitor->NS PL1 mode changes illegal if HCR.TGE is 1 linux-user/arm/nwfpe/fpa11.h | 2 +- linux-user/main.c | 7 +++--- linux-user/signal.c | 4 ++-- target-arm/cpu.h | 13 +++++++++-- target-arm/gdbstub.c | 2 +- target-arm/helper.c | 54 ++++++++++++++++++++++++++++++++++++-------- target-arm/helper.h | 1 + target-arm/kvm32.c | 2 +- target-arm/kvm64.c | 3 +-- target-arm/machine.c | 4 +--- target-arm/op_helper.c | 15 +++++++++--- target-arm/translate.c | 6 ++--- 12 files changed, 83 insertions(+), 30 deletions(-) -- 1.9.1