#include "regnames.h" .extern _decrementer_exception_fn #define ISTATE_OFFSET_SP_FRAME 0x00 #define ISTATE_OFFSET_LR_FRAME 0x04 #define ISTATE_OFFSET_R0 0x08 #define ISTATE_OFFSET_R2 0x0c #define ISTATE_OFFSET_R3 0x10 #define ISTATE_OFFSET_R4 0x14 #define ISTATE_OFFSET_R5 0x18 #define ISTATE_OFFSET_R6 0x1c #define ISTATE_OFFSET_R7 0x20 #define ISTATE_OFFSET_R8 0x24 #define ISTATE_OFFSET_R9 0x28 #define ISTATE_OFFSET_R10 0x2c #define ISTATE_OFFSET_R11 0x30 #define ISTATE_OFFSET_R13 0x34 #define ISTATE_OFFSET_R14 0x38 #define ISTATE_OFFSET_R15 0x3c #define ISTATE_OFFSET_R16 0x40 #define ISTATE_OFFSET_R17 0x44 #define ISTATE_OFFSET_R18 0x48 #define ISTATE_OFFSET_R19 0x4c #define ISTATE_OFFSET_R20 0x50 #define ISTATE_OFFSET_R21 0x54 #define ISTATE_OFFSET_R22 0x58 #define ISTATE_OFFSET_R23 0x5c #define ISTATE_OFFSET_R24 0x60 #define ISTATE_OFFSET_R25 0x64 #define ISTATE_OFFSET_R26 0x68 #define ISTATE_OFFSET_R27 0x6c #define ISTATE_OFFSET_R28 0x70 #define ISTATE_OFFSET_R29 0x74 #define ISTATE_OFFSET_R30 0x78 #define ISTATE_OFFSET_R31 0x7c #define ISTATE_OFFSET_CR 0x80 #define ISTATE_OFFSET_SRR0 0x84 #define ISTATE_OFFSET_SRR1 0x88 #define ISTATE_OFFSET_LR 0x8c #define ISTATE_OFFSET_CTR 0x90 #define ISTATE_OFFSET_XER 0x94 #define ISTATE_OFFSET_DAR 0x98 #define ISTATE_OFFSET_R12 0x9c #define ISTATE_OFFSET_SP 0xa0 #define ISTATE_SIZE 0xa4 #define ALIGN_UP(s, a) (((s) + ((a) - 1)) & ~((a) - 1)) .section V_TEXT_GENESIS, "ax" .macro CTX_SAVE // honestly i'm going insane looking at powerpc assembly documentation // so a lot of this will be based heavily on helenos's exception.S // also their code is much nicer to look at than apple's hw_exception.s // https://github.com/HelenOS/helenos/blob/master/kernel/arch/ppc32/src/exception.S // i do not claim ownership of this mtsprg1 r12 mfcr r12 mtsprg2 sp // move stack pointer to the exception stack lis sp, _exception_stack@ha addi sp, sp, _exception_stack@l subi sp, sp, ALIGN_UP(ISTATE_SIZE, 16) stw r0, ISTATE_OFFSET_R0(sp) stw r2, ISTATE_OFFSET_R2(sp) stw r3, ISTATE_OFFSET_R3(sp) stw r4, ISTATE_OFFSET_R4(sp) stw r5, ISTATE_OFFSET_R5(sp) stw r6, ISTATE_OFFSET_R6(sp) stw r7, ISTATE_OFFSET_R7(sp) stw r8, ISTATE_OFFSET_R8(sp) stw r9, ISTATE_OFFSET_R9(sp) stw r10, ISTATE_OFFSET_R10(sp) stw r11, ISTATE_OFFSET_R11(sp) stw r13, ISTATE_OFFSET_R13(sp) stw r14, ISTATE_OFFSET_R14(sp) stw r15, ISTATE_OFFSET_R15(sp) stw r16, ISTATE_OFFSET_R16(sp) stw r17, ISTATE_OFFSET_R17(sp) stw r18, ISTATE_OFFSET_R18(sp) stw r19, ISTATE_OFFSET_R19(sp) stw r20, ISTATE_OFFSET_R20(sp) stw r21, ISTATE_OFFSET_R21(sp) stw r22, ISTATE_OFFSET_R22(sp) stw r23, ISTATE_OFFSET_R23(sp) stw r24, ISTATE_OFFSET_R24(sp) stw r25, ISTATE_OFFSET_R25(sp) stw r26, ISTATE_OFFSET_R26(sp) stw r27, ISTATE_OFFSET_R27(sp) stw r28, ISTATE_OFFSET_R28(sp) stw r29, ISTATE_OFFSET_R29(sp) stw r30, ISTATE_OFFSET_R30(sp) stw r31, ISTATE_OFFSET_R31(sp) stw r12, ISTATE_OFFSET_CR(sp) mfsrr0 r12 stw r12, ISTATE_OFFSET_SRR0(sp) mfsrr1 r12 stw r12, ISTATE_OFFSET_SRR1(sp) mflr r12 stw r12, ISTATE_OFFSET_LR(sp) mfctr r12 stw r12, ISTATE_OFFSET_CTR(sp) mfxer r12 stw r12, ISTATE_OFFSET_XER(sp) mfdar r12 stw r12, ISTATE_OFFSET_DAR(sp) mfsprg1 r12 stw r12, ISTATE_OFFSET_R12(sp) mfsprg2 r12 stw r12, ISTATE_OFFSET_SP(sp) li r12, 0 stw r12, ISTATE_OFFSET_LR_FRAME(sp) stw r12, ISTATE_OFFSET_SP_FRAME(sp) .endm // _decrementer_exception_wrapper // called when the decrementer exception occurs (i.e. when it reaches 0) .global _decrementer_exception_wrapper .extern _test_decrementer .extern VAP_KERN_BASE _decrementer_exception_wrapper: // temporarily save r12 mtsprg2 r12 mfmsr r12 ori r12, r12, ((1 << 5) | (1 << 4)) // enable instruction relocation and data relocation mtmsr r12 mfsprg2 r12 isync CTX_SAVE lis r12, _decrementer_exception_definition@ha addi r12, r12, _decrementer_exception_definition@l mtsrr0 r12 mfmsr r12 mtsrr1 r12 rfi // end of exceptions .global VAP_VECTOR_END VAP_VECTOR_END: // exception stack .global _vap_exception_stack .org 0x8000 // grows down _exception_stack: .global _decrementer_exception_definition _decrementer_exception_definition: // disable interrupts, enable instruction relocation and data relocation // but this time both here and in srr1 mfsrr1 r12 ori r12, r12, ((1 << 5) | (1 << 4)) // enable instruction relocation and data relocation andi. r12, r12, ~(1 << 15)@l // disable interrupts mtsrr1 r12 isync // copy sp to r3 mr r3, sp // load the address lis r12, scheduler_callback@ha addi r12, r12, scheduler_callback@l mtsrr0 r12 rfi .global _vap_return_from_exception _vap_return_from_exception: // disable interrupts mfmsr r12 rlwinm r21, r12, 0, 17, 15 mtmsr r12 isync // load r3 into sp mr sp, r3 sync isync // restore context lwz r0, ISTATE_OFFSET_R0(sp) lwz r2, ISTATE_OFFSET_R2(sp) lwz r3, ISTATE_OFFSET_R3(sp) lwz r4, ISTATE_OFFSET_R4(sp) lwz r5, ISTATE_OFFSET_R5(sp) lwz r6, ISTATE_OFFSET_R6(sp) lwz r7, ISTATE_OFFSET_R7(sp) lwz r8, ISTATE_OFFSET_R8(sp) lwz r9, ISTATE_OFFSET_R9(sp) lwz r10, ISTATE_OFFSET_R10(sp) lwz r11, ISTATE_OFFSET_R11(sp) lwz r13, ISTATE_OFFSET_R13(sp) lwz r14, ISTATE_OFFSET_R14(sp) lwz r15, ISTATE_OFFSET_R15(sp) lwz r16, ISTATE_OFFSET_R16(sp) lwz r17, ISTATE_OFFSET_R17(sp) lwz r18, ISTATE_OFFSET_R18(sp) lwz r19, ISTATE_OFFSET_R19(sp) lwz r20, ISTATE_OFFSET_R20(sp) lwz r21, ISTATE_OFFSET_R21(sp) lwz r22, ISTATE_OFFSET_R22(sp) lwz r23, ISTATE_OFFSET_R23(sp) lwz r24, ISTATE_OFFSET_R24(sp) lwz r25, ISTATE_OFFSET_R25(sp) lwz r26, ISTATE_OFFSET_R26(sp) lwz r27, ISTATE_OFFSET_R27(sp) lwz r28, ISTATE_OFFSET_R28(sp) lwz r29, ISTATE_OFFSET_R29(sp) lwz r30, ISTATE_OFFSET_R30(sp) lwz r31, ISTATE_OFFSET_R31(sp) lwz r12, ISTATE_OFFSET_CR(sp) mtcr r12 lwz r12, ISTATE_OFFSET_SRR0(sp) mtsrr0 r12 lwz r12, ISTATE_OFFSET_SRR1(sp) mtsrr1 r12 lwz r12, ISTATE_OFFSET_LR(sp) mtlr r12 lwz r12, ISTATE_OFFSET_CTR(sp) mtctr r12 lwz r12, ISTATE_OFFSET_XER(sp) mtxer r12 lwz r12, ISTATE_OFFSET_R12(sp) lwz sp, ISTATE_OFFSET_SP(sp) // return to task rfi // helper function to create an istate from the current state .global _vap_create_istate _vap_create_istate: // r3 = pointer to istate (should have enough room allocated) stw r0, ISTATE_OFFSET_R0(r3) stw r2, ISTATE_OFFSET_R2(r3) stw r3, ISTATE_OFFSET_R3(r3) stw r4, ISTATE_OFFSET_R4(r3) stw r5, ISTATE_OFFSET_R5(r3) stw r6, ISTATE_OFFSET_R6(r3) stw r7, ISTATE_OFFSET_R7(r3) stw r8, ISTATE_OFFSET_R8(r3) stw r9, ISTATE_OFFSET_R9(r3) stw r10, ISTATE_OFFSET_R10(r3) stw r11, ISTATE_OFFSET_R11(r3) stw r13, ISTATE_OFFSET_R13(r3) stw r14, ISTATE_OFFSET_R14(r3) stw r15, ISTATE_OFFSET_R15(r3) stw r16, ISTATE_OFFSET_R16(r3) stw r17, ISTATE_OFFSET_R17(r3) stw r18, ISTATE_OFFSET_R18(r3) stw r19, ISTATE_OFFSET_R19(r3) stw r20, ISTATE_OFFSET_R20(r3) stw r21, ISTATE_OFFSET_R21(r3) stw r22, ISTATE_OFFSET_R22(r3) stw r23, ISTATE_OFFSET_R23(r3) stw r24, ISTATE_OFFSET_R24(r3) stw r25, ISTATE_OFFSET_R25(r3) stw r26, ISTATE_OFFSET_R26(r3) stw r27, ISTATE_OFFSET_R27(r3) stw r28, ISTATE_OFFSET_R28(r3) stw r29, ISTATE_OFFSET_R29(r3) stw r30, ISTATE_OFFSET_R30(r3) stw r31, ISTATE_OFFSET_R31(r3) stw r12, ISTATE_OFFSET_CR(r3) mfsrr0 r12 stw r12, ISTATE_OFFSET_SRR0(r3) mfmsr r12 // we want msr instead of srr1, so that interrupts will return here with this msr stw r12, ISTATE_OFFSET_SRR1(r3) mflr r12 stw r12, ISTATE_OFFSET_LR(r3) mfctr r12 stw r12, ISTATE_OFFSET_CTR(r3) mfxer r12 stw r12, ISTATE_OFFSET_XER(r3) stw r12, ISTATE_OFFSET_R12(r3) stw sp, ISTATE_OFFSET_SP(r3) blr