root/arch/sparc/kernel/sun4v_tlb_miss.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /* sun4v_tlb_miss.S: Sun4v TLB miss handlers.
   3  *
   4  * Copyright (C) 2006 <davem@davemloft.net>
   5  */
   6 
   7         .text
   8         .align  32
   9 
  10         /* Load ITLB fault information into VADDR and CTX, using BASE.  */
  11 #define LOAD_ITLB_INFO(BASE, VADDR, CTX) \
  12         ldx     [BASE + HV_FAULT_I_ADDR_OFFSET], VADDR; \
  13         ldx     [BASE + HV_FAULT_I_CTX_OFFSET], CTX;
  14 
  15         /* Load DTLB fault information into VADDR and CTX, using BASE.  */
  16 #define LOAD_DTLB_INFO(BASE, VADDR, CTX) \
  17         ldx     [BASE + HV_FAULT_D_ADDR_OFFSET], VADDR; \
  18         ldx     [BASE + HV_FAULT_D_CTX_OFFSET], CTX;
  19 
  20         /* DEST = (VADDR >> 22)
  21          *
  22          * Branch to ZERO_CTX_LABEL if context is zero.
  23          */
  24 #define COMPUTE_TAG_TARGET(DEST, VADDR, CTX, ZERO_CTX_LABEL) \
  25         srlx    VADDR, 22, DEST; \
  26         brz,pn  CTX, ZERO_CTX_LABEL; \
  27          nop;
  28 
  29         /* Create TSB pointer.  This is something like:
  30          *
  31          * index_mask = (512 << (tsb_reg & 0x7UL)) - 1UL;
  32          * tsb_base = tsb_reg & ~0x7UL;
  33          * tsb_index = ((vaddr >> HASH_SHIFT) & tsb_mask);
  34          * tsb_ptr = tsb_base + (tsb_index * 16);
  35          */
  36 #define COMPUTE_TSB_PTR(TSB_PTR, VADDR, HASH_SHIFT, TMP1, TMP2) \
  37         and     TSB_PTR, 0x7, TMP1;                     \
  38         mov     512, TMP2;                              \
  39         andn    TSB_PTR, 0x7, TSB_PTR;                  \
  40         sllx    TMP2, TMP1, TMP2;                       \
  41         srlx    VADDR, HASH_SHIFT, TMP1;                \
  42         sub     TMP2, 1, TMP2;                          \
  43         and     TMP1, TMP2, TMP1;                       \
  44         sllx    TMP1, 4, TMP1;                          \
  45         add     TSB_PTR, TMP1, TSB_PTR;
  46 
  47 sun4v_itlb_miss:
  48         /* Load MMU Miss base into %g2.  */
  49         ldxa    [%g0] ASI_SCRATCHPAD, %g2
  50         
  51         /* Load UTSB reg into %g1.  */
  52         mov     SCRATCHPAD_UTSBREG1, %g1
  53         ldxa    [%g1] ASI_SCRATCHPAD, %g1
  54 
  55         LOAD_ITLB_INFO(%g2, %g4, %g5)
  56         COMPUTE_TAG_TARGET(%g6, %g4, %g5, kvmap_itlb_4v)
  57         COMPUTE_TSB_PTR(%g1, %g4, PAGE_SHIFT, %g3, %g7)
  58 
  59         /* Load TSB tag/pte into %g2/%g3 and compare the tag.  */
  60         ldda    [%g1] ASI_QUAD_LDD_PHYS_4V, %g2
  61         cmp     %g2, %g6
  62         bne,a,pn %xcc, tsb_miss_page_table_walk
  63          mov    FAULT_CODE_ITLB, %g3
  64         andcc   %g3, _PAGE_EXEC_4V, %g0
  65         be,a,pn %xcc, tsb_do_fault
  66          mov    FAULT_CODE_ITLB, %g3
  67 
  68         /* We have a valid entry, make hypervisor call to load
  69          * I-TLB and return from trap.
  70          *
  71          * %g3: PTE
  72          * %g4: vaddr
  73          */
  74 sun4v_itlb_load:
  75         ldxa    [%g0] ASI_SCRATCHPAD, %g6
  76         mov     %o0, %g1                ! save %o0
  77         mov     %o1, %g2                ! save %o1
  78         mov     %o2, %g5                ! save %o2
  79         mov     %o3, %g7                ! save %o3
  80         mov     %g4, %o0                ! vaddr
  81         ldx     [%g6 + HV_FAULT_I_CTX_OFFSET], %o1      ! ctx
  82         mov     %g3, %o2                ! PTE
  83         mov     HV_MMU_IMMU, %o3        ! flags
  84         ta      HV_MMU_MAP_ADDR_TRAP
  85         brnz,pn %o0, sun4v_itlb_error
  86          mov    %g2, %o1                ! restore %o1
  87         mov     %g1, %o0                ! restore %o0
  88         mov     %g5, %o2                ! restore %o2
  89         mov     %g7, %o3                ! restore %o3
  90 
  91         retry
  92 
  93 sun4v_dtlb_miss:
  94         /* Load MMU Miss base into %g2.  */
  95         ldxa    [%g0] ASI_SCRATCHPAD, %g2
  96         
  97         /* Load UTSB reg into %g1.  */
  98         mov     SCRATCHPAD_UTSBREG1, %g1
  99         ldxa    [%g1] ASI_SCRATCHPAD, %g1
 100 
 101         LOAD_DTLB_INFO(%g2, %g4, %g5)
 102         COMPUTE_TAG_TARGET(%g6, %g4, %g5, kvmap_dtlb_4v)
 103         COMPUTE_TSB_PTR(%g1, %g4, PAGE_SHIFT, %g3, %g7)
 104 
 105         /* Load TSB tag/pte into %g2/%g3 and compare the tag.  */
 106         ldda    [%g1] ASI_QUAD_LDD_PHYS_4V, %g2
 107         cmp     %g2, %g6
 108         bne,a,pn %xcc, tsb_miss_page_table_walk
 109          mov    FAULT_CODE_DTLB, %g3
 110 
 111         /* We have a valid entry, make hypervisor call to load
 112          * D-TLB and return from trap.
 113          *
 114          * %g3: PTE
 115          * %g4: vaddr
 116          */
 117 sun4v_dtlb_load:
 118         ldxa    [%g0] ASI_SCRATCHPAD, %g6
 119         mov     %o0, %g1                ! save %o0
 120         mov     %o1, %g2                ! save %o1
 121         mov     %o2, %g5                ! save %o2
 122         mov     %o3, %g7                ! save %o3
 123         mov     %g4, %o0                ! vaddr
 124         ldx     [%g6 + HV_FAULT_D_CTX_OFFSET], %o1      ! ctx
 125         mov     %g3, %o2                ! PTE
 126         mov     HV_MMU_DMMU, %o3        ! flags
 127         ta      HV_MMU_MAP_ADDR_TRAP
 128         brnz,pn %o0, sun4v_dtlb_error
 129          mov    %g2, %o1                ! restore %o1
 130         mov     %g1, %o0                ! restore %o0
 131         mov     %g5, %o2                ! restore %o2
 132         mov     %g7, %o3                ! restore %o3
 133 
 134         retry
 135 
 136 sun4v_dtlb_prot:
 137         SET_GL(1)
 138 
 139         /* Load MMU Miss base into %g5.  */
 140         ldxa    [%g0] ASI_SCRATCHPAD, %g5
 141         
 142         ldx     [%g5 + HV_FAULT_D_ADDR_OFFSET], %g5
 143         rdpr    %tl, %g1
 144         cmp     %g1, 1
 145         bgu,pn  %xcc, winfix_trampoline
 146          mov    FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4
 147         ba,pt   %xcc, sparc64_realfault_common
 148          nop
 149 
 150         /* Called from trap table:
 151          * %g4: vaddr
 152          * %g5: context
 153          * %g6: TAG TARGET
 154          */
 155 sun4v_itsb_miss:
 156         mov     SCRATCHPAD_UTSBREG1, %g1
 157         ldxa    [%g1] ASI_SCRATCHPAD, %g1
 158         brz,pn  %g5, kvmap_itlb_4v
 159          mov    FAULT_CODE_ITLB, %g3
 160         ba,a,pt %xcc, sun4v_tsb_miss_common
 161 
 162         /* Called from trap table:
 163          * %g4: vaddr
 164          * %g5: context
 165          * %g6: TAG TARGET
 166          */
 167 sun4v_dtsb_miss:
 168         mov     SCRATCHPAD_UTSBREG1, %g1
 169         ldxa    [%g1] ASI_SCRATCHPAD, %g1
 170         brz,pn  %g5, kvmap_dtlb_4v
 171          mov    FAULT_CODE_DTLB, %g3
 172 
 173         /* fallthrough */
 174 
 175 sun4v_tsb_miss_common:
 176         COMPUTE_TSB_PTR(%g1, %g4, PAGE_SHIFT, %g5, %g7)
 177 
 178         sub     %g2, TRAP_PER_CPU_FAULT_INFO, %g2
 179 
 180 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
 181         mov     SCRATCHPAD_UTSBREG2, %g5
 182         ldxa    [%g5] ASI_SCRATCHPAD, %g5
 183         cmp     %g5, -1
 184         be,pt   %xcc, 80f
 185          nop
 186         COMPUTE_TSB_PTR(%g5, %g4, REAL_HPAGE_SHIFT, %g2, %g7)
 187 
 188         /* That clobbered %g2, reload it.  */
 189         ldxa    [%g0] ASI_SCRATCHPAD, %g2
 190         sub     %g2, TRAP_PER_CPU_FAULT_INFO, %g2
 191 
 192 80:     stx     %g5, [%g2 + TRAP_PER_CPU_TSB_HUGE_TEMP]
 193 #endif
 194 
 195         ba,pt   %xcc, tsb_miss_page_table_walk_sun4v_fastpath
 196          ldx    [%g2 + TRAP_PER_CPU_PGD_PADDR], %g7
 197 
 198 sun4v_itlb_error:
 199         rdpr    %tl, %g1
 200         cmp     %g1, 1
 201         ble,pt  %icc, sun4v_bad_ra
 202          or     %g0, FAULT_CODE_BAD_RA | FAULT_CODE_ITLB, %g1
 203 
 204         sethi   %hi(sun4v_err_itlb_vaddr), %g1
 205         stx     %g4, [%g1 + %lo(sun4v_err_itlb_vaddr)]
 206         sethi   %hi(sun4v_err_itlb_ctx), %g1
 207         ldxa    [%g0] ASI_SCRATCHPAD, %g6
 208         ldx     [%g6 + HV_FAULT_I_CTX_OFFSET], %o1
 209         stx     %o1, [%g1 + %lo(sun4v_err_itlb_ctx)]
 210         sethi   %hi(sun4v_err_itlb_pte), %g1
 211         stx     %g3, [%g1 + %lo(sun4v_err_itlb_pte)]
 212         sethi   %hi(sun4v_err_itlb_error), %g1
 213         stx     %o0, [%g1 + %lo(sun4v_err_itlb_error)]
 214 
 215         sethi   %hi(1f), %g7
 216         rdpr    %tl, %g4
 217         ba,pt   %xcc, etraptl1
 218 1:       or     %g7, %lo(1f), %g7
 219         mov     %l4, %o1
 220         call    sun4v_itlb_error_report
 221          add    %sp, PTREGS_OFF, %o0
 222 
 223         /* NOTREACHED */
 224 
 225 sun4v_dtlb_error:
 226         rdpr    %tl, %g1
 227         cmp     %g1, 1
 228         ble,pt  %icc, sun4v_bad_ra
 229          or     %g0, FAULT_CODE_BAD_RA | FAULT_CODE_DTLB, %g1
 230 
 231         sethi   %hi(sun4v_err_dtlb_vaddr), %g1
 232         stx     %g4, [%g1 + %lo(sun4v_err_dtlb_vaddr)]
 233         sethi   %hi(sun4v_err_dtlb_ctx), %g1
 234         ldxa    [%g0] ASI_SCRATCHPAD, %g6
 235         ldx     [%g6 + HV_FAULT_D_CTX_OFFSET], %o1
 236         stx     %o1, [%g1 + %lo(sun4v_err_dtlb_ctx)]
 237         sethi   %hi(sun4v_err_dtlb_pte), %g1
 238         stx     %g3, [%g1 + %lo(sun4v_err_dtlb_pte)]
 239         sethi   %hi(sun4v_err_dtlb_error), %g1
 240         stx     %o0, [%g1 + %lo(sun4v_err_dtlb_error)]
 241 
 242         sethi   %hi(1f), %g7
 243         rdpr    %tl, %g4
 244         ba,pt   %xcc, etraptl1
 245 1:       or     %g7, %lo(1f), %g7
 246         mov     %l4, %o1
 247         call    sun4v_dtlb_error_report
 248          add    %sp, PTREGS_OFF, %o0
 249 
 250         /* NOTREACHED */
 251 
 252 sun4v_bad_ra:
 253         or      %g0, %g4, %g5
 254         ba,pt   %xcc, sparc64_realfault_common
 255          or     %g1, %g0, %g4
 256 
 257         /* NOTREACHED */
 258 
 259         /* Instruction Access Exception, tl0. */
 260 sun4v_iacc:
 261         ldxa    [%g0] ASI_SCRATCHPAD, %g2
 262         ldx     [%g2 + HV_FAULT_I_TYPE_OFFSET], %g3
 263         ldx     [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4
 264         ldx     [%g2 + HV_FAULT_I_CTX_OFFSET], %g5
 265         sllx    %g3, 16, %g3
 266         or      %g5, %g3, %g5
 267         ba,pt   %xcc, etrap
 268          rd     %pc, %g7
 269         mov     %l4, %o1
 270         mov     %l5, %o2
 271         call    sun4v_insn_access_exception
 272          add    %sp, PTREGS_OFF, %o0
 273         ba,a,pt %xcc, rtrap
 274 
 275         /* Instruction Access Exception, tl1. */
 276 sun4v_iacc_tl1:
 277         ldxa    [%g0] ASI_SCRATCHPAD, %g2
 278         ldx     [%g2 + HV_FAULT_I_TYPE_OFFSET], %g3
 279         ldx     [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4
 280         ldx     [%g2 + HV_FAULT_I_CTX_OFFSET], %g5
 281         sllx    %g3, 16, %g3
 282         or      %g5, %g3, %g5
 283         ba,pt   %xcc, etraptl1
 284          rd     %pc, %g7
 285         mov     %l4, %o1
 286         mov     %l5, %o2
 287         call    sun4v_insn_access_exception_tl1
 288          add    %sp, PTREGS_OFF, %o0
 289         ba,a,pt %xcc, rtrap
 290 
 291         /* Data Access Exception, tl0. */
 292 sun4v_dacc:
 293         ldxa    [%g0] ASI_SCRATCHPAD, %g2
 294         ldx     [%g2 + HV_FAULT_D_TYPE_OFFSET], %g3
 295         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
 296         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
 297         sllx    %g3, 16, %g3
 298         or      %g5, %g3, %g5
 299         ba,pt   %xcc, etrap
 300          rd     %pc, %g7
 301         mov     %l4, %o1
 302         mov     %l5, %o2
 303         call    sun4v_data_access_exception
 304          add    %sp, PTREGS_OFF, %o0
 305         ba,a,pt %xcc, rtrap
 306 
 307         /* Data Access Exception, tl1. */
 308 sun4v_dacc_tl1:
 309         ldxa    [%g0] ASI_SCRATCHPAD, %g2
 310         ldx     [%g2 + HV_FAULT_D_TYPE_OFFSET], %g3
 311         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
 312         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
 313         sllx    %g3, 16, %g3
 314         or      %g5, %g3, %g5
 315         ba,pt   %xcc, etraptl1
 316          rd     %pc, %g7
 317         mov     %l4, %o1
 318         mov     %l5, %o2
 319         call    sun4v_data_access_exception_tl1
 320          add    %sp, PTREGS_OFF, %o0
 321         ba,a,pt %xcc, rtrap
 322 
 323         /* Memory Address Unaligned.  */
 324 sun4v_mna:
 325         /* Window fixup? */
 326         rdpr    %tl, %g2
 327         cmp     %g2, 1
 328         ble,pt  %icc, 1f
 329          nop
 330 
 331         SET_GL(1)
 332         ldxa    [%g0] ASI_SCRATCHPAD, %g2
 333         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g5
 334         mov     HV_FAULT_TYPE_UNALIGNED, %g3
 335         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g4
 336         sllx    %g3, 16, %g3
 337         or      %g4, %g3, %g4
 338         ba,pt   %xcc, winfix_mna
 339          rdpr   %tpc, %g3
 340         /* not reached */
 341 
 342 1:      ldxa    [%g0] ASI_SCRATCHPAD, %g2
 343         mov     HV_FAULT_TYPE_UNALIGNED, %g3
 344         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
 345         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
 346         sllx    %g3, 16, %g3
 347         or      %g5, %g3, %g5
 348 
 349         ba,pt   %xcc, etrap
 350          rd     %pc, %g7
 351         mov     %l4, %o1
 352         mov     %l5, %o2
 353         call    sun4v_do_mna
 354          add    %sp, PTREGS_OFF, %o0
 355         ba,a,pt %xcc, rtrap
 356          nop
 357 
 358         /* Privileged Action.  */
 359 sun4v_privact:
 360         ba,pt   %xcc, etrap
 361          rd     %pc, %g7
 362         call    do_privact
 363          add    %sp, PTREGS_OFF, %o0
 364         ba,a,pt %xcc, rtrap
 365 
 366         /* Unaligned ldd float, tl0. */
 367 sun4v_lddfmna:
 368         ldxa    [%g0] ASI_SCRATCHPAD, %g2
 369         ldx     [%g2 + HV_FAULT_D_TYPE_OFFSET], %g3
 370         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
 371         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
 372         sllx    %g3, 16, %g3
 373         or      %g5, %g3, %g5
 374         ba,pt   %xcc, etrap
 375          rd     %pc, %g7
 376         mov     %l4, %o1
 377         mov     %l5, %o2
 378         call    handle_lddfmna
 379          add    %sp, PTREGS_OFF, %o0
 380         ba,a,pt %xcc, rtrap
 381 
 382         /* Unaligned std float, tl0. */
 383 sun4v_stdfmna:
 384         ldxa    [%g0] ASI_SCRATCHPAD, %g2
 385         ldx     [%g2 + HV_FAULT_D_TYPE_OFFSET], %g3
 386         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
 387         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
 388         sllx    %g3, 16, %g3
 389         or      %g5, %g3, %g5
 390         ba,pt   %xcc, etrap
 391          rd     %pc, %g7
 392         mov     %l4, %o1
 393         mov     %l5, %o2
 394         call    handle_stdfmna
 395          add    %sp, PTREGS_OFF, %o0
 396         ba,a,pt %xcc, rtrap
 397 
 398 #define BRANCH_ALWAYS   0x10680000
 399 #define NOP             0x01000000
 400 #define SUN4V_DO_PATCH(OLD, NEW)        \
 401         sethi   %hi(NEW), %g1; \
 402         or      %g1, %lo(NEW), %g1; \
 403         sethi   %hi(OLD), %g2; \
 404         or      %g2, %lo(OLD), %g2; \
 405         sub     %g1, %g2, %g1; \
 406         sethi   %hi(BRANCH_ALWAYS), %g3; \
 407         sll     %g1, 11, %g1; \
 408         srl     %g1, 11 + 2, %g1; \
 409         or      %g3, %lo(BRANCH_ALWAYS), %g3; \
 410         or      %g3, %g1, %g3; \
 411         stw     %g3, [%g2]; \
 412         sethi   %hi(NOP), %g3; \
 413         or      %g3, %lo(NOP), %g3; \
 414         stw     %g3, [%g2 + 0x4]; \
 415         flush   %g2;
 416 
 417         .globl  sun4v_patch_tlb_handlers
 418         .type   sun4v_patch_tlb_handlers,#function
 419 sun4v_patch_tlb_handlers:
 420         SUN4V_DO_PATCH(tl0_iamiss, sun4v_itlb_miss)
 421         SUN4V_DO_PATCH(tl1_iamiss, sun4v_itlb_miss)
 422         SUN4V_DO_PATCH(tl0_damiss, sun4v_dtlb_miss)
 423         SUN4V_DO_PATCH(tl1_damiss, sun4v_dtlb_miss)
 424         SUN4V_DO_PATCH(tl0_daprot, sun4v_dtlb_prot)
 425         SUN4V_DO_PATCH(tl1_daprot, sun4v_dtlb_prot)
 426         SUN4V_DO_PATCH(tl0_iax, sun4v_iacc)
 427         SUN4V_DO_PATCH(tl1_iax, sun4v_iacc_tl1)
 428         SUN4V_DO_PATCH(tl0_dax, sun4v_dacc)
 429         SUN4V_DO_PATCH(tl1_dax, sun4v_dacc_tl1)
 430         SUN4V_DO_PATCH(tl0_mna, sun4v_mna)
 431         SUN4V_DO_PATCH(tl1_mna, sun4v_mna)
 432         SUN4V_DO_PATCH(tl0_lddfmna, sun4v_lddfmna)
 433         SUN4V_DO_PATCH(tl0_stdfmna, sun4v_stdfmna)
 434         SUN4V_DO_PATCH(tl0_privact, sun4v_privact)
 435         retl
 436          nop
 437         .size   sun4v_patch_tlb_handlers,.-sun4v_patch_tlb_handlers

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