diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-10-29 16:36:51 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-10-29 16:36:51 +0000 |
commit | 8b1e81d71f4d898c97460578fe282f2ebeb5a1de (patch) | |
tree | d70622e7ea03b9d99928145dd2418e381d4a7e7b | |
parent | abe9dad9530b68b427a706d6f4c3947dd5d9cc73 (diff) |
bcm64: use generic 9/arm64/* files
-rw-r--r-- | sys/src/9/bcm64/archbcm3.c | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/archbcm4.c | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/cache.v8.s | 212 | ||||
-rw-r--r-- | sys/src/9/bcm64/clock.c | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/fpu.c | 289 | ||||
-rw-r--r-- | sys/src/9/bcm64/gic.c | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/init9.s | 4 | ||||
-rw-r--r-- | sys/src/9/bcm64/l.s | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/main.c | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/mkfile | 12 | ||||
-rw-r--r-- | sys/src/9/bcm64/mmu.c | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/rebootcode.s | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/sysreg.h | 66 | ||||
-rw-r--r-- | sys/src/9/bcm64/trap.c | 688 |
14 files changed, 18 insertions, 1269 deletions
diff --git a/sys/src/9/bcm64/archbcm3.c b/sys/src/9/bcm64/archbcm3.c index 95876df0f..2e6781d5e 100644 --- a/sys/src/9/bcm64/archbcm3.c +++ b/sys/src/9/bcm64/archbcm3.c @@ -9,7 +9,7 @@ #include "fns.h" #include "../port/error.h" #include "io.h" -#include "sysreg.h" +#include "../arm64/sysreg.h" typedef struct Mbox Mbox; typedef struct Mboxes Mboxes; diff --git a/sys/src/9/bcm64/archbcm4.c b/sys/src/9/bcm64/archbcm4.c index 3fefe9b9d..ad9a9e69c 100644 --- a/sys/src/9/bcm64/archbcm4.c +++ b/sys/src/9/bcm64/archbcm4.c @@ -10,7 +10,7 @@ #include "../port/error.h" #include "io.h" #include "../port/pci.h" -#include "sysreg.h" +#include "../arm64/sysreg.h" typedef struct Mbox Mbox; typedef struct Mboxes Mboxes; diff --git a/sys/src/9/bcm64/cache.v8.s b/sys/src/9/bcm64/cache.v8.s deleted file mode 100644 index 20ecf2f5e..000000000 --- a/sys/src/9/bcm64/cache.v8.s +++ /dev/null @@ -1,212 +0,0 @@ -#include "sysreg.h" - -#undef SYSREG -#define SYSREG(op0,op1,Cn,Cm,op2) SPR(((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)) - -/* - * instruction cache operations - */ -TEXT cacheiinvse(SB), 1, $-4 - MOVWU len+8(FP), R2 - ADD R0, R2 - - MRS DAIF, R11 - MSR $0x2, DAIFSet - MOVWU $1, R10 - MSR R10, CSSELR_EL1 - ISB $SY - MRS CCSIDR_EL1, R4 - - ANDW $7, R4 - ADDW $4, R4 // log2(linelen) - LSL R4, R10 - LSR R4, R0 - LSL R4, R0 - -_iinvse: - IC R0, 3,7,5,1 // IVAU - ADD R10, R0 - CMP R0, R2 - BGT _iinvse - DSB $NSH - ISB $SY - MSR R11, DAIF - RETURN - -TEXT cacheiinv(SB), 1, $-4 - IC R0, 0,7,5,0 // IALLU - DSB $NSH - ISB $SY - RETURN - -TEXT cacheuwbinv(SB), 1, $0 - BL cachedwbinv(SB) - BL cacheiinv(SB) - RETURN - -/* - * data cache operations - */ -TEXT cachedwbse(SB), 1, $-4 - MOV LR, R29 - BL cachedva<>(SB) -TEXT dccvac(SB), 1, $-4 - DC R0, 3,7,10,1 // CVAC - RETURN - -TEXT cacheduwbse(SB), 1, $-4 - MOV LR, R29 - BL cachedva<>(SB) -TEXT dccvau(SB), 1, $-4 - DC R0, 3,7,11,1 // CVAU - RETURN - -TEXT cachedinvse(SB), 1, $-4 - MOV LR, R29 - BL cachedva<>(SB) -TEXT dcivac(SB), 1, $-4 - DC R0, 0,7,6,1 // IVAC - RETURN - -TEXT cachedwbinvse(SB), 1, $-4 - MOV LR, R29 - BL cachedva<>(SB) -TEXT dccivac(SB), 1, $-4 - DC R0, 3,7,14,1 // CIVAC - RETURN - -TEXT cachedva<>(SB), 1, $-4 - MOV LR, R1 - MOVWU len+8(FP), R2 - ADD R0, R2 - - MRS DAIF, R11 - MSR $0x2, DAIFSet - MOVWU $0, R10 - MSR R10, CSSELR_EL1 - ISB $SY - MRS CCSIDR_EL1, R4 - - ANDW $7, R4 - ADDW $4, R4 // log2(linelen) - MOVWU $1, R10 - LSL R4, R10 - LSR R4, R0 - LSL R4, R0 - - DSB $SY - ISB $SY -_cachedva: - BL (R1) - ADD R10, R0 - CMP R0, R2 - BGT _cachedva - DSB $SY - ISB $SY - MSR R11, DAIF - RET R29 - -/* - * l1 cache operations - */ -TEXT cachedwb(SB), 1, $-4 - MOVWU $0, R0 -_cachedwb: - MOV LR, R29 - BL cachedsw<>(SB) -TEXT dccsw(SB), 1, $-4 - DC R0, 0,7,10,2 // CSW - RETURN - -TEXT cachedinv(SB), 1, $-4 - MOVWU $0, R0 -_cachedinv: - MOV LR, R29 - BL cachedsw<>(SB) -TEXT dcisw(SB), 1, $-4 - DC R0, 0,7,6,2 // ISW - RETURN - -TEXT cachedwbinv(SB), 1, $-4 - MOVWU $0, R0 -_cachedwbinv: - MOV LR, R29 - BL cachedsw<>(SB) -TEXT dccisw(SB), 1, $-4 - DC R0, 0,7,14,2 // CISW - RETURN - -/* - * l2 cache operations - */ -TEXT l2cacheuwb(SB), 1, $-4 - MOVWU $1, R0 - B _cachedwb -TEXT l2cacheuinv(SB), 1, $-4 - MOVWU $1, R0 - B _cachedinv -TEXT l2cacheuwbinv(SB), 1, $-4 - MOVWU $1, R0 - B _cachedwbinv - -TEXT cachesize(SB), 1, $-4 - MRS DAIF, R11 - MSR $0x2, DAIFSet - MSR R0, CSSELR_EL1 - ISB $SY - MRS CCSIDR_EL1, R0 - MSR R11, DAIF - RETURN - -TEXT cachedsw<>(SB), 1, $-4 - MOV LR, R1 - - MRS DAIF, R11 - MSR $0x2, DAIFSet - ADDW R0, R0, R8 - MSR R8, CSSELR_EL1 - ISB $SY - MRS CCSIDR_EL1, R4 - - LSR $3, R4, R7 - ANDW $1023, R7 // lastway - ADDW $1, R7, R5 // #ways - - LSR $13, R4, R2 - ANDW $32767, R2 // lastset - ADDW $1, R2 // #sets - - ANDW $7, R4 - ADDW $4, R4 // log2(linelen) - - MOVWU $32, R3 // wayshift = 32 - log2(#ways) -_countlog2ways: - CBZ R7, _loop // lastway == 0? - LSR $1, R7 // lastway >>= 1 - SUB $1, R3 // wayshift-- - B _countlog2ways -_loop: - DSB $SY - ISB $SY -_nextway: - MOVWU $0, R6 // set -_nextset: - LSL R3, R7, R0 // way<<wayshift - LSL R4, R6, R9 // set<<log2(linelen) - ORRW R8, R0 // level - ORRW R9, R0 // setway - - BL (R1) // op(setway) - - ADDW $1, R6 // set++ - CMPW R2, R6 - BLT _nextset - - ADDW $1, R7 // way++ - CMPW R5, R7 - BLT _nextway - - DSB $SY - ISB $SY - MSR R11, DAIF - RET R29 diff --git a/sys/src/9/bcm64/clock.c b/sys/src/9/bcm64/clock.c index f5fcc4784..b5bc2596b 100644 --- a/sys/src/9/bcm64/clock.c +++ b/sys/src/9/bcm64/clock.c @@ -19,7 +19,7 @@ #include "fns.h" #include "io.h" #include "ureg.h" -#include "sysreg.h" +#include "../arm64/sysreg.h" enum { SYSTIMERS = VIRTIO+0x3000, diff --git a/sys/src/9/bcm64/fpu.c b/sys/src/9/bcm64/fpu.c deleted file mode 100644 index 6a868ceb6..000000000 --- a/sys/src/9/bcm64/fpu.c +++ /dev/null @@ -1,289 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" - -#include "ureg.h" -#include "sysreg.h" - -/* libc */ -extern ulong getfcr(void); -extern void setfcr(ulong fcr); -extern ulong getfsr(void); -extern void setfsr(ulong fsr); - -static FPsave fpsave0; - -static void -fpsave(FPsave *p) -{ - p->control = getfcr(); - p->status = getfsr(); - fpsaveregs(p->regs); - fpoff(); -} - -static void -fprestore(FPsave *p) -{ - fpon(); - setfcr(p->control); - setfsr(p->status); - fploadregs(p->regs); -} - -static void -fpinit(void) -{ - fprestore(&fpsave0); -} - -void -fpuinit(void) -{ - m->fpstate = FPinit; - m->fpsave = nil; - fpoff(); -} - -static FPsave* -fpalloc(void) -{ - FPsave *save; - - while((save = mallocalign(sizeof(FPsave), 16, 0, 0)) == nil){ - spllo(); - resrcwait("no memory for FPsave"); - splhi(); - } - return save; -} - -static void -fpfree(FPsave *save) -{ - free(save); -} - - -/* - * Protect or save FPU state and setup new state - * (lazily in the case of user process) for the kernel. - * All syscalls, traps and interrupts (except mathtrap()!) - * are handled between fpukenter() and fpukexit(), - * so they can use floating point and vector instructions. - */ -FPsave* -fpukenter(Ureg*) -{ - if(up == nil){ - switch(m->fpstate){ - case FPactive: - fpsave(m->fpsave); - /* wet floor */ - case FPinactive: - m->fpstate = FPinit; - return m->fpsave; - } - return nil; - } - - switch(up->fpstate){ - case FPactive: - up->fpstate = FPprotected; - fpoff(); - /* wet floor */ - case FPprotected: - return nil; - } - - switch(up->kfpstate){ - case FPactive: - fpsave(up->kfpsave); - /* wet floor */ - case FPinactive: - up->kfpstate = FPinit; - return up->kfpsave; - } - return nil; -} - -void -fpukexit(Ureg *ureg, FPsave *save) -{ - if(up == nil){ - switch(m->fpstate){ - case FPactive: - fpoff(); - /* wet floor */ - case FPinactive: - fpfree(m->fpsave); - m->fpstate = FPinit; - } - m->fpsave = save; - if(save != nil) - m->fpstate = FPinactive; - return; - } - - if(up->fpstate == FPprotected){ - if(userureg(ureg)){ - up->fpstate = FPactive; - fpon(); - } - return; - } - - switch(up->kfpstate){ - case FPactive: - fpoff(); - /* wet floor */ - case FPinactive: - fpfree(up->kfpsave); - up->kfpstate = FPinit; - } - up->kfpsave = save; - if(save != nil) - up->kfpstate = FPinactive; -} - -void -fpuprocsetup(Proc *p) -{ - p->fpstate = FPinit; -} - -void -fpuprocfork(Proc *p) -{ - int s; - - s = splhi(); - switch(up->fpstate & ~FPillegal){ - case FPprotected: - fpon(); - /* wet floor */ - case FPactive: - fpsave(up->fpsave); - up->fpstate = FPinactive; - /* wet floor */ - case FPinactive: - if(p->fpsave == nil) - p->fpsave = fpalloc(); - memmove(p->fpsave, up->fpsave, sizeof(FPsave)); - p->fpstate = FPinactive; - } - splx(s); -} - -void -fpuprocsave(Proc *p) -{ - if(p->state == Moribund){ - if(p->fpstate == FPactive || p->kfpstate == FPactive) - fpoff(); - fpfree(p->fpsave); - fpfree(p->kfpsave); - p->fpsave = p->kfpsave = nil; - p->fpstate = p->kfpstate = FPinit; - return; - } - if(p->kfpstate == FPactive){ - fpsave(p->kfpsave); - p->kfpstate = FPinactive; - return; - } - if(p->fpstate == FPprotected) - fpon(); - else if(p->fpstate != FPactive) - return; - fpsave(p->fpsave); - p->fpstate = FPinactive; -} - -void -fpuprocrestore(Proc*) -{ - /* - * when the scheduler switches, - * we can discard its fp state. - */ - switch(m->fpstate){ - case FPactive: - fpoff(); - /* wet floor */ - case FPinactive: - fpfree(m->fpsave); - m->fpsave = nil; - m->fpstate = FPinit; - } -} - -void -mathtrap(Ureg *ureg) -{ - if(!userureg(ureg)){ - if(up == nil){ - switch(m->fpstate){ - case FPinit: - m->fpsave = fpalloc(); - m->fpstate = FPactive; - fpinit(); - break; - case FPinactive: - fprestore(m->fpsave); - m->fpstate = FPactive; - break; - default: - panic("floating point error in irq"); - } - return; - } - - if(up->fpstate == FPprotected){ - fpon(); - fpsave(up->fpsave); - up->fpstate = FPinactive; - } - - switch(up->kfpstate){ - case FPinit: - up->kfpsave = fpalloc(); - up->kfpstate = FPactive; - fpinit(); - break; - case FPinactive: - fprestore(up->kfpsave); - up->kfpstate = FPactive; - break; - default: - panic("floating point error in trap"); - } - return; - } - - if(up->fpstate & FPillegal){ - postnote(up, 1, "sys: floating point in note handler", NDebug); - return; - } - switch(up->fpstate){ - case FPinit: - if(up->fpsave == nil) - up->fpsave = fpalloc(); - up->fpstate = FPactive; - fpinit(); - break; - case FPinactive: - fprestore(up->fpsave); - up->fpstate = FPactive; - break; - case FPprotected: - up->fpstate = FPactive; - fpon(); - break; - case FPactive: - postnote(up, 1, "sys: floating point error", NDebug); - break; - } -} diff --git a/sys/src/9/bcm64/gic.c b/sys/src/9/bcm64/gic.c index 469a1b0e5..328b18392 100644 --- a/sys/src/9/bcm64/gic.c +++ b/sys/src/9/bcm64/gic.c @@ -6,7 +6,7 @@ #include "io.h" #include "../port/pci.h" #include "ureg.h" -#include "sysreg.h" +#include "../arm64/sysreg.h" #include "../port/error.h" enum { diff --git a/sys/src/9/bcm64/init9.s b/sys/src/9/bcm64/init9.s deleted file mode 100644 index 45ae62fea..000000000 --- a/sys/src/9/bcm64/init9.s +++ /dev/null @@ -1,4 +0,0 @@ -TEXT main(SB), 1, $8 - MOV $setSB(SB), R28 /* load the SB */ - MOV $boot(SB), R0 - B startboot(SB) diff --git a/sys/src/9/bcm64/l.s b/sys/src/9/bcm64/l.s index 81164a200..2290e051b 100644 --- a/sys/src/9/bcm64/l.s +++ b/sys/src/9/bcm64/l.s @@ -1,5 +1,5 @@ #include "mem.h" -#include "sysreg.h" +#include "../arm64/sysreg.h" #undef SYSREG #define SYSREG(op0,op1,Cn,Cm,op2) SPR(((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)) diff --git a/sys/src/9/bcm64/main.c b/sys/src/9/bcm64/main.c index 1d73ad75b..cc5dc9918 100644 --- a/sys/src/9/bcm64/main.c +++ b/sys/src/9/bcm64/main.c @@ -6,7 +6,7 @@ #include "fns.h" #include "../port/error.h" #include "io.h" -#include "sysreg.h" +#include "../arm64/sysreg.h" #include "rebootcode.i" #include <pool.h> diff --git a/sys/src/9/bcm64/mkfile b/sys/src/9/bcm64/mkfile index fd7193c39..b489c9ce7 100644 --- a/sys/src/9/bcm64/mkfile +++ b/sys/src/9/bcm64/mkfile @@ -88,8 +88,16 @@ install:V: /$objtype/$p$CONF /$objtype/$p$CONF:D: $p$CONF s$p$CONF cp -x $p$CONF s$p$CONF /$objtype/ +ARM64FILES=`{../port/mkfilelist ../arm64} +^($ARM64FILES)\.$O:R: '../arm64/\1.c' + $CC $CFLAGS -I. -. ../arm64/$stem1.c -REPCC=`{../port/mkfilelist ../bcm} +cache.v8.$O: ../arm64/cache.v8.s + $AS $AFLAGS -I. -. ../arm64/cache.v8.s +init9.$O: ../arm64/init9.s + $AS $AFLAGS -I. -. ../arm64/init9.s + +REPCC=`{../port/mkfilelist ../bcm | sed 's/(fpu|trap)[|)]//g'} ^($REPCC)\.$O:R: '../bcm/\1.c' $CC $CFLAGS -I. -. ../bcm/$stem1.c @@ -101,7 +109,7 @@ arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O syscall.$O trap.$O: \ /$objtype/include/ureg.h trap.$O main.$O: /sys/include/tos.h l.$O cache.v8.$O mmu.$O rebootcode.$O: mem.h -l.$O cache.v8.$O archbcm3.$O clock.$O fpu.$O trap.$O mmu.$O rebootcode.$O: sysreg.h +l.$O cache.v8.$O archbcm3.$O clock.$O fpu.$O trap.$O mmu.$O rebootcode.$O: ../arm64/sysreg.h main.$O: rebootcode.i pcibcm.$O: ../port/pci.h diff --git a/sys/src/9/bcm64/mmu.c b/sys/src/9/bcm64/mmu.c index 311f89826..9a8a34fa2 100644 --- a/sys/src/9/bcm64/mmu.c +++ b/sys/src/9/bcm64/mmu.c @@ -3,7 +3,7 @@ #include "mem.h" #include "dat.h" #include "fns.h" -#include "sysreg.h" +#include "../arm64/sysreg.h" #define INITMAP (ROUND((uintptr)end + BY2PG, PGLSZ(1))-KZERO) diff --git a/sys/src/9/bcm64/rebootcode.s b/sys/src/9/bcm64/rebootcode.s index 8b4986473..009f10b8c 100644 --- a/sys/src/9/bcm64/rebootcode.s +++ b/sys/src/9/bcm64/rebootcode.s @@ -1,5 +1,5 @@ #include "mem.h" -#include "sysreg.h" +#include "../arm64/sysreg.h" #undef SYSREG #define SYSREG(op0,op1,Cn,Cm,op2) SPR(((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)) diff --git a/sys/src/9/bcm64/sysreg.h b/sys/src/9/bcm64/sysreg.h deleted file mode 100644 index 0d9b1b172..000000000 --- a/sys/src/9/bcm64/sysreg.h +++ /dev/null @@ -1,66 +0,0 @@ -#define MIDR_EL1 SYSREG(3,0,0,0,0) -#define MPIDR_EL1 SYSREG(3,0,0,0,5) -#define ID_AA64AFR0_EL1 SYSREG(3,0,0,5,4) -#define ID_AA64AFR1_EL1 SYSREG(3,0,0,5,5) -#define ID_AA64DFR0_EL1 SYSREG(3,0,0,5,0) -#define ID_AA64DFR1_EL1 SYSREG(3,0,0,5,1) -#define ID_AA64ISAR0_EL1 SYSREG(3,0,0,6,0) -#define ID_AA64ISAR1_EL1 SYSREG(3,0,0,6,1) -#define ID_AA64MMFR0_EL1 SYSREG(3,0,0,7,0) -#define ID_AA64MMFR1_EL1 SYSREG(3,0,0,7,1) -#define ID_AA64PFR0_EL1 SYSREG(3,0,0,4,0) -#define ID_AA64PFR1_EL1 SYSREG(3,0,0,4,1) -#define SCTLR_EL1 SYSREG(3,0,1,0,0) -#define CPACR_EL1 SYSREG(3,0,1,0,2) -#define MAIR_EL1 SYSREG(3,0,10,2,0) -#define TCR_EL1 SYSREG(3,0,2,0,2) -#define TTBR0_EL1 SYSREG(3,0,2,0,0) -#define TTBR1_EL1 SYSREG(3,0,2,0,1) -#define ESR_EL1 SYSREG(3,0,5,2,0) -#define FAR_EL1 SYSREG(3,0,6,0,0) -#define VBAR_EL1 SYSREG(3,0,12,0,0) -#define VTTBR_EL2 SYSREG(3,4,2,1,0) -#define SP_EL0 SYSREG(3,0,4,1,0) -#define SP_EL1 SYSREG(3,4,4,1,0) -#define SP_EL2 SYSREG(3,6,4,1,0) -#define SCTLR_EL2 SYSREG(3,4,1,0,0) -#define HCR_EL2 SYSREG(3,4,1,1,0) -#define MDCR_EL2 SYSREG(3,4,1,1,1) -#define PMCR_EL0 SYSREG(3,3,9,12,0) -#define PMCNTENSET SYSREG(3,3,9,12,1) -#define PMCCNTR_EL0 SYSREG(3,3,9,13,0) -#define PMUSERENR_EL0 SYSREG(3,3,9,14,0) - -#define CNTPCT_EL0 SYSREG(3,3,14,0,1) -#define CNTVCT_EL0 SYSREG(3,3,14,0,2) -#define CNTKCTL_EL1 SYSREG(3,0,14,1,0) -#define CNTP_TVAL_EL0 SYSREG(3,3,14,2,0) -#define CNTP_CTL_EL0 SYSREG(3,3,14,2,1) -#define CNTP_CVAL_EL0 SYSREG(3,3,14,2,2) - -#define TPIDR_EL0 SYSREG(3,3,13,0,2) -#define TPIDR_EL1 SYSREG(3,0,13,0,4) - -#define CCSIDR_EL1 SYSREG(3,1,0,0,0) -#define CSSELR_EL1 SYSREG(3,2,0,0,0) - -#define ACTLR_EL2 SYSREG(3,4,1,0,1) -#define CPUACTLR_EL1 SYSREG(3,1,15,2,0) -#define CPUECTLR_EL1 SYSREG(3,1,15,2,1) -#define CBAR_EL1 SYSREG(3,1,15,3,0) - -/* l.s redefines this for the assembler */ -#define SYSREG(op0,op1,Cn,Cm,op2) ((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5) - -#define OSHLD (0<<2 | 1) -#define OSHST (0<<2 | 2) -#define OSH (0<<2 | 3) -#define NSHLD (1<<2 | 1) -#define NSHST (1<<2 | 2) -#define NSH (1<<2 | 3) -#define ISHLD (2<<2 | 1) -#define ISHST (2<<2 | 2) -#define ISH (2<<2 | 3) -#define LD (3<<2 | 1) -#define ST (3<<2 | 2) -#define SY (3<<2 | 3) diff --git a/sys/src/9/bcm64/trap.c b/sys/src/9/bcm64/trap.c deleted file mode 100644 index 1b51c148c..000000000 --- a/sys/src/9/bcm64/trap.c +++ /dev/null @@ -1,688 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "../port/systab.h" - -#include <tos.h> -#include "ureg.h" -#include "sysreg.h" - -int (*buserror)(Ureg*); - -/* SPSR bits user can modify */ -#define USPSRMASK (0xFULL<<28) - -static void -setupvector(u32int *v, void (*t)(void), void (*f)(void)) -{ - int i; - - for(i = 0; i < 0x80/4; i++){ - v[i] = ((u32int*)t)[i]; - if(v[i] == 0x14000000){ - v[i] |= ((u32int*)f - &v[i]) & 0x3ffffff; - return; - } - } - panic("bug in vector code"); -} - -void -trapinit(void) -{ - extern void vsys(void); - extern void vtrap(void); - extern void virq(void); - extern void vfiq(void); - extern void vserr(void); - - extern void vsys0(void); - extern void vtrap0(void); - extern void vtrap1(void); - - static u32int *v; - - intrcpushutdown(); - if(v == nil){ - /* disable everything */ - intrsoff(); - - v = mallocalign(0x80*4*4, 1<<11, 0, 0); - if(v == nil) - panic("no memory for vector table"); - - setupvector(&v[0x000/4], vtrap, vtrap0); - setupvector(&v[0x080/4], virq, vtrap0); - setupvector(&v[0x100/4], vfiq, vtrap0); - setupvector(&v[0x180/4], vserr, vtrap0); - - setupvector(&v[0x200/4], vtrap, vtrap1); - setupvector(&v[0x280/4], virq, vtrap1); - setupvector(&v[0x300/4], vfiq, vtrap1); - setupvector(&v[0x380/4], vserr, vtrap1); - - setupvector(&v[0x400/4], vsys, vsys0); - setupvector(&v[0x480/4], virq, vtrap0); - setupvector(&v[0x500/4], vfiq, vtrap0); - setupvector(&v[0x580/4], vserr, vtrap0); - - setupvector(&v[0x600/4], vtrap, vtrap0); - setupvector(&v[0x680/4], virq, vtrap0); - setupvector(&v[0x700/4], vfiq, vtrap0); - setupvector(&v[0x780/4], vserr, vtrap0); - - cacheduwbse(v, 0x80*4*4); - } - cacheiinvse(v, 0x80*4*4); - syswr(VBAR_EL1, (uintptr)v); - splx(0x3<<6); // unmask serr and debug -} - -static char *traps[64] = { - [0x00] "sys: trap: unknown", - [0x01] "sys: trap: WFI or WFE instruction execution", - [0x0E] "sys: trap: illegal execution state", - [0x18] "sys: trap: illegal MSR/MRS access", - [0x22] "sys: trap: misaligned pc", - [0x26] "sys: trap: stack pointer misaligned", - [0x30] "sys: breakpoint", - [0x32] "sys: software step", - [0x34] "sys: watchpoint", - [0x3C] "sys: breakpoint", -}; - -void -trap(Ureg *ureg) -{ - FPsave *f = nil; - u32int type, intr; - int user; - - intr = ureg->type >> 32; - if(intr == 2){ - fiq(ureg); - return; - } - splflo(); - user = kenter(ureg); - type = (u32int)ureg->type >> 26; - switch(type){ - case 0x20: // instruction abort from lower level - case 0x21: // instruction abort from same level - case 0x24: // data abort from lower level - case 0x25: // data abort from same level - f = fpukenter(ureg); - faultarm64(ureg); - break; - case 0x07: // SIMD/FP - case 0x2C: // FPU exception (A64 only) - mathtrap(ureg); - break; - case 0x00: // unknown - if(intr == 1){ - f = fpukenter(ureg); - if(!irq(ureg)) - preempted(); - else if(up != nil && up->delaysched) - sched(); - break; - } - if(intr == 3){ - case 0x2F: // SError interrupt - f = fpukenter(ureg); - if(buserror != nil && (*buserror)(ureg)) - break; - dumpregs(ureg); - panic("SError interrupt"); - break; - } - /* wet floor */ - case 0x01: // WFI or WFE instruction execution - case 0x03: // MCR or MRC access to CP15 (A32 only) - case 0x04: // MCRR or MRC access to CP15 (A32 only) - case 0x05: // MCR or MRC access to CP14 (A32 only) - case 0x06: // LDC or STD access to CP14 (A32 only) - case 0x08: // MCR or MRC to CP10 (A32 only) - case 0x0C: // MRC access to CP14 (A32 only) - case 0x0E: // Illegal Execution State - case 0x11: // SVC instruction execution (A32 only) - case 0x12: // HVC instruction execution (A32 only) - case 0x13: // SMC instruction execution (A32 only) - case 0x15: // SVC instruction execution (A64 only) - case 0x16: // HVC instruction execution (A64 only) - case 0x17: // SMC instruction execution (A64 only) - case 0x18: // MSR/MRS (A64) - case 0x22: // misaligned pc - case 0x26: // stack pointer misaligned - case 0x28: // FPU exception (A32 only) - case 0x30: // breakpoint from lower level - case 0x31: // breakpoint from same level - case 0x32: // software step from lower level - case 0x33: // software step from same level - case 0x34: // watchpoint execution from lower level - case 0x35: // watchpoint exception from same level - case 0x38: // breapoint (A32 only) - case 0x3A: // vector catch exception (A32 only) - case 0x3C: // BRK instruction (A64 only) - default: - f = fpukenter(ureg); - if(!userureg(ureg)){ - dumpregs(ureg); - panic("unhandled trap"); - } - if(traps[type] == nil) type = 0; // unknown - postnote(up, 1, traps[type], NDebug); - break; - } - - splhi(); - if(user){ - if(up->procctl || up->nnote) - notify(ureg); - kexit(ureg); - } - if(type != 0x07 && type != 0x2C) - fpukexit(ureg, f); -} - -void -syscall(Ureg *ureg) -{ - vlong startns, stopns; - uintptr sp, ret; - ulong scallnr; - int i, s; - char *e; - - if(!kenter(ureg)) - panic("syscall from kernel"); - fpukenter(ureg); - - m->syscall++; - up->insyscall = 1; - up->pc = ureg->pc; - - sp = ureg->sp; - up->scallnr = scallnr = ureg->r0; - spllo(); - - up->nerrlab = 0; - startns = 0; - ret = -1; - if(!waserror()){ - if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){ - validaddr(sp, sizeof(Sargs)+BY2WD, 0); - evenaddr(sp); - } - up->s = *((Sargs*) (sp + BY2WD)); - - if(up->procctl == Proc_tracesyscall){ - syscallfmt(scallnr, ureg->pc, (va_list) up->s.args); - s = splhi(); - up->procctl = Proc_stopme; - procctl(); - splx(s); - startns = todget(nil); - } - - if(scallnr >= nsyscall || systab[scallnr] == nil){ - pprint("bad sys call number %lud pc %#p", scallnr, ureg->pc); - postnote(up, 1, "sys: bad sys call", NDebug); - error(Ebadarg); - } - up->psstate = sysctab[scallnr]; - ret = systab[scallnr]((va_list)up->s.args); - poperror(); - }else{ - e = up->syserrstr; - up->syserrstr = up->errstr; - up->errstr = e; - } - if(up->nerrlab){ - print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab); - for(i = 0; i < NERR; i++) - print("sp=%#p pc=%#p\n", up->errlab[i].sp, up->errlab[i].pc); - panic("error stack"); - } - ureg->r0 = ret; - if(up->procctl == Proc_tracesyscall){ - stopns = todget(nil); - sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns); - s = splhi(); - up->procctl = Proc_stopme; - procctl(); - splx(s); - } - up->insyscall = 0; - up->psstate = 0; - - if(scallnr == NOTED){ - noted(ureg, *((ulong*) up->s.args)); - /* - * normally, syscall() returns to forkret() - * not restoring general registers when going - * to userspace. to completely restore the - * interrupted context, we have to return thru - * noteret(). we override return pc to jump to - * to it when returning form syscall() - */ - returnto(noteret); - - splhi(); - up->fpstate &= ~FPillegal; - } - else - splhi(); - - if(scallnr != RFORK && (up->procctl || up->nnote)) - notify(ureg); - - if(up->delaysched){ - sched(); - splhi(); - } - - kexit(ureg); - fpukexit(ureg, nil); -} - -int -notify(Ureg *ureg) -{ - uintptr sp; - char *msg; - - if(up->procctl) - procctl(); - if(up->nnote == 0) - return 0; - - spllo(); - qlock(&up->debug); - msg = popnote(ureg); - if(msg == nil){ - qunlock(&up->debug); - splhi(); - return 0; - } - - sp = ureg->sp; - sp -= 256; /* debugging: preserve context causing problem */ - sp -= sizeof(Ureg); - sp = STACKALIGN(sp); - - if(!okaddr((uintptr)up->notify, 1, 0) - || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1) - || ((uintptr) up->notify & 3) != 0 - || (sp & 7) != 0){ - qunlock(&up->debug); - pprint("suicide: bad address in notify: handler=%#p sp=%#p\n", - up->notify, sp); - pexit("Suicide", 0); - } - - memmove((Ureg*)sp, ureg, sizeof(Ureg)); - *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */ - up->ureg = (void*)sp; - sp -= BY2WD+ERRMAX; - memmove((char*)sp, msg, ERRMAX); - sp -= 3*BY2WD; - *(uintptr*)(sp+2*BY2WD) = sp+3*BY2WD; - *(uintptr*)(sp+1*BY2WD) = (uintptr)up->ureg; - ureg->r0 = (uintptr) up->ureg; - ureg->sp = sp; - ureg->pc = (uintptr) up->notify; - ureg->link = 0; - qunlock(&up->debug); - - splhi(); - fpuprocsave(up); - up->fpstate |= FPillegal; - return 1; -} - -void -noted(Ureg *ureg, ulong arg0) -{ - Ureg *nureg; - uintptr oureg, sp; - - qlock(&up->debug); - if(arg0 != NRSTR && !up->notified){ - qunlock(&up->debug); - pprint("call to noted() when not notified\n"); - pexit("Suicide", 0); - } - up->notified = 0; - - nureg = up->ureg; - - oureg = (uintptr) nureg; - if(!okaddr(oureg - BY2WD, BY2WD + sizeof(Ureg), 0) || (oureg & 7) != 0){ - qunlock(&up->debug); - pprint("bad ureg in noted or call to noted when not notified\n"); - pexit("Suicide", 0); - } - - nureg->psr = (nureg->psr & USPSRMASK) | (ureg->psr & ~USPSRMASK); - memmove(ureg, nureg, sizeof(Ureg)); - - switch(arg0){ - case NCONT: case NRSTR: - if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) || - (nureg->pc & 3) != 0 || (nureg->sp & 7) != 0){ - qunlock(&up->debug); - pprint("suicide: trap in noted\n"); - pexit("Suicide", 0); - } - up->ureg = (Ureg *) (*(uintptr*) (oureg - BY2WD)); - qunlock(&up->debug); - break; - - case NSAVE: - if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) || - (nureg->pc & 3) != 0 || (nureg->sp & 7) != 0){ - qunlock(&up->debug); - pprint("suicide: trap in noted\n"); - pexit("Suicide", 0); - } - qunlock(&up->debug); - sp = oureg - 4 * BY2WD - ERRMAX; - ureg->sp = sp; - ureg->r0 = (uintptr) oureg; - ((uintptr *) sp)[1] = oureg; - ((uintptr *) sp)[0] = 0; - break; - - default: - up->lastnote->flag = NDebug; - - case NDFLT: - qunlock(&up->debug); - if(up->lastnote->flag == NDebug) - pprint("suicide: %s\n", up->lastnote->msg); - pexit(up->lastnote->msg, up->lastnote->flag != NDebug); - } -} - -static void -faultnote(Ureg *ureg, char *access, uintptr addr) -{ - extern void checkpages(void); - char buf[ERRMAX]; - - if(!userureg(ureg)){ - dumpregs(ureg); - panic("fault: %s addr=%#p", access, addr); - } - checkpages(); - snprint(buf, sizeof(buf), "sys: trap: fault %s addr=%#p", access, addr); - postnote(up, 1, buf, NDebug); -} - -void -faultarm64(Ureg *ureg) -{ - int user, read; - uintptr addr; - - user = userureg(ureg); - if(user) - up->insyscall = 1; - else { - extern void _peekinst(void); - - if(ureg->pc == (uintptr)_peekinst){ - ureg->pc = ureg->link; - return; - } - if(waserror()){ - if(up->nerrlab == 0){ - pprint("suicide: sys: %s\n", up->errstr); - pexit(up->errstr, 1); - } - nexterror(); - } - } - - addr = getfar(); - read = (ureg->type & (1<<6)) == 0; - - switch((u32int)ureg->type & 0x3F){ - case 4: case 5: case 6: case 7: // Tanslation fault. - case 8: case 9: case 10: case 11: // Access flag fault. - case 12: case 13: case 14: case 15: // Permission fault. - case 48: // tlb conflict fault. - if(fault(addr, ureg->pc, read) == 0) - break; - - /* wet floor */ - case 0: case 1: case 2: case 3: // Address size fault. - case 16: // synchronous external abort. - case 24: // synchronous parity error on a memory access. - case 20: case 21: case 22: case 23: // synchronous external abort on a table walk. - case 28: case 29: case 30: case 31: // synchronous parity error on table walk. - case 33: // alignment fault. - case 52: // implementation defined, lockdown abort. - case 53: // implementation defined, unsuppoted exclusive. - case 61: // first level domain fault - case 62: // second level domain fault - default: - faultnote(ureg, read? "read": "write", addr); - } - - if(user) - up->insyscall = 0; - else - poperror(); -} - -int -userureg(Ureg* ureg) -{ - return (ureg->psr & 15) == 0; -} - -uintptr -userpc(void) -{ - Ureg *ur = up->dbgreg; - return ur->pc; -} - -uintptr -dbgpc(Proc *) -{ - Ureg *ur = up->dbgreg; - if(ur == nil) - return 0; - return ur->pc; -} - -void -procfork(Proc *p) -{ - fpuprocfork(p); - p->tpidr = up->tpidr; -} - -void -procsetup(Proc *p) -{ - fpuprocsetup(p); - p->tpidr = 0; - syswr(TPIDR_EL0, p->tpidr); -} - -void -procsave(Proc *p) -{ - fpuprocsave(p); - if(p->kp == 0) - p->tpidr = sysrd(TPIDR_EL0); - putasid(p); // release asid -} - -void -procrestore(Proc *p) -{ - fpuprocrestore(p); - if(p->kp == 0) - syswr(TPIDR_EL0, p->tpidr); -} - -void -kprocchild(Proc *p, void (*entry)(void)) -{ - p->sched.pc = (uintptr) entry; - p->sched.sp = (uintptr) p - 16; - *(void**)p->sched.sp = kprocchild; /* fake */ -} - -void -forkchild(Proc *p, Ureg *ureg) -{ - Ureg *cureg; - - p->sched.pc = (uintptr) forkret; - p->sched.sp = (uintptr) p - TRAPFRAMESIZE; - - cureg = (Ureg*) (p->sched.sp + 16); - memmove(cureg, ureg, sizeof(Ureg)); - cureg->r0 = 0; -} - -uintptr -execregs(uintptr entry, ulong ssize, ulong nargs) -{ - uintptr *sp; - Ureg *ureg; - - sp = (uintptr*)(USTKTOP - ssize); - *--sp = nargs; - - ureg = up->dbgreg; - ureg->sp = (uintptr)sp; - ureg->pc = entry; - ureg->link = 0; - return USTKTOP-sizeof(Tos); -} - -void -evenaddr(uintptr addr) -{ - if(addr & 3){ - postnote(up, 1, "sys: odd address", NDebug); - error(Ebadarg); - } -} - -void -callwithureg(void (*f) (Ureg *)) -{ - Ureg u; - - u.pc = getcallerpc(&f); - u.sp = (uintptr) &f; - f(&u); -} - -void -setkernur(Ureg *ureg, Proc *p) -{ - ureg->pc = p->sched.pc; - ureg->sp = p->sched.sp; - ureg->link = (uintptr)sched; -} - -void -setupwatchpts(Proc*, Watchpt*, int) -{ -} - -void -setregisters(Ureg* ureg, char* pureg, char* uva, int n) -{ - ulong v; - - v = ureg->psr; - memmove(pureg, uva, n); - ureg->psr = (ureg->psr & USPSRMASK) | (v & ~USPSRMASK); -} - -static void -dumpstackwithureg(Ureg *ureg) -{ - uintptr v, estack, sp; - char *s; - int i; - - if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){ - iprint("dumpstack disabled\n"); - return; - } - iprint("ktrace /kernel/path %#p %#p %#p # pc, sp, link\n", - ureg->pc, ureg->sp, ureg->link); - delay(2000); - - sp = ureg->sp; - if(sp < KZERO || (sp & 7) != 0) - sp = (uintptr)&ureg; - - estack = (uintptr)m+MACHSIZE; - if(up != nil && sp <= (uintptr)up) - estack = (uintptr)up; - - if(sp > estack){ - if(up != nil) - iprint("&up %#p sp %#p\n", up, sp); - else - iprint("&m %#p sp %#p\n", m, sp); - return; - } - - i = 0; - for(; sp < estack; sp += sizeof(uintptr)){ - v = *(uintptr*)sp; - if(KTZERO < v && v < (uintptr)etext && (v & 3) == 0){ - iprint("%#8.8lux=%#8.8lux ", (ulong)sp, (ulong)v); - i++; - } - if(i == 4){ - i = 0; - iprint("\n"); - } - } - if(i) - iprint("\n"); -} - -void -dumpstack(void) -{ - callwithureg(dumpstackwithureg); -} - -void -dumpregs(Ureg *ureg) -{ - u64int *r; - int i, x; - - x = splhi(); - if(up != nil) - iprint("cpu%d: dumpregs ureg %#p process %lud: %s\n", m->machno, ureg, - up->pid, up->text); - else - iprint("cpu%d: dumpregs ureg %#p\n", m->machno, ureg); - r = &ureg->r0; - for(i = 0; i < 30; i += 3) - iprint("R%d %.16llux R%d %.16llux R%d %.16llux\n", i, r[i], i+1, r[i+1], i+2, r[i+2]); - iprint("PC %#p SP %#p LR %#p PSR %llux TYPE %llux\n", - ureg->pc, ureg->sp, ureg->link, - ureg->psr, ureg->type); - splx(x); -} |