sparc64: rtrap must set PSTATE.mcde before handling outstanding user work
The kernel must execute with PSTATE.mcde=1 for ADI version checking to
be enabled when the kernel reads or writes user memory mapped with ADI
enabled using versioned addresses. If PSTATE.mcde=0 then the MMU
interprets version bits in an address as address bits, and an access
attempt results in a data access exception. Until now setting
PSTATE.mcde=1 in the kernel has been handled only by patching etrap to
ensure that is set on entry into the kernel. However, there are code
paths in rtrap that overwrite PSTATE and inadvertently clear PSTATE.mcde
before additional execution happens in the kernel.
rtrap is executed to exit the kernel and return to user mode execution.
Before restoring registers and returning to user mode, rtrap checks for
work to do. The check is done with interrupts disabled, and if there is
work to do, then interrupts are enabled before calling a function to
complete the work after which interrupts are disabled again and the
check is repeated. Interrupts are disabled and enabled by overwriting
PSTATE. Possible work includes (but is not limited to) preemption,
signal delivery, and writing out buffered user register windows to the
stack. All of these may lead to accessing user addresses. In the case
of preemption, a resumed thread will run with PSTATE.mcde=0 until it
completes a return to user mode or is rescheduled on a CPU where
PSTATE.mcde is set. If the thread accesses ADI-enabled user memory with
a versioned address (e.g. to complete some I/O) in that timeframe then
the access will fail. To fix the problem, patch rtrap to set
PSTATE.mcde when interrupts are enabled before handling the work.
Orabug:
25853545
Signed-off-by: Anthony Yznaga <anthony.yznaga@oracle.com>
Reviewed-by: Khalid Aziz <khalid.aziz@oracle.com>
Reviewed-by: Steve Sistare <steven.sistare@oracle.com>
Signed-off-by: Allen Pais <allen.pais@oracle.com>