ref: 8b1e81d71f4d898c97460578fe282f2ebeb5a1de
parent: abe9dad9530b68b427a706d6f4c3947dd5d9cc73
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 29 12:36:51 EDT 2023
bcm64: use generic 9/arm64/* files
--- 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;
--- 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;
--- a/sys/src/9/bcm64/cache.v8.s
+++ /dev/null
@@ -1,212 +1,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
--- 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,
--- a/sys/src/9/bcm64/fpu.c
+++ /dev/null
@@ -1,289 +1,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;
- }
-}
--- 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 {
--- a/sys/src/9/bcm64/init9.s
+++ /dev/null
@@ -1,4 +1,0 @@
-TEXT main(SB), 1, $8
- MOV $setSB(SB), R28 /* load the SB */
- MOV $boot(SB), R0
- B startboot(SB)
--- 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))
--- 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>
--- a/sys/src/9/bcm64/mkfile
+++ b/sys/src/9/bcm64/mkfile
@@ -88,8 +88,16 @@
/$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 @@
/$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
--- 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)
--- 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))
--- a/sys/src/9/bcm64/sysreg.h
+++ /dev/null
@@ -1,66 +1,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)
--- a/sys/src/9/bcm64/trap.c
+++ /dev/null
@@ -1,688 +1,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);
-}