~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sparc/kernel/sun4v_ivec.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 /* sun4v_ivec.S: Sun4v interrupt vector handling.
  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 %g4.
 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_empty
 24          nop
 25 
 26         /* Get &trap_block[smp_processor_id()] into %g4.  */
 27         ldxa    [%g0] ASI_SCRATCHPAD, %g4
 28         sub     %g4, TRAP_PER_CPU_FAULT_INFO, %g4
 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_processor_id()] */
 37         sethi   %hi(cpu_mondo_counter), %g5
 38         or      %g5, %lo(cpu_mondo_counter), %g5
 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 address into %g7.  */
 46         ldx     [%g4 + TRAP_PER_CPU_CPU_MONDO_PA], %g7
 47 
 48         /* Now get the cross-call arguments and handler PC, same
 49          * layout as sun4u:
 50          *
 51          * 1st 64-bit word: low half is 32-bit PC, put into %g3 and jmpl to it
 52          *                  high half is context arg to MMU flushes, into %g5
 53          * 2nd 64-bit word: 64-bit arg, load into %g1
 54          * 3rd 64-bit word: 64-bit arg, load into %g7
 55          */
 56         ldxa    [%g7 + %g2] ASI_PHYS_USE_EC, %g3
 57         add     %g2, 0x8, %g2
 58         srlx    %g3, 32, %g5
 59         ldxa    [%g7 + %g2] ASI_PHYS_USE_EC, %g1
 60         add     %g2, 0x8, %g2
 61         srl     %g3, 0, %g3
 62         ldxa    [%g7 + %g2] ASI_PHYS_USE_EC, %g7
 63         add     %g2, 0x40 - 0x8 - 0x8, %g2
 64 
 65         /* Update queue head pointer.  */
 66         lduw    [%g4 + TRAP_PER_CPU_CPU_MONDO_QMASK], %g4
 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 %g4.  */
 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_empty
 87          nop
 88 
 89         /* Get &trap_block[smp_processor_id()] into %g4.  */
 90         ldxa    [%g0] ASI_SCRATCHPAD, %g4
 91         sub     %g4, TRAP_PER_CPU_FAULT_INFO, %g4
 92 
 93         /* Get DEV mondo queue base phys address into %g5.  */
 94         ldx     [%g4 + TRAP_PER_CPU_DEV_MONDO_PA], %g5
 95 
 96         /* Load IVEC into %g3.  */
 97         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
 98         add     %g2, 0x40, %g2
 99 
100         /* XXX There can be a full 64-byte block of data here.
101          * XXX This is how we can get at MSI vector data.
102          * XXX Current we do not capture this, but when we do we'll
103          * XXX need to add a 64-byte storage area in the struct ino_bucket
104          * XXX or the struct irq_desc.
105          */
106 
107         /* Update queue head pointer, this frees up some registers.  */
108         lduw    [%g4 + TRAP_PER_CPU_DEV_MONDO_QMASK], %g4
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 ~bucket_phys_addr  */
118         brlz,pt %g3, 1f
119          xnor   %g3, %g0, %g4
120 
121         /* Get __pa(&ivector_table[IVEC]) into %g4.  */
122         sethi   %hi(ivector_table_pa), %g4
123         ldx     [%g4 + %lo(ivector_table_pa)], %g4
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 << pil) in %softint.  */
132         wr      %g0, 1 << PIL_DEVICE_IRQ, %set_softint
133 
134 sun4v_dev_mondo_queue_empty:
135         retry
136 
137 sun4v_res_mondo:
138         /* Head offset in %g2, tail offset in %g4.  */
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_empty
145          nop
146 
147         /* Get &trap_block[smp_processor_id()] into %g3.  */
148         ldxa    [%g0] ASI_SCRATCHPAD, %g3
149         sub     %g3, TRAP_PER_CPU_FAULT_INFO, %g3
150 
151         /* Get RES mondo queue base phys address into %g5.  */
152         ldx     [%g3 + TRAP_PER_CPU_RESUM_MONDO_PA], %g5
153 
154         /* Get RES kernel buffer base phys address into %g7.  */
155         ldx     [%g3 + TRAP_PER_CPU_RESUM_KBUF_PA], %g7
156 
157         /* If the first word is non-zero, queue is full.  */
158         ldxa    [%g7 + %g2] ASI_PHYS_USE_EC, %g1
159         brnz,pn %g1, sun4v_res_mondo_queue_full
160          nop
161 
162         lduw    [%g3 + TRAP_PER_CPU_RESUM_QMASK], %g4
163 
164         /* Remember this entry's offset in %g1.  */
165         mov     %g2, %g1
166 
167         /* Copy 64-byte queue entry into kernel buffer.  */
168         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
169         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
170         add     %g2, 0x08, %g2
171         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
172         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
173         add     %g2, 0x08, %g2
174         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
175         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
176         add     %g2, 0x08, %g2
177         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
178         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
179         add     %g2, 0x08, %g2
180         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
181         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
182         add     %g2, 0x08, %g2
183         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
184         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
185         add     %g2, 0x08, %g2
186         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
187         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
188         add     %g2, 0x08, %g2
189         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
190         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
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 register state so we can call
201          * C code.  The etrap handling will leave %g4 in %l4 for us
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 damage by setting
227          * the head equal to the tail.  We'll just trap again otherwise.
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 %g4.  */
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_empty
256          nop
257 
258         /* Get &trap_block[smp_processor_id()] into %g3.  */
259         ldxa    [%g0] ASI_SCRATCHPAD, %g3
260         sub     %g3, TRAP_PER_CPU_FAULT_INFO, %g3
261 
262         /* Get RES mondo queue base phys address into %g5.  */
263         ldx     [%g3 + TRAP_PER_CPU_NONRESUM_MONDO_PA], %g5
264 
265         /* Get RES kernel buffer base phys address into %g7.  */
266         ldx     [%g3 + TRAP_PER_CPU_NONRESUM_KBUF_PA], %g7
267 
268         /* If the first word is non-zero, queue is full.  */
269         ldxa    [%g7 + %g2] ASI_PHYS_USE_EC, %g1
270         brnz,pn %g1, sun4v_nonres_mondo_queue_full
271          nop
272 
273         lduw    [%g3 + TRAP_PER_CPU_NONRESUM_QMASK], %g4
274 
275         /* Remember this entry's offset in %g1.  */
276         mov     %g2, %g1
277 
278         /* Copy 64-byte queue entry into kernel buffer.  */
279         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
280         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
281         add     %g2, 0x08, %g2
282         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
283         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
284         add     %g2, 0x08, %g2
285         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
286         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
287         add     %g2, 0x08, %g2
288         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
289         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
290         add     %g2, 0x08, %g2
291         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
292         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
293         add     %g2, 0x08, %g2
294         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
295         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
296         add     %g2, 0x08, %g2
297         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
298         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
299         add     %g2, 0x08, %g2
300         ldxa    [%g5 + %g2] ASI_PHYS_USE_EC, %g3
301         stxa    %g3, [%g7 + %g2] ASI_PHYS_USE_EC
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 register state so we can call
312          * C code.  The etrap handling will leave %g4 in %l4 for us
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 damage by setting
338          * the head equal to the tail.  We'll just trap again otherwise.
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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php