From: Anthony Yznaga Date: Tue, 13 Jun 2017 20:47:06 +0000 (-0700) Subject: sparc64: rtrap must set PSTATE.mcde before handling outstanding user work X-Git-Tag: v4.1.12-105.0.20170705_2000~41 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=b1a2d9ae70aa5879630171a7fab5492c8b4b7229;p=users%2Fjedix%2Flinux-maple.git 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 Reviewed-by: Khalid Aziz Reviewed-by: Steve Sistare Signed-off-by: Allen Pais --- diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 709a82ebd294..173af08ae46e 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S @@ -24,13 +24,21 @@ .align 32 __handle_preemption: call SCHEDULE_USER - wrpr %g0, RTRAP_PSTATE, %pstate +661: wrpr %g0, RTRAP_PSTATE, %pstate + .section .sun4v_adi_1insn_patch, "ax" + .word 661b + wrpr %g0, RTRAP_PSTATE | PSTATE_MCDE, %pstate + .previous ba,pt %xcc, __handle_preemption_continue wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate __handle_user_windows: call fault_in_user_windows - wrpr %g0, RTRAP_PSTATE, %pstate +661: wrpr %g0, RTRAP_PSTATE, %pstate + .section .sun4v_adi_1insn_patch, "ax" + .word 661b + wrpr %g0, RTRAP_PSTATE | PSTATE_MCDE, %pstate + .previous ba,pt %xcc, __handle_preemption_continue wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate @@ -47,7 +55,11 @@ __handle_signal: add %sp, PTREGS_OFF, %o0 mov %l0, %o2 call do_notify_resume - wrpr %g0, RTRAP_PSTATE, %pstate +661: wrpr %g0, RTRAP_PSTATE, %pstate + .section .sun4v_adi_1insn_patch, "ax" + .word 661b + wrpr %g0, RTRAP_PSTATE | PSTATE_MCDE, %pstate + .previous wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate /* Signal delivery can modify pt_regs tstate, so we must diff --git a/arch/sparc/kernel/urtt_fill.S b/arch/sparc/kernel/urtt_fill.S index ca1a0c1b9d76..e1b9a99180bd 100644 --- a/arch/sparc/kernel/urtt_fill.S +++ b/arch/sparc/kernel/urtt_fill.S @@ -49,7 +49,11 @@ user_rtt_fill_fixup_common: SET_GL(0) .previous - wrpr %g0, RTRAP_PSTATE, %pstate +661: wrpr %g0, RTRAP_PSTATE, %pstate + .section .sun4v_adi_1insn_patch, "ax" + .word 661b + wrpr %g0, RTRAP_PSTATE | PSTATE_MCDE, %pstate + .previous mov %l1, %g6 ldx [%g6 + TI_TASK], %g4