1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* sun4v_ivec.S: Sun4v interrupt vector handli 3 * 4 * Copyright (C) 2006 <davem@davemloft.net> 5 */ 6 7 #include <asm/cpudata.h> 8 #include <asm/intr_queue.h> 9 #include <asm/pil.h> 10 11 .text 12 .align 32 13 14 sun4v_cpu_mondo: 15 /* Head offset in %g2, tail offset in 16 * If they are the same, no work. 17 */ 18 mov INTRQ_CPU_MONDO_HEAD, %g2 19 ldxa [%g2] ASI_QUEUE, %g2 20 mov INTRQ_CPU_MONDO_TAIL, %g4 21 ldxa [%g4] ASI_QUEUE, %g4 22 cmp %g2, %g4 23 be,pn %xcc, sun4v_cpu_mondo_queue_em 24 nop 25 26 /* Get &trap_block[smp_processor_id()] 27 ldxa [%g0] ASI_SCRATCHPAD, %g4 28 sub %g4, TRAP_PER_CPU_FAULT_INFO, 29 30 /* Get smp_processor_id() into %g3 */ 31 sethi %hi(trap_block), %g5 32 or %g5, %lo(trap_block), %g5 33 sub %g4, %g5, %g3 34 srlx %g3, TRAP_BLOCK_SZ_SHIFT, %g3 35 36 /* Increment cpu_mondo_counter[smp_pro 37 sethi %hi(cpu_mondo_counter), %g5 38 or %g5, %lo(cpu_mondo_counter), % 39 sllx %g3, 3, %g3 40 add %g5, %g3, %g5 41 ldx [%g5], %g3 42 add %g3, 1, %g3 43 stx %g3, [%g5] 44 45 /* Get CPU mondo queue base phys addre 46 ldx [%g4 + TRAP_PER_CPU_CPU_MONDO_ 47 48 /* Now get the cross-call arguments an 49 * layout as sun4u: 50 * 51 * 1st 64-bit word: low half is 32-bit 52 * high half is conte 53 * 2nd 64-bit word: 64-bit arg, load i 54 * 3rd 64-bit word: 64-bit arg, load i 55 */ 56 ldxa [%g7 + %g2] ASI_PHYS_USE_EC, % 57 add %g2, 0x8, %g2 58 srlx %g3, 32, %g5 59 ldxa [%g7 + %g2] ASI_PHYS_USE_EC, % 60 add %g2, 0x8, %g2 61 srl %g3, 0, %g3 62 ldxa [%g7 + %g2] ASI_PHYS_USE_EC, % 63 add %g2, 0x40 - 0x8 - 0x8, %g2 64 65 /* Update queue head pointer. */ 66 lduw [%g4 + TRAP_PER_CPU_CPU_MONDO_ 67 and %g2, %g4, %g2 68 69 mov INTRQ_CPU_MONDO_HEAD, %g4 70 stxa %g2, [%g4] ASI_QUEUE 71 membar #Sync 72 73 jmpl %g3, %g0 74 nop 75 76 sun4v_cpu_mondo_queue_empty: 77 retry 78 79 sun4v_dev_mondo: 80 /* Head offset in %g2, tail offset in 81 mov INTRQ_DEVICE_MONDO_HEAD, %g2 82 ldxa [%g2] ASI_QUEUE, %g2 83 mov INTRQ_DEVICE_MONDO_TAIL, %g4 84 ldxa [%g4] ASI_QUEUE, %g4 85 cmp %g2, %g4 86 be,pn %xcc, sun4v_dev_mondo_queue_em 87 nop 88 89 /* Get &trap_block[smp_processor_id()] 90 ldxa [%g0] ASI_SCRATCHPAD, %g4 91 sub %g4, TRAP_PER_CPU_FAULT_INFO, 92 93 /* Get DEV mondo queue base phys addre 94 ldx [%g4 + TRAP_PER_CPU_DEV_MONDO_ 95 96 /* Load IVEC into %g3. */ 97 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 98 add %g2, 0x40, %g2 99 100 /* XXX There can be a full 64-byte blo 101 * XXX This is how we can get at MSI v 102 * XXX Current we do not capture this, 103 * XXX need to add a 64-byte storage a 104 * XXX or the struct irq_desc. 105 */ 106 107 /* Update queue head pointer, this fre 108 lduw [%g4 + TRAP_PER_CPU_DEV_MONDO_ 109 and %g2, %g4, %g2 110 111 mov INTRQ_DEVICE_MONDO_HEAD, %g4 112 stxa %g2, [%g4] ASI_QUEUE 113 membar #Sync 114 115 TRAP_LOAD_IRQ_WORK_PA(%g1, %g4) 116 117 /* For VIRQs, cookie is encoded as ~bu 118 brlz,pt %g3, 1f 119 xnor %g3, %g0, %g4 120 121 /* Get __pa(&ivector_table[IVEC]) into 122 sethi %hi(ivector_table_pa), %g4 123 ldx [%g4 + %lo(ivector_table_pa)], 124 sllx %g3, 4, %g3 125 add %g4, %g3, %g4 126 127 1: ldx [%g1], %g2 128 stxa %g2, [%g4] ASI_PHYS_USE_EC 129 stx %g4, [%g1] 130 131 /* Signal the interrupt by setting (1 132 wr %g0, 1 << PIL_DEVICE_IRQ, %set 133 134 sun4v_dev_mondo_queue_empty: 135 retry 136 137 sun4v_res_mondo: 138 /* Head offset in %g2, tail offset in 139 mov INTRQ_RESUM_MONDO_HEAD, %g2 140 ldxa [%g2] ASI_QUEUE, %g2 141 mov INTRQ_RESUM_MONDO_TAIL, %g4 142 ldxa [%g4] ASI_QUEUE, %g4 143 cmp %g2, %g4 144 be,pn %xcc, sun4v_res_mondo_queue_em 145 nop 146 147 /* Get &trap_block[smp_processor_id()] 148 ldxa [%g0] ASI_SCRATCHPAD, %g3 149 sub %g3, TRAP_PER_CPU_FAULT_INFO, 150 151 /* Get RES mondo queue base phys addre 152 ldx [%g3 + TRAP_PER_CPU_RESUM_MOND 153 154 /* Get RES kernel buffer base phys add 155 ldx [%g3 + TRAP_PER_CPU_RESUM_KBUF 156 157 /* If the first word is non-zero, queu 158 ldxa [%g7 + %g2] ASI_PHYS_USE_EC, % 159 brnz,pn %g1, sun4v_res_mondo_queue_ful 160 nop 161 162 lduw [%g3 + TRAP_PER_CPU_RESUM_QMAS 163 164 /* Remember this entry's offset in %g1 165 mov %g2, %g1 166 167 /* Copy 64-byte queue entry into kerne 168 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 169 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 170 add %g2, 0x08, %g2 171 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 172 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 173 add %g2, 0x08, %g2 174 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 175 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 176 add %g2, 0x08, %g2 177 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 178 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 179 add %g2, 0x08, %g2 180 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 181 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 182 add %g2, 0x08, %g2 183 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 184 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 185 add %g2, 0x08, %g2 186 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 187 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 188 add %g2, 0x08, %g2 189 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 190 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 191 add %g2, 0x08, %g2 192 193 /* Update queue head pointer. */ 194 and %g2, %g4, %g2 195 196 mov INTRQ_RESUM_MONDO_HEAD, %g4 197 stxa %g2, [%g4] ASI_QUEUE 198 membar #Sync 199 200 /* Disable interrupts and save registe 201 * C code. The etrap handling will le 202 * when it's done. 203 */ 204 rdpr %pil, %g2 205 wrpr %g0, PIL_NORMAL_MAX, %pil 206 mov %g1, %g4 207 ba,pt %xcc, etrap_irq 208 rd %pc, %g7 209 #ifdef CONFIG_TRACE_IRQFLAGS 210 call trace_hardirqs_off 211 nop 212 #endif 213 /* Log the event. */ 214 add %sp, PTREGS_OFF, %o0 215 call sun4v_resum_error 216 mov %l4, %o1 217 218 /* Return from trap. */ 219 ba,pt %xcc, rtrap_irq 220 nop 221 222 sun4v_res_mondo_queue_empty: 223 retry 224 225 sun4v_res_mondo_queue_full: 226 /* The queue is full, consolidate our 227 * the head equal to the tail. We'll 228 * Call C code to log the event. 229 */ 230 mov INTRQ_RESUM_MONDO_HEAD, %g2 231 stxa %g4, [%g2] ASI_QUEUE 232 membar #Sync 233 234 rdpr %pil, %g2 235 wrpr %g0, PIL_NORMAL_MAX, %pil 236 ba,pt %xcc, etrap_irq 237 rd %pc, %g7 238 #ifdef CONFIG_TRACE_IRQFLAGS 239 call trace_hardirqs_off 240 nop 241 #endif 242 call sun4v_resum_overflow 243 add %sp, PTREGS_OFF, %o0 244 245 ba,pt %xcc, rtrap_irq 246 nop 247 248 sun4v_nonres_mondo: 249 /* Head offset in %g2, tail offset in 250 mov INTRQ_NONRESUM_MONDO_HEAD, %g2 251 ldxa [%g2] ASI_QUEUE, %g2 252 mov INTRQ_NONRESUM_MONDO_TAIL, %g4 253 ldxa [%g4] ASI_QUEUE, %g4 254 cmp %g2, %g4 255 be,pn %xcc, sun4v_nonres_mondo_queue 256 nop 257 258 /* Get &trap_block[smp_processor_id()] 259 ldxa [%g0] ASI_SCRATCHPAD, %g3 260 sub %g3, TRAP_PER_CPU_FAULT_INFO, 261 262 /* Get RES mondo queue base phys addre 263 ldx [%g3 + TRAP_PER_CPU_NONRESUM_M 264 265 /* Get RES kernel buffer base phys add 266 ldx [%g3 + TRAP_PER_CPU_NONRESUM_K 267 268 /* If the first word is non-zero, queu 269 ldxa [%g7 + %g2] ASI_PHYS_USE_EC, % 270 brnz,pn %g1, sun4v_nonres_mondo_queue_ 271 nop 272 273 lduw [%g3 + TRAP_PER_CPU_NONRESUM_Q 274 275 /* Remember this entry's offset in %g1 276 mov %g2, %g1 277 278 /* Copy 64-byte queue entry into kerne 279 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 280 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 281 add %g2, 0x08, %g2 282 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 283 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 284 add %g2, 0x08, %g2 285 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 286 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 287 add %g2, 0x08, %g2 288 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 289 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 290 add %g2, 0x08, %g2 291 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 292 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 293 add %g2, 0x08, %g2 294 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 295 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 296 add %g2, 0x08, %g2 297 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 298 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 299 add %g2, 0x08, %g2 300 ldxa [%g5 + %g2] ASI_PHYS_USE_EC, % 301 stxa %g3, [%g7 + %g2] ASI_PHYS_USE_ 302 add %g2, 0x08, %g2 303 304 /* Update queue head pointer. */ 305 and %g2, %g4, %g2 306 307 mov INTRQ_NONRESUM_MONDO_HEAD, %g4 308 stxa %g2, [%g4] ASI_QUEUE 309 membar #Sync 310 311 /* Disable interrupts and save registe 312 * C code. The etrap handling will le 313 * when it's done. 314 */ 315 rdpr %pil, %g2 316 wrpr %g0, PIL_NORMAL_MAX, %pil 317 mov %g1, %g4 318 ba,pt %xcc, etrap_irq 319 rd %pc, %g7 320 #ifdef CONFIG_TRACE_IRQFLAGS 321 call trace_hardirqs_off 322 nop 323 #endif 324 /* Log the event. */ 325 add %sp, PTREGS_OFF, %o0 326 call sun4v_nonresum_error 327 mov %l4, %o1 328 329 /* Return from trap. */ 330 ba,pt %xcc, rtrap_irq 331 nop 332 333 sun4v_nonres_mondo_queue_empty: 334 retry 335 336 sun4v_nonres_mondo_queue_full: 337 /* The queue is full, consolidate our 338 * the head equal to the tail. We'll 339 * Call C code to log the event. 340 */ 341 mov INTRQ_NONRESUM_MONDO_HEAD, %g2 342 stxa %g4, [%g2] ASI_QUEUE 343 membar #Sync 344 345 rdpr %pil, %g2 346 wrpr %g0, PIL_NORMAL_MAX, %pil 347 ba,pt %xcc, etrap_irq 348 rd %pc, %g7 349 #ifdef CONFIG_TRACE_IRQFLAGS 350 call trace_hardirqs_off 351 nop 352 #endif 353 call sun4v_nonresum_overflow 354 add %sp, PTREGS_OFF, %o0 355 356 ba,pt %xcc, rtrap_irq 357 nop
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.