Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / diag / assembly / arch / prm / interrupt / interrupt_dmu_cntrl_stall.s
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: interrupt_dmu_cntrl_stall.s
* Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
* 4150 Network Circle, Santa Clara, California 95054, U.S.A.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For the avoidance of doubt, and except that if any non-GPL license
* choice is available it will apply instead, Sun elects to use only
* the General Public License version 2 (GPLv2) at this time for any
* software where a choice of GPL license versions is made
* available with the language indicating that GPLv2 or any later version
* may be used, or where a choice of which version of the GPL is applied is
* otherwise unspecified.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*
* ========== Copyright Header End ============================================
*/
#define HBOOT_HV_ONLY
#define ENABLE_PCIE_LINK_TRAINING
#define ENABLE_INTR0x60 1
#define INTR0x60_EVENT_QUEUE_BASE event_queue_base
#define INTR0x60_MSI_START_ADDRESS 0x0
#define INTR0x60_MONDO_IV 7
#define INTR0x60_MSI_0_NUM 100
#define INTR0x60_MSI_0_EQN 16
#define INTR0x60_MONDO_40_V 1
#define INTR0x60_MONDO_40_MODE 1
#define INTR0x60_MONDO_40_THREAD 0
#define INTR0x60_MONDO_40_CNTRL 0
#define INTR0x60_MSI_1_NUM 101
#define INTR0x60_MSI_1_EQN 17
#define INTR0x60_MONDO_41_V 1
#define INTR0x60_MONDO_41_MODE 1
#define INTR0x60_MONDO_41_THREAD 0
#define INTR0x60_MONDO_41_CNTRL 0
#define INTR0x60_MSI_2_NUM 102
#define INTR0x60_MSI_2_EQN 18
#define INTR0x60_MONDO_42_V 1
#define INTR0x60_MONDO_42_MODE 1
#define INTR0x60_MONDO_42_THREAD 1
#define INTR0x60_MONDO_42_CNTRL 1
#define INTR0x60_MSI_3_NUM 103
#define INTR0x60_MSI_3_EQN 19
#define INTR0x60_MONDO_43_V 1
#define INTR0x60_MONDO_43_MODE 1
#define INTR0x60_MONDO_43_THREAD 2
#define INTR0x60_MONDO_43_CNTRL 2
#define INTR0x60_MSI_4_NUM 104
#define INTR0x60_MSI_4_EQN 20
#define INTR0x60_MONDO_44_V 1
#define INTR0x60_MONDO_44_MODE 1
#define INTR0x60_MONDO_44_THREAD 3
#define INTR0x60_MONDO_44_CNTRL 3
/* Kick off the other MSIs and then stall */
#define INTR0x60_MSI_0_EXTRA_HANDLER_WHILE_BUSY \
call t0_mondo40_handler; \
1: nop
/* Calculate the address for this INO (%g3) in mondo_seen.
* Has interrupt to this INO already occured?
* Record the interrupt as done. */
#define INTR0x60_MSI_EXTRA_HANDLER \
setx mondo_seen, %g7, %g4; \
add %g3, %g4, %g4; \
ldub [%g4], %g5; \
brz %g5, 1f; \
set 1, %g6; \
EXIT_BAD; \
1: stub %g6, [%g4]
#include "interrupt0x60_defines.h"
#define SYNC_THREADS 1
#include "hboot.s"
#include "interrupt0x60_handler.s"
/************************************************************************
Test case code start
************************************************************************/
SECTION .MAIN
.text
.global main
main:
rdpr %pstate, %g7
or %g7, 0x2, %g7 ! Set interrupt enable
wrpr %g7, %pstate
setx iteration_counter, %o1, %o0
ta T_RD_THID ! %o1 = thread ID
brnz %o1, t1_to_t3_main ! branch if not thread 0
nop
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! Thread 0 Start Here
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
t0_main:
setx mondo_seen+40, %l7, %i7
mov 4, %i6 ! Set the number of iterations
t0_clear_mondo_seen:
stb %i6, [%o0] ! iteration counter
stb %g0, [%i7] ! Mondo 40
stb %g0, [%i7+1] ! Mondo 41
stb %g0, [%i7+2] ! Mondo 42
stb %g0, [%i7+3] ! Mondo 43
stb %g0, [%i7+4] ! Mondo 44
/* Kick off first interrupt, trap handler kicks off rest */
t0_kick_msi_0:
! user event to generate MSI msg.
nop ! $EV trig_pc_d(1, @VA(.MAIN.t0_kick_msi_0)) -> EnablePCIeIgCmd ("MSI32", eval(INTR0x60_MSI_0_NUM, 16), 0, 4, 1, *, 1 )
/* Wait for interrupt to occur. */
t0_intr_wait:
#ifdef DTM_ENABLED
setx 0x400, %l1, %l2 ! DTM timeout count
#else
setx 0x100, %l1, %l2 ! timeout count
#endif
t0_intr_wait_loop_top:
ldub [%i7], %l0
cmp %l0, 1
be t0_saw_mondo
dec %l2
brnz %l2, t0_intr_wait_loop_top
nop
t0_timeout:
! $EV trig_pc_d(1, @VA(.MAIN.t0_timeout)) -> printf("ERROR: T0 timeout waiting for mondo 40",*,1)
ba local_test_failed
nop
t0_saw_mondo:
ldub [%i7+2], %l0 ! Check for mondo 42
cmp %l0, 1
bne t0_missed_mondo_42
ldub [%i7+3], %l0 ! Check for mondo 43
cmp %l0, 1
bne t0_missed_mondo_43
ldub [%i7+4], %l0 ! Check for mondo 44
cmp %l0, 1
bne t0_missed_mondo_44
mov 100, %l2
t0_wait_for_mondo_41:
brz %l2, t0_missed_mondo_41
dec %l2
ldub [%i7+1], %l0 ! Check for mondo 41
cmp %l0, 1
bne t0_wait_for_mondo_41
nop
t0_iteration_passed:
dec %i6
brz %i6, t0_done
t0_setup_next_iteration:
/* Rotate controllers and run it again */
best_set_reg(mpeval(PCI_E_INT_MAP_ADDR+PCI_E_INT_MAP_STEP*(40-20)),
%l1, %l2)
mov 5, %l7 /* Number of mondos that need fixing */
mov 0xf, %l6
sllx %l6, PCI_E_INT_MAP_INT_CNTRL_NUM_SHIFT, %l6
t0_setup_next_iteration_top:
ldx [%l2], %l3
and %l3, %l6, %l4 /* Isolate the controller value */
sllx %l4, 1, %l4 /* Generate new controller value */
andcc %l4, %l6, %g0 /* Check for 0000 value */
bne %xcc, 1f
andn %l3, %l6, %l3 /* Clear previous controller value */
srlx %l4, 4, %l4 /* Correct for 0000 value */
1: or %l4, %l3, %l3 /* Merge new value with old CSR value */
stx %l3, [%l2]
dec %l7
brnz %l7, t0_setup_next_iteration_top
add %l2, PCI_E_INT_MAP_STEP, %l2
ba t0_clear_mondo_seen
nop
!Done
t0_done:
stx %g0, [%o0] ! Signal other threads that we are done
ba test_passed
nop
.global t0_mondo40_handler
t0_mondo40_handler: /* This is called from the trap handler */
! $EV trig_pc_d(1, @VA(.MAIN.t0_mondo40_handler)) -> EnablePCIeIgCmd ("MSI32", eval(INTR0x60_MSI_1_NUM, 16), 0, 4, 1, *, 1 )
nop
t0_mondo40_handler_kick_msi_2:
! $EV trig_pc_d(1, @VA(.MAIN.t0_mondo40_handler_kick_msi_2)) -> EnablePCIeIgCmd ("MSI32", eval(INTR0x60_MSI_2_NUM, 16), 0, 4, 1, *, 1 )
nop
t0_mondo40_handler_kick_msi_3:
! $EV trig_pc_d(1, @VA(.MAIN.t0_mondo40_handler_kick_msi_3)) -> EnablePCIeIgCmd ("MSI32", eval(INTR0x60_MSI_3_NUM, 16), 0, 4, 1, *, 1 )
nop
t0_mondo40_handler_kick_msi_4:
! $EV trig_pc_d(1, @VA(.MAIN.t0_mondo40_handler_kick_msi_4)) -> EnablePCIeIgCmd ("MSI32", eval(INTR0x60_MSI_4_NUM, 16), 0, 4, 1, *, 1 )
/* Wait for the new interrupts to arrive and be processed by other threads */
#ifdef DTM_ENABLED
mov 800, %g7 ! Set the maximum time to wait, DTM
#else
mov 200, %g7 ! Set the maximum time to wait
#endif
t0_mondo40_handler_loop_top:
brz %g7, t0_mondo40_handler_loop_timeout
dec %g7
setx mondo_seen+42, %g5, %g6
ldub [%g6], %g5
brz %g5, t0_mondo40_handler_loop_top
ldub [%g6+1], %g5
brz %g5, t0_mondo40_handler_loop_top
ldub [%g6+2], %g5
brz %g5, t0_mondo40_handler_loop_top
nop
/* If we fall to here, all 3 other interrupts have been processed */
t0_mondo40_handler_retl:
retl
nop
t0_mondo40_handler_loop_timeout:
! $EV trig_pc_d(1, @VA(.MAIN.t0_mondo40_handler_loop_timeout)) -> printf("ERROR: T0 timeout waiting for mondos 42 thru 44 to be processed",*,1)
ba local_test_failed
nop
t0_missed_mondo_41:
! $EV trig_pc_d(1, @VA(.MAIN.t0_missed_mondo_41)) -> printf("ERROR: T0 missed mondo 41",*,1)
ba local_test_failed
nop
t0_missed_mondo_42:
! $EV trig_pc_d(1, @VA(.MAIN.t0_missed_mondo_42)) -> printf("ERROR: T0 missed mondo 42",*,1)
ba local_test_failed
nop
t0_missed_mondo_43:
! $EV trig_pc_d(1, @VA(.MAIN.t0_missed_mondo_43)) -> printf("ERROR: T0 missed mondo 43",*,1)
ba local_test_failed
nop
t0_missed_mondo_44:
! $EV trig_pc_d(1, @VA(.MAIN.t0_missed_mondo_44)) -> printf("ERROR: T0 missed mondo 44",*,1)
ba local_test_failed
nop
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! All Threads Except 0 Start Here
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
t1_to_t3_main:
setx mondo_seen+41, %l7, %i7
add %i7, %o1, %i7 ! add thread number to get mondo number
/* Wait for interrupt to occur. */
t1_t3_intr_wait:
#ifdef DTM_ENABLED
setx 0x400, %l1, %l2 ! DTM timeout count
#else
setx 0x100, %l1, %l2 ! timeout count
#endif
t1_t3_intr_wait_loop_top:
ldub [%i7], %l0
cmp %l0, 1
be t1_t3_saw_mondo
dec %l2
brnz %l2, t1_t3_intr_wait_loop_top
nop
t1_t3_timeout:
! $EV trig_pc_d(1, @VA(.MAIN.t1_t3_timeout)) -> printf("ERROR: T1-T3 timeout waiting for mondo",*,1)
ba local_test_failed
nop
t1_t3_saw_mondo:
/* Check if thread 0 has cleared the iteration count */
ldub [%o0], %o2
brz %o2, t1_t3_done
/* If thread 0 has cleared the "mondo seen" flag,
* loop again for next controller settings */
ldub [%i7], %l0
brz %l0, t1_t3_intr_wait
nop
/* Otherwise, keep looping */
ba t1_t3_saw_mondo
nop
!Done
t1_t3_done:
ba test_passed
nop
test_passed:
EXIT_GOOD
local_test_failed:
EXIT_BAD
/************************************************************************
Test case data start
************************************************************************/
.align 1024
.data
user_data_start:
iteration_counter: .byte 4 ! Number of controller configs left to do
.global mondo_seen
mondo_seen: ! One byte per mondo
.skip 60, 0 ! Start with virtual mondo 0 for easy math
.align eval(512*1024)
.global event_queue_base
event_queue_base:
.skip 1024
user_data_end:
.end
/************************************************************************/