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> 11#include <asm/irqflags.h> 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/* 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) 52 .set noat 53 /* Disable thread scheduling to make Status update atomic */ 54 DMT 27 # dmt k1 55 _ehb 56 /* Set EXL */ 57 mfc0 k0,CP0_STATUS 58 ori k0,k0,ST0_EXL 59 mtc0 k0,CP0_STATUS 60 _ehb 61 /* Thread scheduling now inhibited by EXL. Restore TE state. */ 62 andi k1,k1,VPECONTROL_TE 63 beqz k1,1f 64 emt 651: 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 85 _ehb 86 get_saved_sp 87 /* Interrupting TC will have pre-set values in slots in the new frame */ 882: 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 93 _ehb 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 99 TRACE_IRQS_OFF 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 */ 103 lw a0,PT_PADSLOT4(sp) 104 LONG_L s0, TI_REGS($28) 105 LONG_S sp, TI_REGS($28) 106 PTR_LA ra, ret_from_irq 107 jr t0 108 109/* 110 * Called from idle loop to provoke processing of queued IPIs 111 * First IPI message in queue passed as argument. 112 */ 113 114LEAF(self_ipi) 115 /* Before anything else, block interrupts */ 116 mfc0 t0,CP0_TCSTATUS 117 ori t1,t0,TCSTATUS_IXMT 118 mtc0 t1,CP0_TCSTATUS 119 _ehb 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 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 130END(self_ipi) 131