| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 1 | /* | 
|  | 2 | * Assembly Language Functions for MIPS MT SMTC support | 
|  | 3 | */ | 
|  | 4 |  | 
|  | 5 | /* | 
|  | 6 | * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */ | 
|  | 7 |  | 
|  | 8 | #include <asm/regdef.h> | 
|  | 9 | #include <asm/asmmacro.h> | 
|  | 10 | #include <asm/stackframe.h> | 
| Ralf Baechle | 6e74bae | 2006-08-16 14:05:11 +0100 | [diff] [blame] | 11 | #include <asm/irqflags.h> | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 12 |  | 
|  | 13 | /* | 
|  | 14 | * "Software Interrupt" linkage. | 
|  | 15 | * | 
|  | 16 | * This is invoked when an "Interrupt" is sent from one TC to another, | 
|  | 17 | * where the TC to be interrupted is halted, has it's Restart address | 
|  | 18 | * and Status values saved by the "remote control" thread, then modified | 
|  | 19 | * to cause execution to begin here, in kenel mode. This code then | 
|  | 20 | * disguises the TC state as that of an exception and transfers | 
|  | 21 | * control to the general exception or vectored interrupt handler. | 
|  | 22 | */ | 
|  | 23 | .set noreorder | 
|  | 24 |  | 
|  | 25 | /* | 
|  | 26 | The __smtc_ipi_vector would use k0 and k1 as temporaries and | 
|  | 27 | 1) Set EXL (this is per-VPE, so this can't be done by proxy!) | 
|  | 28 | 2) Restore the K/CU and IXMT bits to the pre "exception" state | 
|  | 29 | (EXL means no interrupts and access to the kernel map). | 
|  | 30 | 3) Set EPC to be the saved value of TCRestart. | 
|  | 31 | 4) Jump to the exception handler entry point passed by the sender. | 
|  | 32 |  | 
|  | 33 | CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED?? | 
|  | 34 | */ | 
|  | 35 |  | 
|  | 36 | /* | 
|  | 37 | * Reviled and slandered vision: Set EXL and restore K/CU/IXMT | 
|  | 38 | * state of pre-halt thread, then save everything and call | 
|  | 39 | * thought some function pointer to imaginary_exception, which | 
|  | 40 | * will parse a register value or memory message queue to | 
|  | 41 | * deliver things like interprocessor interrupts. On return | 
|  | 42 | * from that function, jump to the global ret_from_irq code | 
|  | 43 | * to invoke the scheduler and return as appropriate. | 
|  | 44 | */ | 
|  | 45 |  | 
|  | 46 | #define PT_PADSLOT4 (PT_R0-8) | 
|  | 47 | #define PT_PADSLOT5 (PT_R0-4) | 
|  | 48 |  | 
|  | 49 | .text | 
|  | 50 | .align 5 | 
|  | 51 | FEXPORT(__smtc_ipi_vector) | 
|  | 52 | .set	noat | 
|  | 53 | /* Disable thread scheduling to make Status update atomic */ | 
|  | 54 | DMT	27					# dmt	k1 | 
| Ralf Baechle | 4277ff5 | 2006-06-03 22:40:15 +0100 | [diff] [blame] | 55 | _ehb | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 56 | /* Set EXL */ | 
|  | 57 | mfc0	k0,CP0_STATUS | 
|  | 58 | ori	k0,k0,ST0_EXL | 
|  | 59 | mtc0	k0,CP0_STATUS | 
| Ralf Baechle | 4277ff5 | 2006-06-03 22:40:15 +0100 | [diff] [blame] | 60 | _ehb | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 61 | /* Thread scheduling now inhibited by EXL. Restore TE state. */ | 
|  | 62 | andi	k1,k1,VPECONTROL_TE | 
|  | 63 | beqz	k1,1f | 
|  | 64 | emt | 
|  | 65 | 1: | 
|  | 66 | /* | 
|  | 67 | * The IPI sender has put some information on the anticipated | 
|  | 68 | * kernel stack frame.  If we were in user mode, this will be | 
|  | 69 | * built above the saved kernel SP.  If we were already in the | 
|  | 70 | * kernel, it will be built above the current CPU SP. | 
|  | 71 | * | 
|  | 72 | * Were we in kernel mode, as indicated by CU0? | 
|  | 73 | */ | 
|  | 74 | sll	k1,k0,3 | 
|  | 75 | .set noreorder | 
|  | 76 | bltz	k1,2f | 
|  | 77 | move	k1,sp | 
|  | 78 | .set reorder | 
|  | 79 | /* | 
|  | 80 | * If previously in user mode, set CU0 and use kernel stack. | 
|  | 81 | */ | 
|  | 82 | li	k1,ST0_CU0 | 
|  | 83 | or	k1,k1,k0 | 
|  | 84 | mtc0	k1,CP0_STATUS | 
| Ralf Baechle | 4277ff5 | 2006-06-03 22:40:15 +0100 | [diff] [blame] | 85 | _ehb | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 86 | get_saved_sp | 
|  | 87 | /* Interrupting TC will have pre-set values in slots in the new frame */ | 
|  | 88 | 2:	subu	k1,k1,PT_SIZE | 
|  | 89 | /* Load TCStatus Value */ | 
|  | 90 | lw	k0,PT_TCSTATUS(k1) | 
|  | 91 | /* Write it to TCStatus to restore CU/KSU/IXMT state */ | 
|  | 92 | mtc0	k0,$2,1 | 
| Ralf Baechle | 4277ff5 | 2006-06-03 22:40:15 +0100 | [diff] [blame] | 93 | _ehb | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 94 | lw	k0,PT_EPC(k1) | 
|  | 95 | mtc0	k0,CP0_EPC | 
|  | 96 | /* Save all will redundantly recompute the SP, but use it for now */ | 
|  | 97 | SAVE_ALL | 
|  | 98 | CLI | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 99 | TRACE_IRQS_OFF | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 100 | /* Function to be invoked passed stack pad slot 5 */ | 
|  | 101 | lw	t0,PT_PADSLOT5(sp) | 
|  | 102 | /* Argument from sender passed in stack pad slot 4 */ | 
| Atsushi Nemoto | f431baa | 2006-10-09 01:24:23 +0900 | [diff] [blame] | 103 | lw	a0,PT_PADSLOT4(sp) | 
| Ralf Baechle | cb56837 | 2006-10-31 22:49:04 +0000 | [diff] [blame] | 104 | LONG_L	s0, TI_REGS($28) | 
|  | 105 | LONG_S	sp, TI_REGS($28) | 
|  | 106 | PTR_LA	ra, ret_from_irq | 
| Atsushi Nemoto | f431baa | 2006-10-09 01:24:23 +0900 | [diff] [blame] | 107 | jr	t0 | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 108 |  | 
|  | 109 | /* | 
|  | 110 | * Called from idle loop to provoke processing of queued IPIs | 
|  | 111 | * First IPI message in queue passed as argument. | 
|  | 112 | */ | 
|  | 113 |  | 
|  | 114 | LEAF(self_ipi) | 
|  | 115 | /* Before anything else, block interrupts */ | 
|  | 116 | mfc0	t0,CP0_TCSTATUS | 
|  | 117 | ori	t1,t0,TCSTATUS_IXMT | 
|  | 118 | mtc0	t1,CP0_TCSTATUS | 
| Ralf Baechle | 4277ff5 | 2006-06-03 22:40:15 +0100 | [diff] [blame] | 119 | _ehb | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 120 | /* We know we're in kernel mode, so prepare stack frame */ | 
|  | 121 | subu	t1,sp,PT_SIZE | 
|  | 122 | sw	ra,PT_EPC(t1) | 
|  | 123 | sw	a0,PT_PADSLOT4(t1) | 
|  | 124 | la	t2,ipi_decode | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 125 | sw	t2,PT_PADSLOT5(t1) | 
|  | 126 | /* Save pre-disable value of TCStatus */ | 
|  | 127 | sw	t0,PT_TCSTATUS(t1) | 
|  | 128 | j	__smtc_ipi_vector | 
|  | 129 | nop | 
|  | 130 | END(self_ipi) |