blob: 2866863a39df269da6ba9710acf96808197e33ea [file] [log] [blame]
Ralf Baechle41c594a2006-04-05 09:45:45 +01001/*
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 Baechle6e74bae2006-08-16 14:05:11 +010011#include <asm/irqflags.h>
Ralf Baechle41c594a2006-04-05 09:45:45 +010012
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/*
26The __smtc_ipi_vector would use k0 and k1 as temporaries and
271) Set EXL (this is per-VPE, so this can't be done by proxy!)
282) Restore the K/CU and IXMT bits to the pre "exception" state
29 (EXL means no interrupts and access to the kernel map).
303) Set EPC to be the saved value of TCRestart.
314) Jump to the exception handler entry point passed by the sender.
32
33CAN 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
51FEXPORT(__smtc_ipi_vector)
Steven J. Hill2a0b24f2013-03-25 12:15:55 -050052#ifdef CONFIG_CPU_MICROMIPS
53 nop
54#endif
Ralf Baechle41c594a2006-04-05 09:45:45 +010055 .set noat
56 /* Disable thread scheduling to make Status update atomic */
57 DMT 27 # dmt k1
Ralf Baechle4277ff52006-06-03 22:40:15 +010058 _ehb
Ralf Baechle41c594a2006-04-05 09:45:45 +010059 /* Set EXL */
60 mfc0 k0,CP0_STATUS
61 ori k0,k0,ST0_EXL
62 mtc0 k0,CP0_STATUS
Ralf Baechle4277ff52006-06-03 22:40:15 +010063 _ehb
Ralf Baechle41c594a2006-04-05 09:45:45 +010064 /* Thread scheduling now inhibited by EXL. Restore TE state. */
65 andi k1,k1,VPECONTROL_TE
66 beqz k1,1f
67 emt
681:
69 /*
70 * The IPI sender has put some information on the anticipated
Ralf Baechle70342282013-01-22 12:59:30 +010071 * kernel stack frame. If we were in user mode, this will be
Ralf Baechle41c594a2006-04-05 09:45:45 +010072 * built above the saved kernel SP. If we were already in the
73 * kernel, it will be built above the current CPU SP.
74 *
75 * Were we in kernel mode, as indicated by CU0?
76 */
77 sll k1,k0,3
78 .set noreorder
79 bltz k1,2f
80 move k1,sp
81 .set reorder
82 /*
83 * If previously in user mode, set CU0 and use kernel stack.
84 */
85 li k1,ST0_CU0
86 or k1,k1,k0
87 mtc0 k1,CP0_STATUS
Ralf Baechle4277ff52006-06-03 22:40:15 +010088 _ehb
Ralf Baechle41c594a2006-04-05 09:45:45 +010089 get_saved_sp
90 /* Interrupting TC will have pre-set values in slots in the new frame */
912: subu k1,k1,PT_SIZE
92 /* Load TCStatus Value */
93 lw k0,PT_TCSTATUS(k1)
94 /* Write it to TCStatus to restore CU/KSU/IXMT state */
95 mtc0 k0,$2,1
Ralf Baechle4277ff52006-06-03 22:40:15 +010096 _ehb
Ralf Baechle41c594a2006-04-05 09:45:45 +010097 lw k0,PT_EPC(k1)
98 mtc0 k0,CP0_EPC
99 /* Save all will redundantly recompute the SP, but use it for now */
100 SAVE_ALL
101 CLI
Ralf Baechle192ef362006-07-07 14:07:18 +0100102 TRACE_IRQS_OFF
Ralf Baechle41c594a2006-04-05 09:45:45 +0100103 /* Function to be invoked passed stack pad slot 5 */
104 lw t0,PT_PADSLOT5(sp)
105 /* Argument from sender passed in stack pad slot 4 */
Atsushi Nemotof431baa2006-10-09 01:24:23 +0900106 lw a0,PT_PADSLOT4(sp)
Ralf Baechlecb568372006-10-31 22:49:04 +0000107 LONG_L s0, TI_REGS($28)
108 LONG_S sp, TI_REGS($28)
109 PTR_LA ra, ret_from_irq
Atsushi Nemotof431baa2006-10-09 01:24:23 +0900110 jr t0
Ralf Baechle41c594a2006-04-05 09:45:45 +0100111
112/*
113 * Called from idle loop to provoke processing of queued IPIs
114 * First IPI message in queue passed as argument.
115 */
116
117LEAF(self_ipi)
118 /* Before anything else, block interrupts */
119 mfc0 t0,CP0_TCSTATUS
120 ori t1,t0,TCSTATUS_IXMT
121 mtc0 t1,CP0_TCSTATUS
Ralf Baechle4277ff52006-06-03 22:40:15 +0100122 _ehb
Ralf Baechle41c594a2006-04-05 09:45:45 +0100123 /* We know we're in kernel mode, so prepare stack frame */
124 subu t1,sp,PT_SIZE
125 sw ra,PT_EPC(t1)
126 sw a0,PT_PADSLOT4(t1)
127 la t2,ipi_decode
Ralf Baechle41c594a2006-04-05 09:45:45 +0100128 sw t2,PT_PADSLOT5(t1)
129 /* Save pre-disable value of TCStatus */
130 sw t0,PT_TCSTATUS(t1)
131 j __smtc_ipi_vector
132 nop
133END(self_ipi)