| 1 | ################################################################################# | 
|---|
| 2 | #       File : reset.s | 
|---|
| 3 | #       Author : Alain Greiner | 
|---|
| 4 | #       Date : 15/04/2011 | 
|---|
| 5 | ################################################################################# | 
|---|
| 6 | #       This is a boot code for a generic multi-clusters / multi-processors | 
|---|
| 7 | #       TSAR architecture (up to 256 clusters / up to 4  processors per cluster). | 
|---|
| 8 | #       There is one XICU, one TTY, one DMA and one stack segment per cluster. | 
|---|
| 9 | #       segment base adresses = base + cluster_segment_increment*cluster_id | 
|---|
| 10 | #       - Each processor initializes the stack pointer ($29) depending on pid. | 
|---|
| 11 | #       - Only processor 0 initializes the Interrupt vector (TTY, DMA & IOC). | 
|---|
| 12 | #       - Each processor initialises its private ICU mask register. | 
|---|
| 13 | #       - Each processor initializes the Status Register (SR) | 
|---|
| 14 | #       - Each processor initializes the EPC register, and jumps to the main | 
|---|
| 15 | #         address in kernel mode... | 
|---|
| 16 | ################################################################################# | 
|---|
| 17 |  | 
|---|
| 18 | .section .reset,"ax",@progbits | 
|---|
| 19 |  | 
|---|
| 20 | .extern seg_stack_base | 
|---|
| 21 | .extern seg_icu_base | 
|---|
| 22 | .extern _interrupt_vector | 
|---|
| 23 | .extern _isr_tty_get | 
|---|
| 24 | .extern _isr_dma | 
|---|
| 25 | .extern _isr_ioc | 
|---|
| 26 |  | 
|---|
| 27 | .extern NB_PROCS | 
|---|
| 28 | .extern NB_CLUSTERS | 
|---|
| 29 |  | 
|---|
| 30 | .globl  reset                           # makes reset an external symbol | 
|---|
| 31 | .ent    reset | 
|---|
| 32 | .align  2 | 
|---|
| 33 |  | 
|---|
| 34 | reset: | 
|---|
| 35 | .set noreorder | 
|---|
| 36 |  | 
|---|
| 37 | # computes proc_id, local_id, cluster_id, and cluster_increment | 
|---|
| 38 | mfc0    $26,    $15,    1 | 
|---|
| 39 | andi    $10,    $26,    0x3FF       # $10 <= proc_id (at most 1024 processors) | 
|---|
| 40 | la      $26,    NB_PROCS            # $26 <= number of processors per cluster | 
|---|
| 41 | divu    $10,    $26 | 
|---|
| 42 | mfhi    $11                         # $11 <= local_id = proc_id % NB_PROCS | 
|---|
| 43 | mflo    $12                         # $12 <= cluster_id = proc_id / NB_PROCS | 
|---|
| 44 | la      $26,    NB_CLUSTERS | 
|---|
| 45 | li      $13,    0x80000000 | 
|---|
| 46 | divu    $13,    $26 | 
|---|
| 47 | mflo    $14 | 
|---|
| 48 | sll     $14,    1                   # $14 <= cluster_increment = 4G / NB_CLUSTERS | 
|---|
| 49 | mult    $14,    $12 | 
|---|
| 50 | mflo    $13                         # $13 <= cluster_id * cluster_increment | 
|---|
| 51 |  | 
|---|
| 52 | # initializes stack pointer depending on both the local_id and the cluster_id | 
|---|
| 53 | la      $27,    seg_stack_base | 
|---|
| 54 | addu    $27,    $27,    $13         # $27 <= seg_stack_base + cluster_id * increment | 
|---|
| 55 | li      $26,    0x10000             # $26 <= 64K | 
|---|
| 56 | addi    $25,    $11,    1           # $25 <= local_id + 1 | 
|---|
| 57 | mult    $25,    $26 | 
|---|
| 58 | mflo    $24                         # $24 <= 64K * (local_id+1) | 
|---|
| 59 | addu    $29,    $27,    $24         # $29 <= seg_stack_base + (cluster_id*increment) + (local_id+1)*64K | 
|---|
| 60 |  | 
|---|
| 61 | # in each cluster, each processor initializes its private XICU mask register | 
|---|
| 62 | # in each cluster, the ICU base address depends on the cluster_id | 
|---|
| 63 | la      $20,    seg_icu_base | 
|---|
| 64 | addu    $20,    $20,    $13         # $20 <= seg_icu_base + cluster_id*cluster_increment | 
|---|
| 65 | la      $21,    _reset_switch | 
|---|
| 66 | sll     $22,    $11,    2           # $22 <= local_id*4 | 
|---|
| 67 | addu    $23,    $21,    $22         # $23 <= &_reset_switch[local_id*4] | 
|---|
| 68 | lw      $24,    0($23) | 
|---|
| 69 | jr      $24 | 
|---|
| 70 | nop | 
|---|
| 71 | _reset_proc0: | 
|---|
| 72 | li      $13,    0b010010000000      # offset for MSK_HWI_ENABLE & proc[0] | 
|---|
| 73 | addu    $13,    $20,    $13 | 
|---|
| 74 | li      $27,    0x111               # TTY[0] DMA[0] IOC | 
|---|
| 75 | sw      $27,    0($13)              # MASK[0] | 
|---|
| 76 | j       _reset_itvector | 
|---|
| 77 | _reset_proc1: | 
|---|
| 78 | li      $13,    0b010010000100      # offset for MSK_HWI_ENABLE & proc[1] | 
|---|
| 79 | addu    $13,    $20,    $13 | 
|---|
| 80 | li      $27,    0x022               # TTY[1] DMA[1] | 
|---|
| 81 | sw      $27,    0($13)              # MASK[1] | 
|---|
| 82 | j       _reset_itvector | 
|---|
| 83 | _reset_proc2: | 
|---|
| 84 | li      $13,    0b010010001000      # offset for MSK_HWI_ENABLE & proc[2] | 
|---|
| 85 | addu    $13,    $20,    $13 | 
|---|
| 86 | li      $27,    0x044               # TTY[2] DMA[2] | 
|---|
| 87 | sw      $27,    0($13)              # MASK[2] | 
|---|
| 88 | j       _reset_itvector | 
|---|
| 89 | _reset_proc3: | 
|---|
| 90 | li      $13,    0b010010001100      # offset for MSK_HWI_ENABLE & proc[3] | 
|---|
| 91 | addu    $13,    $20,    $13 | 
|---|
| 92 | li      $27,    0x088               # TTY[3] DMA[3] | 
|---|
| 93 | sw      $27,    0($13)              # MASK[3] | 
|---|
| 94 | j       _reset_itvector | 
|---|
| 95 | nop | 
|---|
| 96 |  | 
|---|
| 97 | _reset_switch: | 
|---|
| 98 | .word       _reset_proc0 | 
|---|
| 99 | .word       _reset_proc1 | 
|---|
| 100 | .word       _reset_proc2 | 
|---|
| 101 | .word       _reset_proc3 | 
|---|
| 102 |  | 
|---|
| 103 | # only processor 0 in cluster 0 initializes interrupt vector | 
|---|
| 104 |  | 
|---|
| 105 | _reset_itvector: | 
|---|
| 106 | bne     $10,    $0,    _reset_end | 
|---|
| 107 | la      $26,    _interrupt_vector   # interrupt vector address | 
|---|
| 108 | la      $27,    _isr_tty_get | 
|---|
| 109 | sw      $27,    0($26)              # interrupt_vector[0] <= _isr_tty_get | 
|---|
| 110 | sw      $27,    4($26)              # interrupt_vector[1] <= _isr_tty_get | 
|---|
| 111 | sw      $27,    8($26)              # interrupt_vector[2] <= _isr_tty_get | 
|---|
| 112 | sw      $27,   12($26)              # interrupt_vector[3] <= _isr_tty_get | 
|---|
| 113 | la      $27,    _isr_dma | 
|---|
| 114 | sw      $27,   16($26)              # interrupt_vector[4] <= _isr_dma | 
|---|
| 115 | sw      $27,   20($26)              # interrupt_vector[5] <= _isr_dma | 
|---|
| 116 | sw      $27,   24($26)              # interrupt_vector[6] <= _isr_dma | 
|---|
| 117 | sw      $27,   28($26)              # interrupt_vector[7] <= _isr_dma | 
|---|
| 118 | la      $27,    _isr_ioc | 
|---|
| 119 | sw      $27,   32($26)              # interrupt_vector[8] <= _isr_ioc | 
|---|
| 120 |  | 
|---|
| 121 | _reset_end: | 
|---|
| 122 |  | 
|---|
| 123 | # initializes SR register | 
|---|
| 124 | li      $26,    0x0000FF01 | 
|---|
| 125 | mtc0    $26,    $12                 # SR <= kernel mode / IRQ enable | 
|---|
| 126 |  | 
|---|
| 127 | # jumps to main in kernel mode | 
|---|
| 128 | la      $26,    main | 
|---|
| 129 | jr      $26 | 
|---|
| 130 | nop | 
|---|
| 131 |  | 
|---|
| 132 | .end        reset | 
|---|
| 133 |  | 
|---|
| 134 | .set reorder | 
|---|