root/arch/sparc/kernel/rtrap_64.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /*
   3  * rtrap.S: Preparing for return from trap on Sparc V9.
   4  *
   5  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   6  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
   7  */
   8 
   9 
  10 #include <asm/asi.h>
  11 #include <asm/pstate.h>
  12 #include <asm/ptrace.h>
  13 #include <asm/spitfire.h>
  14 #include <asm/head.h>
  15 #include <asm/visasm.h>
  16 #include <asm/processor.h>
  17 
  18 #ifdef CONFIG_CONTEXT_TRACKING
  19 # define SCHEDULE_USER schedule_user
  20 #else
  21 # define SCHEDULE_USER schedule
  22 #endif
  23 
  24                 .text
  25                 .align                  32
  26 __handle_preemption:
  27                 call                    SCHEDULE_USER
  28 661:             wrpr                   %g0, RTRAP_PSTATE, %pstate
  29                 /* If userspace is using ADI, it could potentially pass
  30                  * a pointer with version tag embedded in it. To maintain
  31                  * the ADI security, we must re-enable PSTATE.mcde before
  32                  * we continue execution in the kernel for another thread.
  33                  */
  34                 .section .sun_m7_1insn_patch, "ax"
  35                 .word   661b
  36                  wrpr                   %g0, RTRAP_PSTATE|PSTATE_MCDE, %pstate
  37                 .previous
  38                 ba,pt                   %xcc, __handle_preemption_continue
  39                  wrpr                   %g0, RTRAP_PSTATE_IRQOFF, %pstate
  40 
  41 __handle_user_windows:
  42                 add                     %sp, PTREGS_OFF, %o0
  43                 call                    fault_in_user_windows
  44 661:             wrpr                   %g0, RTRAP_PSTATE, %pstate
  45                 /* If userspace is using ADI, it could potentially pass
  46                  * a pointer with version tag embedded in it. To maintain
  47                  * the ADI security, we must re-enable PSTATE.mcde before
  48                  * we continue execution in the kernel for another thread.
  49                  */
  50                 .section .sun_m7_1insn_patch, "ax"
  51                 .word   661b
  52                  wrpr                   %g0, RTRAP_PSTATE|PSTATE_MCDE, %pstate
  53                 .previous
  54                 ba,pt                   %xcc, __handle_preemption_continue
  55                  wrpr                   %g0, RTRAP_PSTATE_IRQOFF, %pstate
  56 
  57 __handle_userfpu:
  58                 rd                      %fprs, %l5
  59                 andcc                   %l5, FPRS_FEF, %g0
  60                 sethi                   %hi(TSTATE_PEF), %o0
  61                 be,a,pn                 %icc, __handle_userfpu_continue
  62                  andn                   %l1, %o0, %l1
  63                 ba,a,pt                 %xcc, __handle_userfpu_continue
  64 
  65 __handle_signal:
  66                 mov                     %l5, %o1
  67                 add                     %sp, PTREGS_OFF, %o0
  68                 mov                     %l0, %o2
  69                 call                    do_notify_resume
  70 661:             wrpr                   %g0, RTRAP_PSTATE, %pstate
  71                 /* If userspace is using ADI, it could potentially pass
  72                  * a pointer with version tag embedded in it. To maintain
  73                  * the ADI security, we must re-enable PSTATE.mcde before
  74                  * we continue execution in the kernel for another thread.
  75                  */
  76                 .section .sun_m7_1insn_patch, "ax"
  77                 .word   661b
  78                  wrpr                   %g0, RTRAP_PSTATE|PSTATE_MCDE, %pstate
  79                 .previous
  80                 wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
  81 
  82                 /* Signal delivery can modify pt_regs tstate, so we must
  83                  * reload it.
  84                  */
  85                 ldx                     [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
  86                 sethi                   %hi(0xf << 20), %l4
  87                 and                     %l1, %l4, %l4
  88                 andn                    %l1, %l4, %l1
  89                 ba,pt                   %xcc, __handle_preemption_continue
  90                  srl                    %l4, 20, %l4
  91 
  92                 /* When returning from a NMI (%pil==15) interrupt we want to
  93                  * avoid running softirqs, doing IRQ tracing, preempting, etc.
  94                  */
  95                 .globl                  rtrap_nmi
  96 rtrap_nmi:      ldx                     [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
  97                 sethi                   %hi(0xf << 20), %l4
  98                 and                     %l1, %l4, %l4
  99                 andn                    %l1, %l4, %l1
 100                 srl                     %l4, 20, %l4
 101                 ba,pt                   %xcc, rtrap_no_irq_enable
 102                 nop
 103                 /* Do not actually set the %pil here.  We will do that
 104                  * below after we clear PSTATE_IE in the %pstate register.
 105                  * If we re-enable interrupts here, we can recurse down
 106                  * the hardirq stack potentially endlessly, causing a
 107                  * stack overflow.
 108                  */
 109 
 110                 .align                  64
 111                 .globl                  rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
 112 rtrap_irq:
 113 rtrap:
 114                 /* mm/ultra.S:xcall_report_regs KNOWS about this load. */
 115                 ldx                     [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
 116 rtrap_xcall:
 117                 sethi                   %hi(0xf << 20), %l4
 118                 and                     %l1, %l4, %l4
 119                 andn                    %l1, %l4, %l1
 120                 srl                     %l4, 20, %l4
 121 #ifdef CONFIG_TRACE_IRQFLAGS
 122                 brnz,pn                 %l4, rtrap_no_irq_enable
 123                  nop
 124                 call                    trace_hardirqs_on
 125                  nop
 126                 /* Do not actually set the %pil here.  We will do that
 127                  * below after we clear PSTATE_IE in the %pstate register.
 128                  * If we re-enable interrupts here, we can recurse down
 129                  * the hardirq stack potentially endlessly, causing a
 130                  * stack overflow.
 131                  *
 132                  * It is tempting to put this test and trace_hardirqs_on
 133                  * call at the 'rt_continue' label, but that will not work
 134                  * as that path hits unconditionally and we do not want to
 135                  * execute this in NMI return paths, for example.
 136                  */
 137 #endif
 138 rtrap_no_irq_enable:
 139                 andcc                   %l1, TSTATE_PRIV, %l3
 140                 bne,pn                  %icc, to_kernel
 141                  nop
 142 
 143                 /* We must hold IRQs off and atomically test schedule+signal
 144                  * state, then hold them off all the way back to userspace.
 145                  * If we are returning to kernel, none of this matters.  Note
 146                  * that we are disabling interrupts via PSTATE_IE, not using
 147                  * %pil.
 148                  *
 149                  * If we do not do this, there is a window where we would do
 150                  * the tests, later the signal/resched event arrives but we do
 151                  * not process it since we are still in kernel mode.  It would
 152                  * take until the next local IRQ before the signal/resched
 153                  * event would be handled.
 154                  *
 155                  * This also means that if we have to deal with user
 156                  * windows, we have to redo all of these sched+signal checks
 157                  * with IRQs disabled.
 158                  */
 159 to_user:        wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
 160                 wrpr                    0, %pil
 161 __handle_preemption_continue:
 162                 ldx                     [%g6 + TI_FLAGS], %l0
 163                 sethi                   %hi(_TIF_USER_WORK_MASK), %o0
 164                 or                      %o0, %lo(_TIF_USER_WORK_MASK), %o0
 165                 andcc                   %l0, %o0, %g0
 166                 sethi                   %hi(TSTATE_PEF), %o0
 167                 be,pt                   %xcc, user_nowork
 168                  andcc                  %l1, %o0, %g0
 169                 andcc                   %l0, _TIF_NEED_RESCHED, %g0
 170                 bne,pn                  %xcc, __handle_preemption
 171                  andcc                  %l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0
 172                 bne,pn                  %xcc, __handle_signal
 173                  ldub                   [%g6 + TI_WSAVED], %o2
 174                 brnz,pn                 %o2, __handle_user_windows
 175                  nop
 176                 sethi                   %hi(TSTATE_PEF), %o0
 177                 andcc                   %l1, %o0, %g0
 178 
 179                 /* This fpdepth clear is necessary for non-syscall rtraps only */
 180 user_nowork:
 181                 bne,pn                  %xcc, __handle_userfpu
 182                  stb                    %g0, [%g6 + TI_FPDEPTH]
 183 __handle_userfpu_continue:
 184 
 185 rt_continue:    ldx                     [%sp + PTREGS_OFF + PT_V9_G1], %g1
 186                 ldx                     [%sp + PTREGS_OFF + PT_V9_G2], %g2
 187 
 188                 ldx                     [%sp + PTREGS_OFF + PT_V9_G3], %g3
 189                 ldx                     [%sp + PTREGS_OFF + PT_V9_G4], %g4
 190                 ldx                     [%sp + PTREGS_OFF + PT_V9_G5], %g5
 191                 brz,pt                  %l3, 1f
 192                 mov                     %g6, %l2
 193 
 194                 /* Must do this before thread reg is clobbered below.  */
 195                 LOAD_PER_CPU_BASE(%g5, %g6, %i0, %i1, %i2)
 196 1:
 197                 ldx                     [%sp + PTREGS_OFF + PT_V9_G6], %g6
 198                 ldx                     [%sp + PTREGS_OFF + PT_V9_G7], %g7
 199 
 200                 /* Normal globals are restored, go to trap globals.  */
 201 661:            wrpr                    %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate
 202                 nop
 203                 .section                .sun4v_2insn_patch, "ax"
 204                 .word                   661b
 205                 wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
 206                 SET_GL(1)
 207                 .previous
 208 
 209                 mov                     %l2, %g6
 210 
 211                 ldx                     [%sp + PTREGS_OFF + PT_V9_I0], %i0
 212                 ldx                     [%sp + PTREGS_OFF + PT_V9_I1], %i1
 213 
 214                 ldx                     [%sp + PTREGS_OFF + PT_V9_I2], %i2
 215                 ldx                     [%sp + PTREGS_OFF + PT_V9_I3], %i3
 216                 ldx                     [%sp + PTREGS_OFF + PT_V9_I4], %i4
 217                 ldx                     [%sp + PTREGS_OFF + PT_V9_I5], %i5
 218                 ldx                     [%sp + PTREGS_OFF + PT_V9_I6], %i6
 219                 ldx                     [%sp + PTREGS_OFF + PT_V9_I7], %i7
 220                 ldx                     [%sp + PTREGS_OFF + PT_V9_TPC], %l2
 221                 ldx                     [%sp + PTREGS_OFF + PT_V9_TNPC], %o2
 222 
 223                 ld                      [%sp + PTREGS_OFF + PT_V9_Y], %o3
 224                 wr                      %o3, %g0, %y
 225                 wrpr                    %l4, 0x0, %pil
 226                 wrpr                    %g0, 0x1, %tl
 227                 andn                    %l1, TSTATE_SYSCALL, %l1
 228                 wrpr                    %l1, %g0, %tstate
 229                 wrpr                    %l2, %g0, %tpc
 230                 wrpr                    %o2, %g0, %tnpc
 231 
 232                 brnz,pn                 %l3, kern_rtt
 233                  mov                    PRIMARY_CONTEXT, %l7
 234 
 235 661:            ldxa                    [%l7 + %l7] ASI_DMMU, %l0
 236                 .section                .sun4v_1insn_patch, "ax"
 237                 .word                   661b
 238                 ldxa                    [%l7 + %l7] ASI_MMU, %l0
 239                 .previous
 240 
 241                 sethi                   %hi(sparc64_kern_pri_nuc_bits), %l1
 242                 ldx                     [%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1
 243                 or                      %l0, %l1, %l0
 244 
 245 661:            stxa                    %l0, [%l7] ASI_DMMU
 246                 .section                .sun4v_1insn_patch, "ax"
 247                 .word                   661b
 248                 stxa                    %l0, [%l7] ASI_MMU
 249                 .previous
 250 
 251                 sethi                   %hi(KERNBASE), %l7
 252                 flush                   %l7
 253                 rdpr                    %wstate, %l1
 254                 rdpr                    %otherwin, %l2
 255                 srl                     %l1, 3, %l1
 256 
 257 661:            wrpr                    %l2, %g0, %canrestore
 258                 .section                .fast_win_ctrl_1insn_patch, "ax"
 259                 .word                   661b
 260                 .word                   0x89880000      ! normalw
 261                 .previous
 262 
 263                 wrpr                    %l1, %g0, %wstate
 264                 brnz,pt                 %l2, user_rtt_restore
 265 661:             wrpr                   %g0, %g0, %otherwin
 266                 .section                .fast_win_ctrl_1insn_patch, "ax"
 267                 .word                   661b
 268                  nop
 269                 .previous
 270 
 271                 ldx                     [%g6 + TI_FLAGS], %g3
 272                 wr                      %g0, ASI_AIUP, %asi
 273                 rdpr                    %cwp, %g1
 274                 andcc                   %g3, _TIF_32BIT, %g0
 275                 sub                     %g1, 1, %g1
 276                 bne,pt                  %xcc, user_rtt_fill_32bit
 277                  wrpr                   %g1, %cwp
 278                 ba,a,pt                 %xcc, user_rtt_fill_64bit
 279                  nop
 280 
 281 user_rtt_fill_fixup_dax:
 282                 ba,pt   %xcc, user_rtt_fill_fixup_common
 283                  mov    1, %g3
 284 
 285 user_rtt_fill_fixup_mna:
 286                 ba,pt   %xcc, user_rtt_fill_fixup_common
 287                  mov    2, %g3
 288 
 289 user_rtt_fill_fixup:
 290                 ba,pt   %xcc, user_rtt_fill_fixup_common
 291                  clr    %g3
 292 
 293 user_rtt_pre_restore:
 294                 add                     %g1, 1, %g1
 295                 wrpr                    %g1, 0x0, %cwp
 296 
 297 user_rtt_restore:
 298                 restore
 299                 rdpr                    %canrestore, %g1
 300                 wrpr                    %g1, 0x0, %cleanwin
 301                 retry
 302                 nop
 303 
 304 kern_rtt:       rdpr                    %canrestore, %g1
 305                 brz,pn                  %g1, kern_rtt_fill
 306                  nop
 307 kern_rtt_restore:
 308                 stw                     %g0, [%sp + PTREGS_OFF + PT_V9_MAGIC]
 309                 restore
 310                 retry
 311 
 312 to_kernel:
 313 #ifdef CONFIG_PREEMPT
 314                 ldsw                    [%g6 + TI_PRE_COUNT], %l5
 315                 brnz                    %l5, kern_fpucheck
 316                  ldx                    [%g6 + TI_FLAGS], %l5
 317                 andcc                   %l5, _TIF_NEED_RESCHED, %g0
 318                 be,pt                   %xcc, kern_fpucheck
 319                  nop
 320                 cmp                     %l4, 0
 321                 bne,pn                  %xcc, kern_fpucheck
 322                  nop
 323                 call                    preempt_schedule_irq
 324                  nop
 325                 ba,pt                   %xcc, rtrap
 326 #endif
 327 kern_fpucheck:  ldub                    [%g6 + TI_FPDEPTH], %l5
 328                 brz,pt                  %l5, rt_continue
 329                  srl                    %l5, 1, %o0
 330                 add                     %g6, TI_FPSAVED, %l6
 331                 ldub                    [%l6 + %o0], %l2
 332                 sub                     %l5, 2, %l5
 333 
 334                 add                     %g6, TI_GSR, %o1
 335                 andcc                   %l2, (FPRS_FEF|FPRS_DU), %g0
 336                 be,pt                   %icc, 2f
 337                  and                    %l2, FPRS_DL, %l6
 338                 andcc                   %l2, FPRS_FEF, %g0
 339                 be,pn                   %icc, 5f
 340                  sll                    %o0, 3, %o5
 341                 rd                      %fprs, %g1
 342 
 343                 wr                      %g1, FPRS_FEF, %fprs
 344                 ldx                     [%o1 + %o5], %g1
 345                 add                     %g6, TI_XFSR, %o1
 346                 sll                     %o0, 8, %o2
 347                 add                     %g6, TI_FPREGS, %o3
 348                 brz,pn                  %l6, 1f
 349                  add                    %g6, TI_FPREGS+0x40, %o4
 350 
 351                 membar                  #Sync
 352                 ldda                    [%o3 + %o2] ASI_BLK_P, %f0
 353                 ldda                    [%o4 + %o2] ASI_BLK_P, %f16
 354                 membar                  #Sync
 355 1:              andcc                   %l2, FPRS_DU, %g0
 356                 be,pn                   %icc, 1f
 357                  wr                     %g1, 0, %gsr
 358                 add                     %o2, 0x80, %o2
 359                 membar                  #Sync
 360                 ldda                    [%o3 + %o2] ASI_BLK_P, %f32
 361                 ldda                    [%o4 + %o2] ASI_BLK_P, %f48
 362 1:              membar                  #Sync
 363                 ldx                     [%o1 + %o5], %fsr
 364 2:              stb                     %l5, [%g6 + TI_FPDEPTH]
 365                 ba,pt                   %xcc, rt_continue
 366                  nop
 367 5:              wr                      %g0, FPRS_FEF, %fprs
 368                 sll                     %o0, 8, %o2
 369 
 370                 add                     %g6, TI_FPREGS+0x80, %o3
 371                 add                     %g6, TI_FPREGS+0xc0, %o4
 372                 membar                  #Sync
 373                 ldda                    [%o3 + %o2] ASI_BLK_P, %f32
 374                 ldda                    [%o4 + %o2] ASI_BLK_P, %f48
 375                 membar                  #Sync
 376                 wr                      %g0, FPRS_DU, %fprs
 377                 ba,pt                   %xcc, rt_continue
 378                  stb                    %l5, [%g6 + TI_FPDEPTH]

/* [<][>][^][v][top][bottom][index][help] */