Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / diag / assembly / arch / prm / interrupt / interrupt_dmu_intr_reloc.s
CommitLineData
86530b38
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: interrupt_dmu_intr_reloc.s
5* Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
6* 4150 Network Circle, Santa Clara, California 95054, U.S.A.
7*
8* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9*
10* This program is free software; you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by
12* the Free Software Foundation; version 2 of the License.
13*
14* This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details.
18*
19* You should have received a copy of the GNU General Public License
20* along with this program; if not, write to the Free Software
21* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22*
23* For the avoidance of doubt, and except that if any non-GPL license
24* choice is available it will apply instead, Sun elects to use only
25* the General Public License version 2 (GPLv2) at this time for any
26* software where a choice of GPL license versions is made
27* available with the language indicating that GPLv2 or any later version
28* may be used, or where a choice of which version of the GPL is applied is
29* otherwise unspecified.
30*
31* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
32* CA 95054 USA or visit www.sun.com if you need additional information or
33* have any questions.
34*
35*
36* ========== Copyright Header End ============================================
37*/
38#define MAIN_PAGE_HV_ALSO
39#define ENABLE_PCIE_LINK_TRAINING
40#define SYNC_THREADS 0xff
41
42#define H_HT0_Interrupt_0x60
43#define My_HT0_Interrupt_0x60 \
44 call my_trap_code; \
45 nop; \
46 retry; \
47 nop;
48
49#include "hboot.s"
50#include "peu_defines.h"
51#include "ncu_defines.h"
52#include "cmp_macros.h"
53
54
55/************************************************************************
56 Test case code start
57 ************************************************************************/
58.text
59.global main
60
61main:
62 ta T_CHANGE_HPRIV
63 nop
64
65 ! Initialize the global registers.
66 mov %g0, %g1
67 mov %g0, %g2
68 mov %g0, %g3
69 mov %g0, %g4
70 mov %g0, %g5
71 mov %g0, %g6
72 mov %g0, %g7
73
74 ta T_RD_THID
75 cmp %o1, 0x0
76 be main_t0 ! branch if tread 0
77 nop
78 ba main_t1_to_t63 ! branch if not thread 0
79 nop
80
81
82!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
83!
84! Thread 0 Start Here
85!
86!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
87
88main_t0:
89/* Initialize the NCU for the interrupt. */
90
91 ! Disable interrupts
92
93no_intr:
94 rdpr %pstate, %g5
95 xor %g5, 0x2, %g5 ! Reset interrupt enable
96 wrpr %g5, %pstate
97
98 ! Initialize Mondo Interrupt Vector Register
99 ! VECTOR = 63
100
101ncu_mondo_int_vec:
102 set 63, %g1
103 setx MONDO_INT_VEC, %g2, %g3
104 stx %g1, [%g3]
105
106 ! Clear Mondo Interrupt Busy registers.
107
108ncu_mondo_int_busy:
109 setx MONDO_INT_BUSY, %g1, %g2
110 setx MONDO_INT_BUSY_STEP, %g1, %g3
111 setx MONDO_INT_BUSY_COUNT, %g1, %g4
112
113ncu_mondo_int_busy_loop_top:
114 stx %g0, [%g2]
115 add %g2, %g3, %g2
116 cmp %g4, 1
117 bne ncu_mondo_int_busy_loop_top
118 dec %g4
119
120 ! Initialize for MSI interrupt in PIU
121 ! First clear MSI in case one pending.
122
123peu_msi_clear:
124 setx PCI_E_MSI_CLEAR_ADDR, %g1, %g2
125 setx 0x4000000000000000, %g1, %g3
126 stx %g3, [%g2]
127
128 ! Also clear in Interrupt Clear reg.
129
130peu_intr_clear:
131 setx PCI_E_INT_CLEAR_ADDR, %g1, %g2
132 set PCI_E_INT_CLEAR_STEP, %g1
133 sllx %g1, 2, %g1
134 add %g2, %g1, %g2
135 stx %g0, [%g2]
136
137 ! Setup all the event queues.
138
139 ! First the Event Queue Base Address reg.
140 ! Formatted for a bypass address.
141
142peu_eq_base_addr:
143 setx PCI_E_EV_QUE_BASE_ADDRESS_ADDR, %g1, %g2
144 setx user_data_start+0x80000, %g1, %g3
145 setx 0x7ffff80000, %g1, %g5
146 and %g3, %g5, %g3
147 setx 0xfffc000000000000, %g1, %g6
148 or %g3, %g6, %g3
149 stx %g3, [%g2]
150
151 ! Event Queue Control Set reg.s
152
153peu_eq_ctl_set:
154 setx PCI_E_EV_QUE_CTL_SET_ADDR, %g1, %g2
155 setx 0x100000000000, %g1, %g3 ! EN = 1
156 setx PCI_E_EV_QUE_CTL_SET_COUNT, %g1, %g4
157 setx PCI_E_EV_QUE_CTL_SET_STEP, %g1, %g5
158
159peu_eq_clt_set_loop:
160 stx %g3, [%g2]
161 cmp %g4, 1
162 beq peu_msi_addr
163
164 add %g2, %g5, %g2
165 ba peu_eq_clt_set_loop
166 dec %g4
167
168 ! Now enable MSI interrupt
169
170 ! First MSI addressing register
171
172peu_msi_addr:
173 setx PCI_E_MSI_32_ADDRESS_ADDR, %g1, %g2
174 stx %g0, [%g2]
175 setx PCI_E_MSI_64_ADDRESS_ADDR, %g1, %g2
176 stx %g0, [%g2]
177
178 ! MSI Mapping register, only init. the first, the trap handler does the rest
179
180peu_msi_mapping:
181 setx PCI_E_MSI_MAP_ADDR, %g1, %g2
182 setx 0x8000000000000000, %g1, %g3 ! V = 1, EQNUM = 0
183 stx %g3, [%g2]
184 membar #Sync
185
186 ! Now enable Mondo in PIU and set destination thread
187 ! Interrupt Mapping register
188
189peu_int_map_enable:
190 setx PCI_E_INT_MAP_ADDR, %g1, %g5
191 set PCI_E_INT_MAP_STEP, %g1
192 sllx %g1, 2, %g1
193 add %g5, %g1, %g5
194 setx 0x80000040, %g1, %g6 ! valid = 1, thread id = 0
195 stx %g6, [%g5] ! interrupt controller = 1
196
197 ! Enable interrupts
198
199yes_intr:
200 rdpr %pstate, %g5
201 or %g5, 0x2, %g5 ! Set interrupt enable
202 wrpr %g5, %pstate
203
204
205 /* Sync up all the treads. */
206
207sync_t0:
208 SYNC_THREAD_MAIN( local_test_failed, %g1, %g2, %g3 )
209
210
211 /* Loop to kick off the MSI's */
212 /* Note that the interrupt trap handler will take care of doing the relocation */
213
214gen_msis:
215 setx PCI_E_EV_QUE_CTL_SET_COUNT, %g1, %g7
216 sllx %g7, 1, %g7 ! two interrupts per event queue
217#ifdef DMU_INTR_RELOC_VEC
218 srlx %g7, 2, %g7 ! only do 1/4 of them for test vectors.
219#endif
220 setx interrupt_flag, %g1, %g2
221
222gen_msis_loop:
223 st %g0, [%g2] ! clear interrupt occured flag
224
225gen_msi_user_event:
226 ! user event to generate MSI msg.
227 nop ! $EV trig_pc_d(1, @VA(.MAIN.gen_msi_user_event)) -> EnablePCIeIgCmd ("MSI32", 0, 0, 4, 1, *, 1 )
228
229
230 /* Wait for interrupt to occur. */
231
232intr_wait:
233#ifdef DTM_ENABLED
234 setx 0x2000, %g1, %g3 ! DTM timeout count
235#else
236 setx 0x800, %g1, %g3 ! timeout count
237#endif
238
239intr_wait_loop:
240 ld [%g2], %g5
241 cmp %g5, 1
242 be gen_msis_next
243 dec %g3
244
245 cmp %g3, 0
246 bne intr_wait_loop
247 nop
248 ba local_test_failed
249 nop
250
251 /* Have all the needed MSI's been generated? */
252
253gen_msis_next:
254 dec %g7
255 cmp %g7, 0
256 bne gen_msis_loop
257 nop
258
259#ifndef SKIP_EQ_CHECK
260 /* Did each thread get the correct number of interrupts */
261
262intr_check:
263 setx interrupt_counts, %g1, %g2
264 set 8, %g7
265
266intr_check_loop:
267 ld [%g2], %g5
268 cmp %g5, 9
269 bne local_test_failed
270 dec %g7
271
272 cmp %g7, 0
273 bne intr_check_loop
274 add %g2, 4, %g2
275#endif
276
277 /* Tell the other threads we're done. */
278
279t0_flag_done:
280 setx done_flag, %g1, %g2
281 set 1, %g3
282 st %g3, [%g2]
283
284 !Done
285t0_done:
286 ba test_passed
287 nop
288
289
290!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
291!
292! All Threads Except 0 Start Here
293!
294!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
295
296
297main_t1_to_t63:
298 mov %o1, %g6
299 SYNC_THREAD_OTHER( %g6,%g1,%g2 )
300
301 /* Wait thread 0 to indicate we're done. */
302
303t1_t63_intr_wait:
304#ifdef DTM_ENABLED
305 setx 0x10000, %g1, %g2 ! DTM timeout count
306#else
307 setx 0x4000, %g1, %g2 ! timeout count
308#endif
309 setx done_flag, %g1, %g7
310
311t1_t63_intr_wait_loop_top:
312 ld [%g7], %g5
313 cmp %g5, 1
314 be t1_t63_done
315 dec %g2
316
317 cmp %g2, 0
318 bne t1_t63_intr_wait_loop_top
319 nop
320 ba local_test_failed
321 nop
322
323 !Done
324t1_t63_done:
325 ba test_passed
326 nop
327
328
329test_passed:
330 EXIT_GOOD
331
332local_test_failed:
333 EXIT_BAD
334
335
336/**********************************************************************
337 Interrupt trap handler.
338**********************************************************************/
339
340.global my_trap_code
341
342my_trap_code:
343 ta T_RD_THID ! %o1 = thread id
344
345 ! Check Mondo Interrupt Busy reg. for this thread
346
347trap_mondo_busy:
348 setx MONDO_INT_BUSY, %l1, %l2
349 setx MONDO_INT_BUSY_STEP, %l1, %l3
350 mulx %l3, %o1, %l3
351 add %l3, %l2, %l2
352 ldx [%l2], %l4
353 and %l4, 0x40, %l5 ! Is busy bit set?
354 cmp %l5, 0
355 be local_test_failed
356 nop
357
358 ! Check Mondo Interrupt Alias Busy reg.
359
360trap_mondo_abusy:
361 setx MONDO_INT_ABUSY, %l1, %l2
362 ldx [%l2], %l3
363 cmp %l3, %l4 ! ABUSY = BUSY ?
364 bne local_test_failed
365 nop
366
367 ! Check Mondo Interrupt Data 0/1 against Mondo Interrupt Alias Data 0/1
368
369trap_mondo_data0:
370 setx MONDO_INT_DATA0, %l1, %l2
371 setx MONDO_INT_DATA0_STEP, %l1, %l3
372 mulx %l3, %o1, %l3
373 add %l3, %l2, %l2
374 ldx [%l2], %l0 ! %l0 = mondo_int_busy0
375
376trap_mondo_adata0:
377 setx MONDO_INT_ADATA0, %l1, %l4 ! %l6 = mondo_int_abusy0, inc. INO
378 ldx [%l4], %l6
379 cmp %l6, %l0
380 bne local_test_failed
381 nop
382
383trap_mondo_data1:
384 setx MONDO_INT_DATA1, %l1, %l2
385 setx MONDO_INT_DATA1_STEP, %l1, %l3
386 mulx %l3, %o1, %l3
387 add %l3, %l2, %l2
388 ldx [%l2], %l0 ! %l0 = mondo_int_busy1
389
390trap_mondo_adata1:
391 setx MONDO_INT_ADATA1, %l1, %l4 ! %l5 = mondo_int_abusy1
392 ldx [%l4], %l5
393 cmp %l5, %l0
394 bne local_test_failed
395 nop
396
397 ! Is this the INO expected?
398
399trap_ino_check:
400 and %l6, 0x3f, %l6 ! %l6 = INO
401 sub %l6, 24, %l6 ! %l6 = event queue number
402 setx eq_num, %l1, %l2 ! Do NOT change %l6 until trap_inc_queue!
403 ld [%l2], %l2
404#ifndef SKIP_EQ_CHECK
405 cmp %l2, %l6
406 bne local_test_failed
407 nop
408#endif
409
410 ! Was the correct event queue used?
411
412trap_eq_check1:
413 setx PCI_E_MSI_MAP_ADDR, %l1, %l2
414 ldx [%l2], %l1
415 and %l1, 0x3f, %l1
416 cmp %l1, %l6
417 bne local_test_failed
418 nop
419
420 ! Check Mondo status in PIU
421
422 ! Interrupt Clear reg.
423
424trap_peu_intr_clear:
425 setx PCI_E_INT_CLEAR_ADDR, %l1, %l2
426 set PCI_E_INT_CLEAR_STEP, %l3
427 add %l6, 4, %l4
428 mulx %l3, %l4, %l3
429 add %l2, %l3, %l2
430 ldx [%l2], %l0
431 cmp %l0, 3 ! Should be in pending state
432 bne local_test_failed
433 nop
434
435 ! MSI Mapping reg.
436
437trap_peu_msi_map:
438 setx PCI_E_MSI_MAP_ADDR, %l1, %l2
439 setx 0xc000000000000000, %l1, %l4 ! V = 1, EQWR_N = %l6
440 or %l4, %l6, %l4
441 ldx [%l2], %l0
442 cmp %l0, %l4
443 bne local_test_failed
444 nop
445
446 ! Clear the Mondo interrupt in the PIU
447
448 ! MSI Clear reg.
449
450trap_msi_clear:
451 setx PCI_E_MSI_CLEAR_ADDR, %l1, %l2
452 setx 0x4000000000000000, %l1, %l3
453 stx %l3, [%l2] ! clear EQWR in MSI map reg.
454 membar #Sync
455
456 ! Disable Event Queue via Control Clear reg.
457
458trap_eq_control_clear:
459 setx PCI_E_EV_QUE_CTL_CLEAR_ADDR, %l1, %l2
460 set PCI_E_EV_QUE_CTL_CLEAR_STEP, %l4
461 mulx %l4, %l6, %l4
462 add %l2, %l4, %l2
463 setx 0x100000000000, %l1, %l3 ! DIS = 1
464 stx %l3, [%l2]
465 membar #Sync
466
467 ! Set Event Queue Head = Event Queue Tail
468 ! Also check that they are not equal.
469
470trap_mondo_clear:
471 setx PCI_E_EV_QUE_TAIL_ADDR, %l1, %l2
472 set PCI_E_EV_QUE_TAIL_STEP, %l4
473 mulx %l4, %l6, %l4
474 add %l2, %l4, %l2
475 ldx [%l2], %l0
476 setx PCI_E_EV_QUE_HEAD_ADDR, %l1, %l2
477 set PCI_E_EV_QUE_HEAD_STEP, %l4
478 mulx %l4, %l6, %l4
479 add %l2, %l4, %l2
480 ldx [%l2], %l1
481 cmp %l0, %l1
482 be local_test_failed
483 nop
484 stx %l0, [%l2]
485 membar #Sync
486
487 ! Interrupt Clear reg.
488
489trap_intr_clear:
490 setx PCI_E_INT_CLEAR_ADDR, %l1, %l2
491 set PCI_E_INT_CLEAR_STEP, %l3
492 add %l6, 4, %l1
493 mulx %l3, %l1, %l3
494 add %l2, %l3, %l2
495 stx %g0, [%l2]
496 membar #Sync
497
498 ! Clear the mondo interrupt in the NCU
499
500trap_mondo_intr_clear:
501 setx MONDO_INT_ABUSY, %l0, %l1
502 stx %g0, [%l1]
503 membar #Sync
504
505 ldx [%l1], %l2
506 and %l2, 0x40, %l2
507 cmp %l2, 0 ! Busy should be cleared
508 bne local_test_failed
509 nop
510
511 ! Clear the interrupt in the core
512
513trap_clear_asi_intr_r:
514 ldxa [%g0]ASI_SWVR_INTR_R, %l5
515 cmp %l5, 63 ! check for correct vector number
516 bne local_test_failed
517 nop
518
519 ! Set up to do relocation
520
521 ! First are we done with the current event queue?
522
523trap_eq_check:
524 setx odd_even, %l1, %l2
525 ld [%l2], %l0
526 cmp %l0, 0
527 bne trap_next_eq
528 nop
529
530 ! Keep same event queue, but do the relocation,
531 ! i.e. change thread interrupt is sent to.
532
533 set 1, %l1
534 st %l1, [%l2]
535 ba trap_inc_thread
536 nop
537
538 ! Go to the next event queue
539
540trap_next_eq:
541 st %g0, [%l2]
542 setx eq_num, %l1, %l2
543 inc %l6
544 st %l6, [%l2]
545
546 ! Initialize for the new event queue
547
548trap_inc_queue:
549 setx PCI_E_MSI_MAP_ADDR, %l1, %l2
550 setx 0x8000000000000000, %l1, %l3 ! V = 1
551 or %l3, %l6, %l3 ! or in new event queue number
552 stx %l3, [%l2]
553
554 ! Increment the thread to send the next interrupt to
555
556trap_inc_thread:
557 setx PCI_E_INT_MAP_ADDR, %l1, %l5
558 set PCI_E_INT_MAP_STEP, %l1
559 add %l6, 4, %l7 ! index = event queue # + 4
560 mulx %l1, %l7, %l1
561 add %l5, %l1, %l5
562 setx 0x80000040, %l1, %l2 ! valid = 1, intr. controller #1
563 add %o1, 1, %l7
564 and %l7, 0x7, %l7
565 sllx %l7, 25, %l4
566 or %l2, %l4, %l2 ! or in destination thread id
567 stx %l2, [%l5]
568
569 ! Enable the Event Queue
570
571trap_enable_eq:
572 setx PCI_E_EV_QUE_CTL_SET_ADDR, %l1, %l2
573 setx PCI_E_EV_QUE_CTL_SET_STEP, %l1, %l4
574 mulx %l4, %l6, %l4
575 add %l2, %l4, %l2
576 setx 0x100000000000, %l1, %l3 ! EN = 1
577 stx %l3, [%l2]
578 membar #Sync
579
580 ! Increment thread's interrupt count.
581
582trap_inc_intr_count:
583 sllx %o1, 2, %l7
584 setx interrupt_counts, %l1, %l3
585 add %l7, %l3, %l7 ! %l7 = pointer to thread's interrupt count
586 ld [%l7], %l6
587 inc %l6
588 st %l6, [%l7]
589
590 ! Flag that an interrupt occured
591
592trap_flag_intr:
593 setx interrupt_flag, %l0, %l1
594 ld [%l1], %l2
595 inc %l2
596 st %l2, [%l1]
597
598 ! Done.
599
600trap_done:
601 jmpl %o7+0x8, %g0
602 nop
603
604
605
606/************************************************************************
607 Test case data start
608************************************************************************/
609
610.align 1024
611.data
612user_data_start:
613 .word 0xffffffff
614 .word 0xffffffff
615 .word 0xffffffff
616 .word 0xffffffff
617
618 /* 1 word per thread to count number of interrupts taken */
619interrupt_counts:
620 .word 0
621 .word 0
622 .word 0
623 .word 0
624 .word 0
625 .word 0
626 .word 0
627 .word 0
628
629interrupt_flag:
630 .word 0
631 .word 0
632
633done_flag:
634 .word 0x0
635 .word 0x0
636
637odd_even:
638 .word 0x0
639 .word 0x0
640
641eq_num:
642 .word 0x0
643 .word 0x0
644
645user_data_end:
646.end
647
648/************************************************************************/