1*10465441SEvalZero#include "context.h" 2*10465441SEvalZero#define SPRG0 0x110 /* Special Purpose Register General 0 */ 3*10465441SEvalZero#define SPRG1 0x111 /* Special Purpose Register General 1 */ 4*10465441SEvalZero 5*10465441SEvalZero .globl rt_hw_interrupt_disable 6*10465441SEvalZero .globl rt_hw_interrupt_enable 7*10465441SEvalZero .globl rt_hw_context_switch 8*10465441SEvalZero .globl rt_hw_context_switch_to 9*10465441SEvalZero .globl rt_hw_context_switch_interrupt 10*10465441SEvalZero .globl rt_hw_systemcall_entry 11*10465441SEvalZero 12*10465441SEvalZero/* 13*10465441SEvalZero * rt_base_t rt_hw_interrupt_disable(); 14*10465441SEvalZero * return the interrupt status and disable interrupt 15*10465441SEvalZero */ 16*10465441SEvalZero#if 0 17*10465441SEvalZerort_hw_interrupt_disable: 18*10465441SEvalZero mfmsr r3 /* Disable interrupts */ 19*10465441SEvalZero li r4,0 20*10465441SEvalZero ori r4,r4,MSR_EE 21*10465441SEvalZero andc r4,r4,r3 22*10465441SEvalZero SYNC /* Some chip revs need this... */ 23*10465441SEvalZero mtmsr r4 24*10465441SEvalZero SYNC 25*10465441SEvalZero blr 26*10465441SEvalZero#else 27*10465441SEvalZerort_hw_interrupt_disable: 28*10465441SEvalZero addis r4, r0, 0xFFFD 29*10465441SEvalZero ori r4, r4, 0x7FFF 30*10465441SEvalZero mfmsr r3 31*10465441SEvalZero and r4, r4, 3 /* Clear bits 14 and 16, corresponding to... */ 32*10465441SEvalZero mtmsr r4 /* ...critical and non-critical interrupts */ 33*10465441SEvalZero blr 34*10465441SEvalZero#endif 35*10465441SEvalZero 36*10465441SEvalZero/* 37*10465441SEvalZero * void rt_hw_interrupt_enable(rt_base_t level); 38*10465441SEvalZero * restore interrupt 39*10465441SEvalZero */ 40*10465441SEvalZerort_hw_interrupt_enable: 41*10465441SEvalZero mtmsr r3 42*10465441SEvalZero SYNC 43*10465441SEvalZero blr 44*10465441SEvalZero 45*10465441SEvalZero/* 46*10465441SEvalZero * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 47*10465441SEvalZero * r3 --> from 48*10465441SEvalZero * r4 --> to 49*10465441SEvalZero * 50*10465441SEvalZero * r1: stack pointer 51*10465441SEvalZero */ 52*10465441SEvalZerort_hw_systemcall_entry: 53*10465441SEvalZero mtspr SPRG0,r3 /* save r3 to SPRG0 */ 54*10465441SEvalZero mtspr SPRG1,r4 /* save r4 to SPRG1 */ 55*10465441SEvalZero 56*10465441SEvalZero lis r3,rt_thread_switch_interrput_flag@h 57*10465441SEvalZero ori r3,r3,rt_thread_switch_interrput_flag@l 58*10465441SEvalZero lwz r4,0(r3) 59*10465441SEvalZero cmpi cr0,0,r4,0x0 /* whether is 0 */ 60*10465441SEvalZero beq _no_switch /* no switch, exit */ 61*10465441SEvalZero li r4,0x0 /* set rt_thread_switch_interrput_flag to 0 */ 62*10465441SEvalZero stw r4,0(r3) 63*10465441SEvalZero 64*10465441SEvalZero /* load from thread to r3 */ 65*10465441SEvalZero lis r3,rt_interrupt_from_thread@h /* set rt_interrupt_from_thread */ 66*10465441SEvalZero ori r3,r3,rt_interrupt_from_thread@l 67*10465441SEvalZero lwz r3,0(r3) 68*10465441SEvalZero 69*10465441SEvalZero cmpi cr0,0,r3,0x0 /* whether is 0 */ 70*10465441SEvalZero beq _restore /* it's first switch, goto _restore */ 71*10465441SEvalZero 72*10465441SEvalZero /* save r1:sp to thread[from] stack pointer */ 73*10465441SEvalZero subi r1, r1, STACK_FRAME_SIZE 74*10465441SEvalZero stw r1, 0(r3) 75*10465441SEvalZero 76*10465441SEvalZero /* restore r3, r4 from SPRG */ 77*10465441SEvalZero mfspr r3,SPRG0 78*10465441SEvalZero mfspr r4,SPRG0 79*10465441SEvalZero 80*10465441SEvalZero /* save registers */ 81*10465441SEvalZero stw r0,GPR0(r1) /* save general purpose registers 0 */ 82*10465441SEvalZero stmw r2,GPR2(r1) /* save general purpose registers 2-31 */ 83*10465441SEvalZero 84*10465441SEvalZero mfusprg0 r0 /* save usprg0 */ 85*10465441SEvalZero stw r0,USPRG0(r1) 86*10465441SEvalZero mfcr r0, /* save cr */ 87*10465441SEvalZero stw r0,CR(r1) 88*10465441SEvalZero mfxer r0 /* save xer */ 89*10465441SEvalZero stw r0,XER(r1) 90*10465441SEvalZero mfctr r0 /* save ctr */ 91*10465441SEvalZero stw r0,CTR(r1) 92*10465441SEvalZero mflr r0 /* save lr */ 93*10465441SEvalZero stw r0, LR(r1) 94*10465441SEvalZero 95*10465441SEvalZero mfsrr0 r0 /* save SRR0 and SRR1 */ 96*10465441SEvalZero stw r0,SRR0(r1) 97*10465441SEvalZero mfsrr1 r0 98*10465441SEvalZero stw r0,SRR1(r1) 99*10465441SEvalZero 100*10465441SEvalZero_restore: 101*10465441SEvalZero /* get thread[to] stack pointer */ 102*10465441SEvalZero lis r4,rt_interrupt_to_thread@h 103*10465441SEvalZero ori r4,r4,rt_interrupt_to_thread@l 104*10465441SEvalZero lwz r1,0(r4) 105*10465441SEvalZero lwz r1,0(r1) 106*10465441SEvalZero 107*10465441SEvalZero lwz r0,SRR1(r1) /* restore SRR1 and SRR0 */ 108*10465441SEvalZero mtsrr1 r0 109*10465441SEvalZero lwz r0,SRR0(r1) 110*10465441SEvalZero mtsrr0 r0 111*10465441SEvalZero 112*10465441SEvalZero lwz r0,LR(r1) /* restore lr */ 113*10465441SEvalZero mtlr r0 114*10465441SEvalZero lwz r0,CTR(r1) /* restore ctr */ 115*10465441SEvalZero mtctr r0 116*10465441SEvalZero lwz r0,XER(r1) /* restore xer */ 117*10465441SEvalZero mtxer r0 118*10465441SEvalZero lwz r0,CR(r1) /* restore cr */ 119*10465441SEvalZero mtcr r0 120*10465441SEvalZero lwz r0,USPRG0(r1) /* restore usprg0 */ 121*10465441SEvalZero // mtusprg0 r0 122*10465441SEvalZero 123*10465441SEvalZero lmw r2, GPR2(r1) /* restore general register */ 124*10465441SEvalZero lwz r0,GPR0(r1) 125*10465441SEvalZero addi r1, r1, STACK_FRAME_SIZE 126*10465441SEvalZero /* RFI will restore status register and thus the correct priority*/ 127*10465441SEvalZero rfi 128*10465441SEvalZero 129*10465441SEvalZero_no_switch: 130*10465441SEvalZero /* restore r3, r4 from SPRG */ 131*10465441SEvalZero mfspr r3,SPRG0 132*10465441SEvalZero mfspr r4,SPRG0 133*10465441SEvalZero rfi 134*10465441SEvalZero 135*10465441SEvalZero /* void rt_hw_context_switch_to(to); */ 136*10465441SEvalZero .globl rt_hw_context_switch_to 137*10465441SEvalZerort_hw_context_switch_to: 138*10465441SEvalZero /* set rt_thread_switch_interrput_flag = 1 */ 139*10465441SEvalZero lis r5,rt_thread_switch_interrput_flag@h 140*10465441SEvalZero ori r5,r5,rt_thread_switch_interrput_flag@l 141*10465441SEvalZero li r6, 0x01 142*10465441SEvalZero stw r6,0(r5) 143*10465441SEvalZero 144*10465441SEvalZero /* set rt_interrupt_from_thread = 0 */ 145*10465441SEvalZero lis r5,rt_interrupt_from_thread@h 146*10465441SEvalZero ori r5,r5,rt_interrupt_from_thread@l 147*10465441SEvalZero li r6, 0x00 148*10465441SEvalZero stw r6,0(r5) 149*10465441SEvalZero 150*10465441SEvalZero /* set rt_interrupt_from_thread = to */ 151*10465441SEvalZero lis r5,rt_interrupt_to_thread@h 152*10465441SEvalZero ori r5,r5,rt_interrupt_to_thread@l 153*10465441SEvalZero stw r3,0(r5) 154*10465441SEvalZero 155*10465441SEvalZero /* trigger a system call */ 156*10465441SEvalZero sc 157*10465441SEvalZero 158*10465441SEvalZero blr 159*10465441SEvalZero 160*10465441SEvalZero /* void rt_hw_context_switch(from, to); */ 161*10465441SEvalZero .globl rt_hw_context_switch 162*10465441SEvalZerort_hw_context_switch: 163*10465441SEvalZero /* compare rt_thread_switch_interrupt_flag and set it */ 164*10465441SEvalZero lis r5,rt_thread_switch_interrput_flag@h 165*10465441SEvalZero ori r5,r5,rt_thread_switch_interrput_flag@l 166*10465441SEvalZero lwz r6,0(r5) 167*10465441SEvalZero cmpi cr0,0,r6,0x1 /* whether is 1 */ 168*10465441SEvalZero beq _reswitch /* set already, goto _reswitch */ 169*10465441SEvalZero li r6,0x1 /* set rt_thread_switch_interrput_flag to 1*/ 170*10465441SEvalZero stw r6,0(r5) 171*10465441SEvalZero 172*10465441SEvalZero /* set rt_interrupt_from_thread to 'from' */ 173*10465441SEvalZero lis r5,rt_interrupt_from_thread@h 174*10465441SEvalZero ori r5,r5,rt_interrupt_from_thread@l 175*10465441SEvalZero stw r3,0(r5) 176*10465441SEvalZero 177*10465441SEvalZero_reswitch: 178*10465441SEvalZero /* set rt_interrupt_to_thread to 'to' */ 179*10465441SEvalZero lis r6,rt_interrupt_to_thread@h 180*10465441SEvalZero ori r6,r6,rt_interrupt_to_thread@l 181*10465441SEvalZero stw r4,0(r6) 182*10465441SEvalZero 183*10465441SEvalZero /* trigger a system call */ 184*10465441SEvalZero sc 185*10465441SEvalZero 186*10465441SEvalZero blr 187*10465441SEvalZero 188*10465441SEvalZero .globl rt_hw_context_switch_interrupt 189*10465441SEvalZerort_hw_context_switch_interrupt: 190*10465441SEvalZero /* compare rt_thread_switch_interrupt_flag and set it */ 191*10465441SEvalZero lis r5,rt_thread_switch_interrput_flag@h 192*10465441SEvalZero ori r5,r5,rt_thread_switch_interrput_flag@l 193*10465441SEvalZero lwz r6,0(r5) 194*10465441SEvalZero cmpi cr0,0,r6,0x1 /* whether is 1 */ 195*10465441SEvalZero beq _int_reswitch /* set already, goto _reswitch */ 196*10465441SEvalZero li r6,0x1 /* set rt_thread_switch_interrput_flag to 1*/ 197*10465441SEvalZero stw r6,0(r5) 198*10465441SEvalZero 199*10465441SEvalZero /* set rt_interrupt_from_thread to 'from' */ 200*10465441SEvalZero lis r5,rt_interrupt_from_thread@h 201*10465441SEvalZero ori r5,r5,rt_interrupt_from_thread@l 202*10465441SEvalZero stw r3,0(r5) 203*10465441SEvalZero 204*10465441SEvalZero_int_reswitch: 205*10465441SEvalZero /* set rt_interrupt_to_thread to 'to' */ 206*10465441SEvalZero lis r6,rt_interrupt_to_thread@h 207*10465441SEvalZero ori r6,r6,rt_interrupt_to_thread@l 208*10465441SEvalZero stw r4,0(r6) 209*10465441SEvalZero 210*10465441SEvalZero blr 211