vap/assembly/ppc32/exception.S

311 lines
No EOL
8.3 KiB
ArmAsm

#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