added omap4 kernel prototype
parent
df91e24667
commit
d886c9d248
|
@ -0,0 +1,161 @@
|
|||
#include "u.h"
|
||||
#include "ureg.h"
|
||||
#include "../port/lib.h"
|
||||
#include "../port/error.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "arm.h"
|
||||
#include "tos.h"
|
||||
|
||||
void (*proctrace)(Proc *, int, vlong);
|
||||
|
||||
ulong
|
||||
userpc(void)
|
||||
{
|
||||
return dbgpc(up);
|
||||
}
|
||||
|
||||
ulong
|
||||
dbgpc(Proc *p)
|
||||
{
|
||||
Ureg *ureg;
|
||||
|
||||
ureg = p->dbgreg;
|
||||
if(ureg == 0)
|
||||
return 0;
|
||||
return ureg->pc;
|
||||
}
|
||||
|
||||
void
|
||||
procsave(Proc *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
procrestore(Proc *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
procfork(Proc *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
procsetup(Proc *p)
|
||||
{
|
||||
p->fpstate = FPinit;
|
||||
}
|
||||
|
||||
static void
|
||||
linkproc(void)
|
||||
{
|
||||
spllo();
|
||||
up->kpfun(up->kparg);
|
||||
pexit("kproc exiting", 0);
|
||||
}
|
||||
|
||||
void
|
||||
kprocchild(Proc *p, void (*func)(void *), void *arg)
|
||||
{
|
||||
p->sched.pc = (ulong) linkproc;
|
||||
p->sched.sp = (ulong) p->kstack + KSTACK;
|
||||
p->kpfun = func;
|
||||
p->kparg = arg;
|
||||
}
|
||||
|
||||
void
|
||||
forkchild(Proc *p, Ureg *ureg)
|
||||
{
|
||||
Ureg *cureg;
|
||||
|
||||
p->sched.sp = (ulong) p->kstack + KSTACK - (sizeof(Ureg) + 8);
|
||||
p->sched.pc = (ulong) forkret;
|
||||
cureg = (Ureg*) (p->sched.sp + 8);
|
||||
memmove(cureg, ureg, sizeof(Ureg));
|
||||
cureg->r0 = 0;
|
||||
p->psstate = 0;
|
||||
p->insyscall = 0;
|
||||
}
|
||||
|
||||
long
|
||||
execregs(ulong entry, ulong ssize, ulong nargs)
|
||||
{
|
||||
ulong *sp;
|
||||
Ureg *ureg;
|
||||
|
||||
up->fpstate = FPinit;
|
||||
sp = (ulong *) (USTKTOP - ssize);
|
||||
*--sp = nargs;
|
||||
|
||||
ureg = up->dbgreg;
|
||||
memset(ureg, 0, sizeof *ureg);
|
||||
ureg->psr = PsrMusr;
|
||||
ureg->sp = (ulong) sp;
|
||||
ureg->pc = entry;
|
||||
return USTKTOP - sizeof(Tos);
|
||||
}
|
||||
|
||||
void
|
||||
evenaddr(uintptr addr)
|
||||
{
|
||||
if(addr & 3){
|
||||
postnote(up, 1, "sys: odd address", NDebug);
|
||||
error(Ebadarg);
|
||||
}
|
||||
}
|
||||
|
||||
Segment *
|
||||
data2txt(Segment *)
|
||||
{
|
||||
panic("data2txt");
|
||||
}
|
||||
|
||||
void
|
||||
_dumpstack(ulong sp, ulong pc)
|
||||
{
|
||||
int x;
|
||||
uintptr l, v, i, estack;
|
||||
|
||||
x = 0;
|
||||
x += iprint("ktrace /arm/s9panda %#.8lux %#.8lux <<EOF\n",
|
||||
pc, sp);
|
||||
i = 0;
|
||||
if(up
|
||||
&& (uintptr)&l >= (uintptr)up->kstack
|
||||
&& (uintptr)&l <= (uintptr)up->kstack+KSTACK)
|
||||
estack = (uintptr)up->kstack+KSTACK;
|
||||
else if((uintptr)&l >= (uintptr)(KTZERO - BY2PG)
|
||||
&& (uintptr)&l <= (uintptr)KTZERO)
|
||||
estack = (uintptr)KTZERO;
|
||||
else
|
||||
return;
|
||||
x += iprint("estackx %p\n", estack);
|
||||
|
||||
for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
|
||||
v = *(uintptr*)l;
|
||||
if((KTZERO < v && v < (uintptr)etext) || estack-l < 32){
|
||||
x += iprint("%.8p=%.8p ", l, v);
|
||||
i++;
|
||||
}
|
||||
if(i == 4){
|
||||
i = 0;
|
||||
x += iprint("\n");
|
||||
}
|
||||
}
|
||||
if(i)
|
||||
iprint("\n");
|
||||
iprint("EOF\n");
|
||||
}
|
||||
|
||||
void
|
||||
printureg(Ureg *ureg)
|
||||
{
|
||||
print("R0 %.8ulx R1 %.8ulx R2 %.8ulx R3 %.8ulx\n", ureg->r0, ureg->r1, ureg->r2, ureg->r3);
|
||||
print("R4 %.8ulx R5 %.8ulx R6 %.8ulx R7 %.8ulx\n", ureg->r4, ureg->r5, ureg->r6, ureg->r7);
|
||||
print("R8 %.8ulx R9 %.8ulx R10 %.8ulx R11 %.8ulx\n", ureg->r8, ureg->r9, ureg->r10, ureg->r11);
|
||||
print("R12 %.8ulx R13 %.8ulx R14 %.8ulx R15 %.8ulx\n", ureg->r12, ureg->r13, ureg->r14, ureg->pc);
|
||||
print("PSR %.8ulx exception %ld\n", ureg->psr, ureg->type);
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* arm-specific definitions for cortex-a8
|
||||
* these are used in C and assembler
|
||||
*
|
||||
* `cortex' refers specifically to the cortex-a8.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program Status Registers
|
||||
*/
|
||||
#define PsrMusr 0x00000010 /* mode */
|
||||
#define PsrMfiq 0x00000011
|
||||
#define PsrMirq 0x00000012
|
||||
#define PsrMsvc 0x00000013 /* `protected mode for OS' */
|
||||
#define PsrMmon 0x00000016 /* `secure monitor' (trustzone hyper) */
|
||||
#define PsrMabt 0x00000017
|
||||
#define PsrMund 0x0000001B
|
||||
#define PsrMsys 0x0000001F /* `privileged user mode for OS' (trustzone) */
|
||||
#define PsrMask 0x0000001F
|
||||
|
||||
#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
|
||||
#define PsrDirq 0x00000080 /* disable IRQ interrupts */
|
||||
|
||||
#define PsrV 0x10000000 /* overflow */
|
||||
#define PsrC 0x20000000 /* carry/borrow/extend */
|
||||
#define PsrZ 0x40000000 /* zero */
|
||||
#define PsrN 0x80000000 /* negative/less than */
|
||||
|
||||
/*
|
||||
* Coprocessors
|
||||
*/
|
||||
#define CpFP 10 /* float FP, VFP cfg. */
|
||||
#define CpDFP 11 /* double FP */
|
||||
#define CpSC 15 /* System Control */
|
||||
|
||||
/*
|
||||
* Primary (CRn) CpSC registers.
|
||||
*/
|
||||
#define CpID 0 /* ID and cache type */
|
||||
#define CpCONTROL 1 /* miscellaneous control */
|
||||
#define CpTTB 2 /* Translation Table Base(s) */
|
||||
#define CpDAC 3 /* Domain Access Control */
|
||||
#define CpFSR 5 /* Fault Status */
|
||||
#define CpFAR 6 /* Fault Address */
|
||||
#define CpCACHE 7 /* cache/write buffer control */
|
||||
#define CpTLB 8 /* TLB control */
|
||||
#define CpCLD 9 /* L2 Cache Lockdown, op1==1 */
|
||||
#define CpTLD 10 /* TLB Lockdown, with op2 */
|
||||
#define CpVECS 12 /* vector bases, op1==0, Crm==0, op2s (cortex) */
|
||||
#define CpPID 13 /* Process ID */
|
||||
#define CpDTLB 15 /* TLB, L1 cache stuff (cortex) */
|
||||
|
||||
/*
|
||||
* CpTTB op1==0, Crm==0 opcode2 values.
|
||||
*/
|
||||
#define CpTTB0 0
|
||||
#define CpTTB1 1 /* cortex */
|
||||
#define CpTTBctl 2 /* cortex */
|
||||
|
||||
/*
|
||||
* CpID Secondary (CRm) registers.
|
||||
*/
|
||||
#define CpIDidct 0
|
||||
|
||||
/*
|
||||
* CpID op1==0 opcode2 fields.
|
||||
* the cortex has more op1 codes for cache size, etc.
|
||||
*/
|
||||
#define CpIDid 0 /* main ID */
|
||||
#define CpIDct 1 /* cache type */
|
||||
#define CpIDtlb 3 /* tlb type (cortex) */
|
||||
#define CpIDmpid 5 /* multiprocessor id (cortex) */
|
||||
|
||||
/* CpIDid op1 values */
|
||||
#define CpIDcsize 1 /* cache size (cortex) */
|
||||
#define CpIDcssel 2 /* cache size select (cortex) */
|
||||
|
||||
/*
|
||||
* CpCONTROL op2 codes, op1==0, Crm==0.
|
||||
*/
|
||||
#define CpMainctl 0
|
||||
#define CpAuxctl 1
|
||||
#define CpCPaccess 2
|
||||
|
||||
/*
|
||||
* CpCONTROL: op1==0, CRm==0, op2==CpMainctl.
|
||||
* main control register.
|
||||
* cortex/armv7 has more ops and CRm values.
|
||||
*/
|
||||
#define CpCmmu 0x00000001 /* M: MMU enable */
|
||||
#define CpCalign 0x00000002 /* A: alignment fault enable */
|
||||
#define CpCdcache 0x00000004 /* C: data cache on */
|
||||
#define CpCsbo (3<<22|1<<18|1<<16|017<<3) /* must be 1 (armv7) */
|
||||
#define CpCsbz (CpCtre|1<<26|CpCve|1<<15|7<<7) /* must be 0 (armv7) */
|
||||
#define CpCsw (1<<10) /* SW: SWP(B) enable (deprecated in v7) */
|
||||
#define CpCpredict 0x00000800 /* Z: branch prediction (armv7) */
|
||||
#define CpCicache 0x00001000 /* I: instruction cache on */
|
||||
#define CpChv 0x00002000 /* V: high vectors */
|
||||
#define CpCrr (1<<14) /* RR: round robin vs random cache replacement */
|
||||
#define CpCha (1<<17) /* HA: hw access flag enable */
|
||||
#define CpCdz (1<<19) /* DZ: divide by zero fault enable */
|
||||
#define CpCfi (1<<21) /* FI: fast intrs */
|
||||
#define CpCve (1<<24) /* VE: intr vectors enable */
|
||||
#define CpCee (1<<25) /* EE: exception endianness */
|
||||
#define CpCnmfi (1<<27) /* NMFI: non-maskable fast intrs. */
|
||||
#define CpCtre (1<<28) /* TRE: TEX remap enable */
|
||||
#define CpCafe (1<<29) /* AFE: access flag (ttb) enable */
|
||||
|
||||
/*
|
||||
* CpCONTROL: op1==0, CRm==0, op2==CpAuxctl.
|
||||
* Auxiliary control register on cortex at least.
|
||||
*/
|
||||
#define CpACcachenopipe (1<<20) /* don't pipeline cache maint. */
|
||||
#define CpACcp15serial (1<<18) /* serialise CP1[45] ops. */
|
||||
#define CpACcp15waitidle (1<<17) /* CP1[45] wait-on-idle */
|
||||
#define CpACcp15pipeflush (1<<16) /* CP1[45] flush pipeline */
|
||||
#define CpACneonissue1 (1<<12) /* neon single issue */
|
||||
#define CpACldstissue1 (1<<11) /* force single issue ld, st */
|
||||
#define CpACissue1 (1<<10) /* force single issue */
|
||||
#define CpACnobsm (1<<7) /* no branch size mispredicts */
|
||||
#define CpACibe (1<<6) /* cp15 invalidate & btb enable */
|
||||
#define CpACl1neon (1<<5) /* cache neon (FP) data in L1 cache */
|
||||
#define CpACasa (1<<4) /* enable speculative accesses */
|
||||
#define CpACl1pe (1<<3) /* l1 cache parity enable */
|
||||
#define CpACl2en (1<<1) /* l2 cache enable; default 1 */
|
||||
/*
|
||||
* CpCONTROL Secondary (CRm) registers and opcode2 fields.
|
||||
*/
|
||||
#define CpCONTROLscr 1
|
||||
|
||||
#define CpSCRscr 0
|
||||
|
||||
/*
|
||||
* CpCACHE Secondary (CRm) registers and opcode2 fields. op1==0.
|
||||
* In ARM-speak, 'flush' means invalidate and 'clean' means writeback.
|
||||
*/
|
||||
#define CpCACHEintr 0 /* interrupt (op2==4) */
|
||||
#define CpCACHEisi 1 /* inner-sharable I cache (v7) */
|
||||
#define CpCACHEpaddr 4 /* 0: phys. addr (cortex) */
|
||||
#define CpCACHEinvi 5 /* instruction, branch table */
|
||||
#define CpCACHEinvd 6 /* data or unified */
|
||||
// #define CpCACHEinvu 7 /* unified (not on cortex) */
|
||||
#define CpCACHEva2pa 8 /* va -> pa translation (cortex) */
|
||||
#define CpCACHEwb 10 /* writeback */
|
||||
#define CpCACHEinvdse 11 /* data or unified by mva */
|
||||
#define CpCACHEwbi 14 /* writeback+invalidate */
|
||||
|
||||
#define CpCACHEall 0 /* entire (not for invd nor wb(i) on cortex) */
|
||||
#define CpCACHEse 1 /* single entry */
|
||||
#define CpCACHEsi 2 /* set/index (set/way) */
|
||||
#define CpCACHEtest 3 /* test loop */
|
||||
#define CpCACHEwait 4 /* wait (prefetch flush on cortex) */
|
||||
#define CpCACHEdmbarr 5 /* wb only (cortex) */
|
||||
#define CpCACHEflushbtc 6 /* flush branch-target cache (cortex) */
|
||||
#define CpCACHEflushbtse 7 /* ⋯ or just one entry in it (cortex) */
|
||||
|
||||
/*
|
||||
* CpTLB Secondary (CRm) registers and opcode2 fields.
|
||||
*/
|
||||
#define CpTLBinvi 5 /* instruction */
|
||||
#define CpTLBinvd 6 /* data */
|
||||
#define CpTLBinvu 7 /* unified */
|
||||
|
||||
#define CpTLBinv 0 /* invalidate all */
|
||||
#define CpTLBinvse 1 /* invalidate single entry */
|
||||
#define CpTBLasid 2 /* by ASID (cortex) */
|
||||
|
||||
/*
|
||||
* CpCLD Secondary (CRm) registers and opcode2 fields for op1==0. (cortex)
|
||||
*/
|
||||
#define CpCLDena 12 /* enables */
|
||||
#define CpCLDcyc 13 /* cycle counter */
|
||||
#define CpCLDuser 14 /* user enable */
|
||||
|
||||
#define CpCLDenapmnc 0
|
||||
#define CpCLDenacyc 1
|
||||
|
||||
/*
|
||||
* CpCLD Secondary (CRm) registers and opcode2 fields for op1==1.
|
||||
*/
|
||||
#define CpCLDl2 0 /* l2 cache */
|
||||
|
||||
#define CpCLDl2aux 2 /* auxiliary control */
|
||||
|
||||
/*
|
||||
* l2 cache aux. control
|
||||
*/
|
||||
#define CpCl2ecc (1<<28) /* use ecc, not parity */
|
||||
#define CpCl2noldforw (1<<27) /* no ld forwarding */
|
||||
#define CpCl2nowrcomb (1<<25) /* no write combining */
|
||||
#define CpCl2nowralldel (1<<24) /* no write allocate delay */
|
||||
#define CpCl2nowrallcomb (1<<23) /* no write allocate combine */
|
||||
#define CpCl2nowralloc (1<<22) /* no write allocate */
|
||||
#define CpCl2eccparity (1<<21) /* enable ecc or parity */
|
||||
#define CpCl2inner (1<<16) /* inner cacheability */
|
||||
/* other bits are tag ram & data ram latencies */
|
||||
|
||||
/*
|
||||
* CpTLD Secondary (CRm) registers and opcode2 fields.
|
||||
*/
|
||||
#define CpTLDlock 0 /* TLB lockdown registers */
|
||||
#define CpTLDpreload 1 /* TLB preload */
|
||||
|
||||
#define CpTLDi 0 /* TLB instr. lockdown reg. */
|
||||
#define CpTLDd 1 /* " data " " */
|
||||
|
||||
/*
|
||||
* CpVECS Secondary (CRm) registers and opcode2 fields.
|
||||
*/
|
||||
#define CpVECSbase 0
|
||||
|
||||
#define CpVECSnorm 0 /* (non-)secure base addr */
|
||||
#define CpVECSmon 1 /* secure monitor base addr */
|
||||
|
||||
/*
|
||||
* MMU page table entries.
|
||||
*/
|
||||
#define Fault 0x00000000 /* L[12] pte: unmapped */
|
||||
|
||||
#define Coarse (1) /* L1 */
|
||||
#define Section (2) /* L1 1MB */
|
||||
#define Fine (3) /* L1 */
|
||||
|
||||
#define Large 0x00000001 /* L2 64KB */
|
||||
#define Small 0x00000002 /* L2 4KB */
|
||||
#define Tiny 0x00000003 /* L2 1KB: not in v7 */
|
||||
#define Buffered 0x00000004 /* L[12]: write-back not -thru */
|
||||
#define Cached 0x00000008 /* L[12] */
|
||||
#define ExecuteNever (1<<4)
|
||||
|
||||
#define Noaccess 0 /* AP, DAC */
|
||||
#define Krw 1 /* AP */
|
||||
/* armv7 deprecates AP[2] == 1 & AP[1:0] == 2 (Uro), prefers 3 (new in v7) */
|
||||
#define Uro 2 /* AP */
|
||||
#define Urw 3 /* AP */
|
||||
#define Client 1 /* DAC */
|
||||
#define Manager 3 /* DAC */
|
||||
|
||||
#define AP(n, v) F((v), ((n)*2)+4, 2)
|
||||
#define L1AP(ap) (AP(3, (ap)))
|
||||
#define L2AP(ap) (AP(0, (ap))) /* armv7 */
|
||||
#define DAC(n, v) F((v), (n)*2, 2)
|
||||
|
||||
#define HVECTORS 0xffff0000
|
||||
#define PTEDRAM (L1AP(Krw)|Section|Cached|Buffered)
|
||||
#define PTEIO (ExecuteNever)
|
|
@ -0,0 +1,31 @@
|
|||
#include "arm.h"
|
||||
|
||||
/* arm v7 arch defines these */
|
||||
#define WFI WORD $0xe320f003 /* wait for interrupt */
|
||||
#define DMB WORD $0xf57ff05f /* data mem. barrier; last f = SY */
|
||||
#define DSB WORD $0xf57ff04f /* data synch. barrier; last f = SY */
|
||||
#define ISB WORD $0xf57ff06f /* instr. sync. barrier; last f = SY */
|
||||
#define NOOP WORD $0xe320f000
|
||||
#define CLZ(s, d) WORD $(0xe16f0f10 | (d) << 12 | (s)) /* count leading 0s */
|
||||
#define CPSIE WORD $0xf1080080 /* intr enable: zeroes I bit */
|
||||
#define CPSID WORD $0xf10c0080 /* intr disable: sets I bit */
|
||||
|
||||
#define EWAVE(n)\
|
||||
MOVW $0x48020000, R0; \
|
||||
MOVW $n, R1; \
|
||||
MOVW R1, (R0);
|
||||
|
||||
#define WAVE(n)\
|
||||
MOVW $0xE0000000, R0; \
|
||||
MOVW $n, R1; \
|
||||
MOVW R1, (R0);
|
||||
|
||||
#define LDREX(a,r) WORD $(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12)
|
||||
#define STREX(a,v,r) WORD $(0xe<<28|0x01800f90 | (a)<<16 | (r)<<12 | (v)<<0)
|
||||
#define CLREX WORD $0xf57ff01f
|
||||
|
||||
#define BARRIERS\
|
||||
MOVW $0, R11; \
|
||||
MCR CpSC, 0, R11, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtc; \
|
||||
DSB; \
|
||||
ISB;
|
|
@ -0,0 +1,117 @@
|
|||
#include "u.h"
|
||||
#include "ureg.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
|
||||
extern uchar *periph;
|
||||
ulong *global, *local;
|
||||
enum { PERIPHCLK = 506965000 } ;
|
||||
|
||||
void
|
||||
globalclockinit(void)
|
||||
{
|
||||
global = (ulong*) (periph + 0x200);
|
||||
local = (ulong*) (periph + 0x600);
|
||||
global[2] &= 0xFFFF00F0;
|
||||
global[0] = 0;
|
||||
global[1] = 0;
|
||||
global[2] |= 1;
|
||||
}
|
||||
|
||||
void
|
||||
cycles(uvlong *x)
|
||||
{
|
||||
ulong hi, newhi, lo, *y;
|
||||
|
||||
newhi = global[1];
|
||||
do{
|
||||
hi = newhi;
|
||||
lo = global[0];
|
||||
}while((newhi = global[1]) != hi);
|
||||
y = (ulong *) x;
|
||||
y[0] = lo;
|
||||
y[1] = hi;
|
||||
}
|
||||
|
||||
uvlong
|
||||
fastticks(uvlong *hz)
|
||||
{
|
||||
uvlong ret;
|
||||
|
||||
if(hz != nil)
|
||||
*hz = PERIPHCLK;
|
||||
cycles(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ulong
|
||||
µs(void)
|
||||
{
|
||||
return fastticks2us(fastticks(nil));
|
||||
}
|
||||
|
||||
|
||||
ulong
|
||||
perfticks(void)
|
||||
{
|
||||
return global[0];
|
||||
}
|
||||
|
||||
void
|
||||
clocktick(Ureg* ureg)
|
||||
{
|
||||
extern void _dumpstack(ulong, ulong);
|
||||
static int n;
|
||||
|
||||
// if(++n % 128 == 0 && up && up->pid == 1)
|
||||
// _dumpstack(ureg->sp, ureg->pc);
|
||||
timerintr(ureg, 0);
|
||||
}
|
||||
|
||||
void
|
||||
localclockinit(void)
|
||||
{
|
||||
local[2] = 0xFF07;
|
||||
intenable(29, clocktick);
|
||||
}
|
||||
|
||||
void
|
||||
timerset(uvlong val)
|
||||
{
|
||||
uvlong now, ticks;
|
||||
|
||||
cycles(&now);
|
||||
ticks = (val - now) * (PERIPHCLK / 256) / 1000000000;
|
||||
if(ticks == 0)
|
||||
ticks++;
|
||||
local[2] &= ~1;
|
||||
local[0] = local[1] = ticks;
|
||||
local[2] |= 1;
|
||||
}
|
||||
|
||||
static void
|
||||
waituntil(uvlong n)
|
||||
{
|
||||
uvlong now, then;
|
||||
|
||||
cycles(&now);
|
||||
then = now + n;
|
||||
while(now < then)
|
||||
cycles(&now);
|
||||
}
|
||||
|
||||
void
|
||||
microdelay(int n)
|
||||
{
|
||||
waituntil(((uvlong)n) * PERIPHCLK / 1000000);
|
||||
}
|
||||
|
||||
void
|
||||
delay(int n)
|
||||
{
|
||||
waituntil(((uvlong)n) * PERIPHCLK / 1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
typedef struct Lock Lock;
|
||||
typedef struct Label Label;
|
||||
typedef struct Ureg Ureg;
|
||||
typedef struct Mach Mach;
|
||||
typedef struct FPsave FPsave;
|
||||
typedef struct Notsave Notsave;
|
||||
typedef struct PMMU PMMU;
|
||||
typedef struct Confmem Confmem;
|
||||
typedef struct Conf Conf;
|
||||
typedef struct Proc Proc;
|
||||
typedef uvlong Tval;
|
||||
typedef void KMap;
|
||||
#define VA(k) ((uintptr)(k))
|
||||
#define kmap(p) (KMap*)((p)->pa|kseg0)
|
||||
#define kunmap(k)
|
||||
|
||||
#pragma incomplete Ureg
|
||||
|
||||
struct Lock
|
||||
{
|
||||
ulong key;
|
||||
u32int sr;
|
||||
uintptr pc;
|
||||
Proc* p;
|
||||
Mach* m;
|
||||
int isilock;
|
||||
};
|
||||
|
||||
struct Label
|
||||
{
|
||||
ulong sp;
|
||||
ulong pc;
|
||||
};
|
||||
|
||||
struct FPsave
|
||||
{
|
||||
ulong status;
|
||||
ulong control;
|
||||
ulong regs[8][3];
|
||||
int fpstate;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FPinit,
|
||||
FPactive,
|
||||
FPinactive,
|
||||
};
|
||||
|
||||
struct Notsave
|
||||
{
|
||||
int emptiness;
|
||||
};
|
||||
|
||||
struct PMMU
|
||||
{
|
||||
ulong l1[USTKTOP / MiB];
|
||||
};
|
||||
|
||||
#include "../port/portdat.h"
|
||||
|
||||
struct Mach
|
||||
{
|
||||
int machno; /* physical id of processor */
|
||||
uintptr splpc; /* pc of last caller to splhi */
|
||||
|
||||
Proc* proc; /* current process */
|
||||
Proc* externup;
|
||||
|
||||
int flushmmu; /* flush current proc mmu state */
|
||||
|
||||
ulong ticks; /* of the clock since boot time */
|
||||
Label sched; /* scheduler wakeup */
|
||||
Lock alarmlock; /* access to alarm list */
|
||||
void* alarm; /* alarms bound to this clock */
|
||||
int inclockintr;
|
||||
|
||||
Proc* readied; /* for runproc */
|
||||
ulong schedticks; /* next forced context switch */
|
||||
|
||||
int cputype;
|
||||
ulong delayloop;
|
||||
|
||||
/* stats */
|
||||
int tlbfault;
|
||||
int tlbpurge;
|
||||
int pfault;
|
||||
int cs;
|
||||
int syscall;
|
||||
int load;
|
||||
int intr;
|
||||
uvlong fastclock; /* last sampled value */
|
||||
uvlong inidle; /* time spent in idlehands() */
|
||||
ulong spuriousintr;
|
||||
int lastintr;
|
||||
int ilockdepth;
|
||||
Perf perf;
|
||||
uvlong cyclefreq; /* Frequency of user readable cycle counter */
|
||||
|
||||
};
|
||||
|
||||
struct Confmem
|
||||
{
|
||||
uintptr base;
|
||||
usize npage;
|
||||
uintptr limit;
|
||||
uintptr kbase;
|
||||
uintptr klimit;
|
||||
};
|
||||
|
||||
struct Conf
|
||||
{
|
||||
ulong nmach; /* processors */
|
||||
ulong nproc; /* processes */
|
||||
Confmem mem[1]; /* physical memory */
|
||||
ulong npage; /* total physical pages of memory */
|
||||
usize upages; /* user page pool */
|
||||
ulong copymode; /* 0 is copy on write, 1 is copy on reference */
|
||||
ulong ialloc; /* max interrupt time allocation in bytes */
|
||||
ulong pipeqsize; /* size in bytes of pipe queues */
|
||||
ulong nimage; /* number of page cache image headers */
|
||||
ulong nswap; /* number of swap pages */
|
||||
int nswppo; /* max # of pageouts per segment pass */
|
||||
ulong hz; /* processor cycle freq */
|
||||
ulong mhz;
|
||||
int monitor; /* flag */
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
Lock;
|
||||
int machs; /* bitmap of active CPUs */
|
||||
int exiting; /* shutdown */
|
||||
int ispanic; /* shutdown in response to a panic */
|
||||
}active;
|
||||
|
||||
extern Mach *m;
|
||||
#define up (((Mach*)MACHADDR)->externup)
|
||||
extern Mach* machaddr[MAXMACH];
|
||||
#define MACHP(n) (machaddr[n])
|
||||
extern uintptr kseg0;
|
||||
|
||||
#define AOUT_MAGIC (E_MAGIC)
|
||||
#define NCOLOR 1
|
|
@ -0,0 +1,34 @@
|
|||
#include "../port/portfns.h"
|
||||
|
||||
#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
|
||||
#define getpgcolor(x) 0
|
||||
#define kmapinval()
|
||||
#define checkmmu(a,b)
|
||||
|
||||
extern void procsave(Proc *);
|
||||
extern void procrestore(Proc *);
|
||||
extern void idlehands(void);
|
||||
extern void coherence(void);
|
||||
extern int tas(void*);
|
||||
extern int cmpswap(long*, long, long);
|
||||
extern void evenaddr(uintptr);
|
||||
extern void procsetup(Proc*);
|
||||
extern void procfork(Proc*);
|
||||
extern uintptr cankaddr(uintptr);
|
||||
extern void* KADDR(ulong);
|
||||
extern ulong paddr(void *);
|
||||
extern void cycles(uvlong *);
|
||||
#define PADDR(x) paddr((void*)(x))
|
||||
|
||||
void mmuinit(void);
|
||||
void flushtlb(void);
|
||||
void trapinit(void);
|
||||
void* vmap(ulong, ulong);
|
||||
void vunmap(void*, ulong);
|
||||
void printureg(Ureg*);
|
||||
void fillureguser(Ureg*);
|
||||
void touser(Ureg*);
|
||||
void links(void);
|
||||
void globalclockinit(void);
|
||||
void localclockinit(void);
|
||||
void intenable(int, void(*)(Ureg*));
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* This is the same as the C programme:
|
||||
*
|
||||
* void
|
||||
* main(char* argv0)
|
||||
* {
|
||||
* startboot(argv0, &argv0);
|
||||
* }
|
||||
*
|
||||
* It is in assembler because SB needs to be
|
||||
* set and doing this in C drags in too many
|
||||
* other routines.
|
||||
*/
|
||||
TEXT main(SB), 1, $8
|
||||
MOVW $setR12(SB), R12 /* load the SB */
|
||||
MOVW $boot(SB), R0
|
||||
|
||||
ADD $12, R13, R1 /* pointer to 0(FP) */
|
||||
|
||||
MOVW R0, 4(R13) /* pass argc, argv */
|
||||
MOVW R1, 8(R13)
|
||||
|
||||
BL startboot(SB)
|
||||
_loop:
|
||||
B _loop
|
|
@ -0,0 +1,298 @@
|
|||
#include "arm.s"
|
||||
#include "mem.h"
|
||||
|
||||
TEXT _start(SB), 1, $-4
|
||||
MOVW $setR12(SB), R12
|
||||
ADD $(PHYSDRAM - KZERO), R12
|
||||
|
||||
MOVW $(PsrDirq | PsrDfiq | PsrMsvc), CPSR
|
||||
|
||||
MOVW $0x48020014, R1
|
||||
uartloop:
|
||||
MOVW (R1), R0
|
||||
AND.S $(1<<6), R0
|
||||
B.EQ uartloop
|
||||
|
||||
EWAVE('\r')
|
||||
EWAVE('\n')
|
||||
|
||||
MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
|
||||
BIC $(CpCmmu), R1
|
||||
MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
|
||||
|
||||
EWAVE('P')
|
||||
|
||||
MOVW $KZERO, R1
|
||||
MOVW $(PHYSDRAM|PTEDRAM), R2
|
||||
MOVW $256, R3
|
||||
BL _mapmbs(SB)
|
||||
MOVW $PHYSDRAM, R1
|
||||
MOVW $(PHYSDRAM|PTEDRAM), R2
|
||||
MOVW $256, R3
|
||||
BL _mapmbs(SB)
|
||||
MOVW $0x48000000, R1
|
||||
MOVW $(0x48000000| L1AP(Krw) | Section | PTEIO), R2
|
||||
MOVW $1, R3
|
||||
BL _mapmbs(SB)
|
||||
|
||||
EWAVE('l')
|
||||
|
||||
MOVW $L1PT, R1
|
||||
MCR CpSC, 0, R1, C(CpTTB), C(0), CpTTB0
|
||||
MCR CpSC, 0, R1, C(CpTTB), C(0), CpTTB1
|
||||
|
||||
EWAVE('a')
|
||||
|
||||
MOVW $Client, R1
|
||||
MCR CpSC, 0, R1, C(CpDAC), C(0)
|
||||
MOVW $0, R1
|
||||
MCR CpSC, 0, R1, C(CpPID), C(0x0)
|
||||
|
||||
EWAVE('n')
|
||||
|
||||
MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
|
||||
ORR $(CpCmmu|CpChv|CpCsw), R1
|
||||
MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
|
||||
|
||||
EWAVE(' ')
|
||||
|
||||
BL _jumphi(SB)
|
||||
|
||||
EWAVE('9')
|
||||
|
||||
MOVW $setR12(SB), R12
|
||||
MOVW $KTZERO, R13
|
||||
|
||||
EWAVE(' ')
|
||||
|
||||
BL main(SB)
|
||||
a:
|
||||
WFI
|
||||
B a
|
||||
BL _div(SB) /* hack */
|
||||
|
||||
/* R1: virtual start, R2: physical start, R3: number of MB */
|
||||
TEXT _mapmbs(SB), 1, $-4
|
||||
MOVW $L1PT, R11
|
||||
ADD R1>>18, R11, R1
|
||||
mapmbsl:
|
||||
MOVW.P R2, 4(R1)
|
||||
ADD $MiB, R2
|
||||
SUB.S $1, R3
|
||||
B.NE mapmbsl
|
||||
MOVW R14, PC
|
||||
|
||||
TEXT _jumphi(SB), 1, $-4
|
||||
ADD $(KZERO - PHYSDRAM), R14
|
||||
MOVW R14, PC
|
||||
|
||||
TEXT coherence(SB), 1, $-4
|
||||
BARRIERS
|
||||
RET
|
||||
|
||||
TEXT splhi(SB), 1, $-4
|
||||
MOVW CPSR, R0
|
||||
CPSID
|
||||
MOVW $(MACHADDR + 4), R11
|
||||
MOVW R14, (R11)
|
||||
RET
|
||||
|
||||
TEXT spllo(SB), 1, $-4
|
||||
MOVW CPSR, R0
|
||||
CPSIE
|
||||
RET
|
||||
|
||||
TEXT splx(SB), 1, $-4
|
||||
MOVW CPSR, R1
|
||||
MOVW R0, CPSR
|
||||
MOVW R1, R0
|
||||
RET
|
||||
|
||||
TEXT islo(SB), 1, $-4
|
||||
MOVW CPSR, R0
|
||||
AND $PsrDirq, R0
|
||||
EOR $PsrDirq, R0
|
||||
RET
|
||||
|
||||
TEXT tas(SB), $-4
|
||||
spintas:
|
||||
LDREX(0,1)
|
||||
CMP.S $0, R1
|
||||
B.NE tasnope
|
||||
MOVW $1, R3
|
||||
STREX(0,3,2)
|
||||
CMP.S $0, R2
|
||||
B.NE spintas
|
||||
tasnope:
|
||||
CLREX
|
||||
MOVW R1, R0
|
||||
RET
|
||||
|
||||
TEXT cmpswap(SB), $-4
|
||||
MOVW 4(FP), R3
|
||||
MOVW 8(FP), R4
|
||||
casspin:
|
||||
LDREX(0,1)
|
||||
CMP.S R3, R1
|
||||
B.NE casfail
|
||||
STREX(0,1,2)
|
||||
CMP.S $0, R2
|
||||
B.NE casspin
|
||||
MOVW $1, R0
|
||||
RET
|
||||
casfail:
|
||||
CLREX
|
||||
MOVW $0, R0
|
||||
RET
|
||||
|
||||
TEXT ainc(SB), $-4
|
||||
TEXT _xinc(SB), $-4
|
||||
spinainc:
|
||||
LDREX(0,1)
|
||||
ADD $1, R1
|
||||
STREX(0,1,2)
|
||||
CMP.S $0, R2
|
||||
B.NE spinainc
|
||||
MOVW R1, R0
|
||||
RET
|
||||
|
||||
TEXT adec(SB), $-4
|
||||
TEXT _xdec(SB), $-4
|
||||
spinadec:
|
||||
LDREX(0,1)
|
||||
SUB $1, R1
|
||||
STREX(0,1,2)
|
||||
CMP.S $0, R2
|
||||
B.NE spinadec
|
||||
MOVW R1, R0
|
||||
RET
|
||||
|
||||
TEXT setlabel(SB), 1, $-4
|
||||
MOVW R13, 0(R0)
|
||||
MOVW R14, 4(R0)
|
||||
MOVW $0, R0
|
||||
RET
|
||||
|
||||
TEXT gotolabel(SB), 1, $-4
|
||||
MOVW 0(R0), R13
|
||||
MOVW 4(R0), R14
|
||||
MOVW $1, R0
|
||||
RET
|
||||
|
||||
TEXT idlehands(SB), 1, $-4
|
||||
BARRIERS
|
||||
WFI
|
||||
RET
|
||||
|
||||
TEXT flushtlb(SB), $-4
|
||||
BARRIERS
|
||||
MCR CpSC, 0, R1, C(8), C(7), 0
|
||||
RET
|
||||
|
||||
#define TRAP(n,a)\
|
||||
SUB $n, R14;\
|
||||
WORD $0xf96d0513;\
|
||||
WORD $0xf10e0093;\
|
||||
MOVW R14, -8(R13);\
|
||||
MOVW $a, R14;\
|
||||
MOVW R14, -4(R13);\
|
||||
B _trap(SB)
|
||||
|
||||
TEXT _reset(SB), 1, $-4
|
||||
TRAP(4, 0)
|
||||
TEXT _undefined(SB), 1, $-4
|
||||
TRAP(4, 1)
|
||||
TEXT _prefabort(SB), 1, $-4
|
||||
TRAP(4, 3)
|
||||
TEXT _dataabort(SB), 1, $-4
|
||||
TRAP(8, 4)
|
||||
TEXT _wtftrap(SB), 1, $-4
|
||||
TRAP(4, 5)
|
||||
TEXT _irq(SB), 1, $-4
|
||||
TRAP(4, 6)
|
||||
TEXT _fiq(SB), 1, $-4
|
||||
TRAP(4, 7)
|
||||
|
||||
TEXT _trap(SB), 1, $-4
|
||||
SUB $64, R13
|
||||
MOVM.IA [R0-R12], (R13)
|
||||
MOVW $setR12(SB), R12
|
||||
MOVW 64(R13), R0
|
||||
MOVW 68(R13), R1
|
||||
MOVW R0, 68(R13)
|
||||
MOVW R1, 64(R13)
|
||||
ADD $72, R13, R0
|
||||
MOVW R0, 52(R13)
|
||||
MOVW R13, R0
|
||||
SUB $8, R13
|
||||
BL trap(SB)
|
||||
ADD $8, R13
|
||||
MOVW 64(R13), R0
|
||||
AND $PsrMask, R0
|
||||
CMP $PsrMusr, R0
|
||||
MOVW.EQ R13, R0
|
||||
B.EQ gotouser
|
||||
MOVW 68(R13), R0
|
||||
MOVW R0, 60(R13)
|
||||
MOVW 64(R13), R0
|
||||
MOVW R0, SPSR
|
||||
MOVW R13, R0
|
||||
ADD $72, R13
|
||||
WORD $0xE8D0FFFF
|
||||
|
||||
TEXT _syscall(SB), 1, $-4
|
||||
WORD $0xf96d0513
|
||||
WORD $0xf10e0093
|
||||
SUB $64, R13
|
||||
MOVM.IA.S [R0-R14], (R13)
|
||||
MOVW $setR12(SB), R12
|
||||
MOVW 64(R13), R0
|
||||
MOVW 68(R13), R1
|
||||
MOVW R0, 68(R13)
|
||||
MOVW R1, 64(R13)
|
||||
MOVW R13, R0
|
||||
SUB $8, R13
|
||||
BL syscall(SB)
|
||||
|
||||
TEXT forkret(SB), 1, $-4
|
||||
ADD $8, R13
|
||||
MOVW R13, R0
|
||||
|
||||
TEXT touser(SB), 1, $-4
|
||||
gotouser:
|
||||
ADD $52, R0
|
||||
MOVM.IA.S (R0), [R13-R14]
|
||||
SUB $52, R0
|
||||
MOVW 68(R0), R1
|
||||
MOVW R1, 52(R0)
|
||||
MOVW 64(R0), R1
|
||||
MOVW R1, SPSR
|
||||
WORD $0xE8D09FFF
|
||||
|
||||
TEXT fillureguser(SB), $-4
|
||||
ADD $52, R0
|
||||
MOVM.IA.S [R13-R14], (R0)
|
||||
RET
|
||||
|
||||
|
||||
TEXT dumpstack(SB), 0, $8
|
||||
MOVW R14, 8(R13)
|
||||
ADD $12, R13, R0
|
||||
BL _dumpstack(SB)
|
||||
RET
|
||||
|
||||
TEXT getdfsr(SB), 0, $-4
|
||||
MRC CpSC, 0, R0, C(5), C(0), 0
|
||||
RET
|
||||
|
||||
TEXT getifsr(SB), 0, $-4
|
||||
MRC CpSC, 0, R0, C(5), C(0), 1
|
||||
RET
|
||||
|
||||
TEXT getdfar(SB), 0, $-4
|
||||
MRC CpSC, 0, R0, C(6), C(0), 0
|
||||
RET
|
||||
|
||||
TEXT getifar(SB), 0, $-4
|
||||
MRC CpSC, 0, R0, C(6), C(0), 2
|
||||
RET
|
|
@ -0,0 +1,194 @@
|
|||
#include "u.h"
|
||||
#include "ureg.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "init.h"
|
||||
#include "tos.h"
|
||||
#include "arm.h"
|
||||
|
||||
ulong *uart = (ulong *) 0x48020000;
|
||||
#define wave(x) (*uart = (char) (x))
|
||||
uintptr kseg0 = KZERO;
|
||||
uchar *sp;
|
||||
|
||||
Mach *m;
|
||||
Mach *machaddr[MAXMACH];
|
||||
Conf conf;
|
||||
|
||||
void
|
||||
machinit(void)
|
||||
{
|
||||
machaddr[0] = m = KADDR(FIRSTMACH);
|
||||
memset(m, 0, sizeof(Mach));
|
||||
active.machs = conf.nmach = 1;
|
||||
active.exiting = 0;
|
||||
up = nil;
|
||||
|
||||
conf.mem[0].base = ROUNDUP(PADDR(end), BY2PG);
|
||||
conf.mem[0].limit = ROUNDDN(PHYSDRAM + DRAMSIZ, BY2PG);
|
||||
conf.mem[0].npage = (conf.mem[0].limit - conf.mem[0].base) / BY2PG;
|
||||
conf.npage = conf.mem[0].npage;
|
||||
conf.upages = conf.npage - 64 * MiB / BY2PG;
|
||||
conf.nproc = 100;
|
||||
conf.pipeqsize = 32768;
|
||||
conf.nimage = 200;
|
||||
}
|
||||
|
||||
void
|
||||
init0(void)
|
||||
{
|
||||
Ureg ureg;
|
||||
|
||||
spllo();
|
||||
up->nerrlab = 0;
|
||||
up->slash = namec("#/", Atodir, 0, 0);
|
||||
pathclose(up->slash->path);
|
||||
up->slash->path = newpath("/");
|
||||
up->dot = cclone(up->slash);
|
||||
chandevinit();
|
||||
if(!waserror()){
|
||||
ksetenv("terminal", "generic /sys/src/9/omap4/panda", 0);
|
||||
ksetenv("cputype", "arm", 0);
|
||||
ksetenv("service", "cpu", 0);
|
||||
poperror();
|
||||
}
|
||||
kproc("alarm", alarmkproc, 0);
|
||||
memset(&ureg, 0, sizeof ureg);
|
||||
ureg.pc = UTZERO + 32;
|
||||
ureg.r13 = (ulong) sp;
|
||||
ureg.psr = PsrMusr;
|
||||
touser(&ureg);
|
||||
}
|
||||
|
||||
static uchar *
|
||||
pusharg(char *p)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = strlen(p) + 1;
|
||||
sp -= n;
|
||||
memmove(sp, p, n);
|
||||
return sp;
|
||||
}
|
||||
|
||||
static void
|
||||
bootargs(void *base)
|
||||
{
|
||||
int ac, i;
|
||||
uchar *av[32], **lsp;
|
||||
sp = (uchar*)base + BY2PG - sizeof(Tos);
|
||||
|
||||
ac = 0;
|
||||
av[ac++] = pusharg("boot");
|
||||
sp = (uchar *) ROUNDDN((ulong)sp, 4);
|
||||
sp -= (ac + 1) * 4;
|
||||
lsp = (uchar **) sp;
|
||||
for(i = 0; i < ac; i++)
|
||||
lsp[i] = av[i] + ((USTKTOP - BY2PG) - (ulong) base);
|
||||
lsp[i] = 0;
|
||||
sp += (USTKTOP - BY2PG) - (ulong)base;
|
||||
sp -= BY2WD;
|
||||
}
|
||||
|
||||
void
|
||||
userinit(void)
|
||||
{
|
||||
Proc *p;
|
||||
Segment *s;
|
||||
Page *pg;
|
||||
void *v;
|
||||
|
||||
p = newproc();
|
||||
p->pgrp = newpgrp();
|
||||
p->egrp = smalloc(sizeof(Egrp));
|
||||
p->egrp->ref = 1;
|
||||
p->fgrp = dupfgrp(nil);
|
||||
p->rgrp = newrgrp();
|
||||
p->procmode = 0640;
|
||||
|
||||
kstrdup(&eve, "");
|
||||
kstrdup(&p->text, "*init*");
|
||||
kstrdup(&p->user, eve);
|
||||
|
||||
procsetup(p);
|
||||
|
||||
p->sched.pc = (ulong)init0;
|
||||
p->sched.sp = (ulong)p->kstack + KSTACK - sizeof(Sargs) - BY2WD;
|
||||
|
||||
s = newseg(SG_STACK, USTKTOP - USTKSIZE, USTKSIZE / BY2PG);
|
||||
p->seg[SSEG] = s;
|
||||
pg = newpage(0, 0, USTKTOP - BY2PG);
|
||||
v = vmap(pg->pa, BY2PG);
|
||||
memset(v, 0, BY2PG);
|
||||
segpage(s, pg);
|
||||
bootargs(v);
|
||||
vunmap(v, BY2PG);
|
||||
|
||||
s = newseg(SG_TEXT, UTZERO, 1);
|
||||
s->flushme++;
|
||||
p->seg[TSEG] = s;
|
||||
pg = newpage(0, 0, UTZERO);
|
||||
memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
|
||||
segpage(s, pg);
|
||||
v = vmap(pg->pa, BY2PG);
|
||||
memset(v, 0, BY2PG);
|
||||
memmove(v, initcode, sizeof initcode);
|
||||
vunmap(v, BY2PG);
|
||||
|
||||
ready(p);
|
||||
}
|
||||
|
||||
void
|
||||
main()
|
||||
{
|
||||
extern int chandebug;
|
||||
|
||||
wave('f');
|
||||
memset(edata, 0, end - edata);
|
||||
wave('r');
|
||||
machinit();
|
||||
wave('o');
|
||||
mmuinit();
|
||||
wave('m');
|
||||
trapinit();
|
||||
print(" Bell Labs\n");
|
||||
xinit();
|
||||
globalclockinit();
|
||||
localclockinit();
|
||||
timersinit();
|
||||
procinit0();
|
||||
pageinit();
|
||||
swapinit();
|
||||
initseg();
|
||||
quotefmtinstall();
|
||||
chandevreset();
|
||||
links();
|
||||
chandebug++;
|
||||
userinit();
|
||||
schedinit();
|
||||
}
|
||||
|
||||
void
|
||||
exit(int)
|
||||
{
|
||||
uartputs("resting\n", 9);
|
||||
splhi();
|
||||
while(1)
|
||||
idlehands();
|
||||
}
|
||||
|
||||
void
|
||||
reboot()
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
rdb()
|
||||
{
|
||||
panic("rdb");
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#define KiB 1024u /* Kibi 0x0000000000000400 */
|
||||
#define MiB 1048576u /* Mebi 0x0000000000100000 */
|
||||
#define GiB 1073741824u /* Gibi 000000000040000000 */
|
||||
|
||||
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
|
||||
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) /* ceiling */
|
||||
#define ROUNDDN(x, y) (((x)/(y))*(y)) /* floor */
|
||||
#define MIN(a, b) ((a) < (b)? (a): (b))
|
||||
#define MAX(a, b) ((a) > (b)? (a): (b))
|
||||
#define PGROUND(s) ROUNDUP(s, BY2PG)
|
||||
#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
|
||||
#define PPN(x) ((x)&~(BY2PG-1))
|
||||
#define F(v, o, w) (((v) & ((1<<(w))-1))<<(o))
|
||||
|
||||
#define FMASK(o, w) (((1<<(w))-1)<<(o))
|
||||
|
||||
#define KZERO 0xF0000000
|
||||
#define KTZERO 0xF2000000
|
||||
#define VECTORS 0xFFFF0000
|
||||
#define MACHADDR 0xFFFF1000
|
||||
|
||||
#define UZERO 0
|
||||
#define UTZERO BY2PG
|
||||
#define USTKTOP 0xE0000000
|
||||
|
||||
/* we map MMIO somewhere here */
|
||||
#define IZERO 0xE0000000
|
||||
#define NIOPAGES ROUNDDN((KZERO - IZERO) / BY2PG, 256)
|
||||
|
||||
#define KSTKSIZ (16*KiB)
|
||||
#define KSTACK KSTKSIZ
|
||||
#define TSTKSIZ 256
|
||||
#define USTKSIZE (8*MiB)
|
||||
#define TSTKTOP (USTKTOP - USTKSIZE)
|
||||
#define HZ 100
|
||||
|
||||
#define MAXSYSARG 7
|
||||
#define MAXMACH 2
|
||||
|
||||
#define BY2WD 4
|
||||
#define BY2V 8
|
||||
#define BY2PG 4096
|
||||
#define PGSHIFT 12
|
||||
#define PTEMAPMEM 1048576
|
||||
#define PTEPERTAB (PTEMAPMEM/BY2PG)
|
||||
#define SEGMAPSIZE 1984
|
||||
#define SSEGMAPSIZE 16
|
||||
#define BLOCKALIGN 32
|
||||
|
||||
#define PTEVALID (1<<0)
|
||||
#define PTERONLY 0
|
||||
#define PTEWRITE (1<<1)
|
||||
#define PTEUNCACHED (1<<2)
|
||||
#define PTEKERNEL (1<<3)
|
||||
|
||||
#define PHYSDRAM 0x80000000
|
||||
#define DRAMSIZ (1024 * MiB)
|
||||
|
||||
#define L1PT PHYSDRAM
|
||||
#define L1SIZ (16 * KiB)
|
||||
#define IOPT (L1PT + L1SIZ)
|
||||
#define L2SIZ (1 * KiB)
|
||||
#define PRIVL2 (IOPT + L2SIZ * (NIOPAGES / 256))
|
||||
#define PHYSVECTORS ROUNDUP(PRIVL2 + L2SIZ, BY2PG)
|
||||
#define FIRSTMACH (PHYSVECTORS + BY2PG)
|
|
@ -0,0 +1,101 @@
|
|||
CONF=panda
|
||||
CONFLIST=panda
|
||||
|
||||
loadaddr=0xF2000000
|
||||
|
||||
objtype=arm
|
||||
</$objtype/mkfile
|
||||
p=9
|
||||
|
||||
DEVS=`{rc ../port/mkdevlist $CONF}
|
||||
|
||||
PORT=\
|
||||
alarm.$O\
|
||||
alloc.$O\
|
||||
allocb.$O\
|
||||
auth.$O\
|
||||
cache.$O\
|
||||
chan.$O\
|
||||
dev.$O\
|
||||
edf.$O\
|
||||
fault.$O\
|
||||
mul64fract.$O\
|
||||
rebootcmd.$O\
|
||||
page.$O\
|
||||
parse.$O\
|
||||
pgrp.$O\
|
||||
portclock.$O\
|
||||
print.$O\
|
||||
proc.$O\
|
||||
qio.$O\
|
||||
qlock.$O\
|
||||
segment.$O\
|
||||
swap.$O\
|
||||
sysfile.$O\
|
||||
sysproc.$O\
|
||||
taslock.$O\
|
||||
tod.$O\
|
||||
xalloc.$O\
|
||||
|
||||
OBJ=\
|
||||
l.$O\
|
||||
main.$O\
|
||||
mmu.$O\
|
||||
random.$O\
|
||||
clock.$O\
|
||||
arch.$O\
|
||||
uart.$O\
|
||||
trap.$O\
|
||||
$CONF.root.$O\
|
||||
$CONF.rootc.$O\
|
||||
$DEVS\
|
||||
$PORT\
|
||||
|
||||
LIB=\
|
||||
/$objtype/lib/libmemlayer.a\
|
||||
/$objtype/lib/libmemdraw.a\
|
||||
/$objtype/lib/libdraw.a\
|
||||
/$objtype/lib/libip.a\
|
||||
/$objtype/lib/libsec.a\
|
||||
/$objtype/lib/libmp.a\
|
||||
/$objtype/lib/libc.a\
|
||||
|
||||
9:V: $p$CONF s$p$CONF
|
||||
|
||||
$p$CONF:DQ: $CONF.c $OBJ $LIB mkfile
|
||||
$CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
|
||||
echo '# linking raw kernel'
|
||||
$LD -o $target -H0 -P -R4096 -T$loadaddr -l $OBJ $CONF.$O $LIB
|
||||
|
||||
s$p$CONF:DQ: $CONF.$O $OBJ $LIB
|
||||
echo '# linking kernel with symbols'
|
||||
# $LD -o $target -R4096 -T$loadaddr -l -a $OBJ $CONF.$O $LIB >$target.list
|
||||
$LD -o $target -R4096 -T$loadaddr -l $OBJ $CONF.$O $LIB
|
||||
size $target
|
||||
|
||||
$p$CONF.gz:D: $p$CONF
|
||||
gzip -9 <$p$CONF >$target
|
||||
|
||||
$OBJ: $HFILES
|
||||
|
||||
l.$O: arm.s
|
||||
|
||||
install:V: /$objtype/$p$CONF
|
||||
|
||||
/$objtype/$p$CONF:D: $p$CONF s$p$CONF
|
||||
cp $p$CONF s$p$CONF /$objtype
|
||||
|
||||
<../boot/bootmkfile
|
||||
<../port/portmkfile
|
||||
<|../port/mkbootrules $CONF
|
||||
|
||||
CFLAGS= -I. -I../port $CFLAGS # hack to compile private sysproc.c (e.g.)
|
||||
|
||||
init.h:D: ../port/initcode.c init9.s
|
||||
$CC ../port/initcode.c
|
||||
$AS init9.s
|
||||
$LD -l -R1 -s -o init.out init9.$O initcode.$O /$objtype/lib/libc.a
|
||||
{echo 'uchar initcode[]={'
|
||||
xd -1x <init.out |
|
||||
sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
|
||||
echo '};'} > init.h
|
|
@ -0,0 +1,237 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "arm.h"
|
||||
|
||||
char iopages[NIOPAGES / 8];
|
||||
Lock iopagelock;
|
||||
uchar *periph;
|
||||
|
||||
static int
|
||||
isfree(int i)
|
||||
{
|
||||
return (iopages[i / 8] & (1 << (i % 8))) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
freeio(int i)
|
||||
{
|
||||
iopages[i / 8] &= ~(1 << (i % 8));
|
||||
}
|
||||
|
||||
static int
|
||||
getiopages(int n)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
lock(&iopagelock);
|
||||
for(i = 0; i <= NIOPAGES - n; i++){
|
||||
for(j = 0; j < n; j++)
|
||||
if(!isfree(i + j))
|
||||
goto next;
|
||||
for(j = 0; j < n; j++)
|
||||
iopages[(i + j) / 8] |= (1 << ((i + j) % 8));
|
||||
unlock(&iopagelock);
|
||||
return i;
|
||||
next: ;
|
||||
}
|
||||
panic("out of i/o pages");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
putiopages(int i, int n)
|
||||
{
|
||||
lock(&iopagelock);
|
||||
while(n--)
|
||||
freeio(i++);
|
||||
unlock(&iopagelock);
|
||||
}
|
||||
|
||||
void *
|
||||
vmap(ulong phys, ulong length)
|
||||
{
|
||||
ulong virt, off, *l2;
|
||||
|
||||
off = phys % BY2PG;
|
||||
length = (ROUNDUP(phys + length, BY2PG) - ROUNDDN(phys, BY2PG)) / BY2PG;
|
||||
if(length == 0)
|
||||
return nil;
|
||||
phys = ROUNDDN(phys, BY2PG);
|
||||
virt = getiopages(length);
|
||||
l2 = KADDR(IOPT);
|
||||
l2 += virt;
|
||||
while(length--){
|
||||
*l2++ = phys | L2AP(Krw) | Small | PTEIO;
|
||||
phys += BY2PG;
|
||||
}
|
||||
flushtlb();
|
||||
return (void *) (IZERO + BY2PG * virt + off);
|
||||
}
|
||||
|
||||
void
|
||||
vunmap(void *virt, ulong length)
|
||||
{
|
||||
ulong v, *l2;
|
||||
|
||||
if((ulong)virt < IZERO || (ulong)virt >= IZERO + NIOPAGES * BY2PG)
|
||||
panic("vunmap: virt=%p", virt);
|
||||
v = (ROUNDDN((ulong) virt, BY2PG) - IZERO) / BY2PG;
|
||||
length = (ROUNDUP(((ulong) virt) + length, BY2PG) - ROUNDDN((ulong) virt, BY2PG)) / BY2PG;
|
||||
if(length == 0)
|
||||
return;
|
||||
l2 = KADDR(IOPT);
|
||||
l2 += v;
|
||||
lock(&iopagelock);
|
||||
while(length--){
|
||||
*l2++ = 0;
|
||||
freeio(v++);
|
||||
}
|
||||
unlock(&iopagelock);
|
||||
flushtlb();
|
||||
}
|
||||
|
||||
void
|
||||
mmuinit(void)
|
||||
{
|
||||
ulong *l1, l2, *pl2;
|
||||
int i, n;
|
||||
extern ulong *uart;
|
||||
|
||||
l1 = KADDR(L1PT);
|
||||
l2 = IOPT;
|
||||
n = NIOPAGES / 256;
|
||||
memset(KADDR(l2), 0, n * L2SIZ);
|
||||
for(i = 0; i < n; i++){
|
||||
l1[(IZERO / MiB) + i] = l2 | Coarse;
|
||||
l2 += L2SIZ;
|
||||
}
|
||||
uart = vmap((ulong) uart, BY2PG);
|
||||
memset(l1, 0, sizeof(ulong) * (IZERO / MiB));
|
||||
l1[4095] = PRIVL2 | Coarse;
|
||||
pl2 = KADDR(PRIVL2);
|
||||
for(i = 0; i < 240; i++)
|
||||
pl2[i] = (0x8FF00000 + i * BY2PG) | L2AP(Krw) | Small | Cached | Buffered;
|
||||
pl2[240] = PHYSVECTORS | L2AP(Krw) | Small | Cached | Buffered;
|
||||
pl2[241] = FIRSTMACH | L2AP(Krw) | Small | Cached | Buffered;
|
||||
flushtlb();
|
||||
m = (Mach *) MACHADDR;
|
||||
periph = vmap(0x48240000, 2 * BY2PG);
|
||||
}
|
||||
|
||||
void
|
||||
mmuswitch(Proc *p)
|
||||
{
|
||||
ulong *l1;
|
||||
|
||||
l1 = KADDR(L1PT);
|
||||
memmove(l1, p->l1, sizeof p->l1);
|
||||
flushtlb();
|
||||
}
|
||||
|
||||
void
|
||||
putmmu(ulong va, ulong pa, Page *)
|
||||
{
|
||||
ulong *l1a, *l1b, *l2;
|
||||
int l1o, l2o;
|
||||
|
||||
l1o = va / MiB;
|
||||
l2o = (va % MiB) / BY2PG;
|
||||
l1a = KADDR(L1PT);
|
||||
l1b = up->l1;
|
||||
if(l1a[l1o] == 0){
|
||||
if((pa & PTEVALID) == 0)
|
||||
return;
|
||||
l2 = xspanalloc(L2SIZ, L2SIZ, 0);
|
||||
l1a[l1o] = l1b[l1o] = PADDR(l2) | Coarse;
|
||||
} else
|
||||
l2 = KADDR(ROUNDDN(l1a[l1o], L2SIZ));
|
||||
l2 += l2o;
|
||||
if((pa & PTEVALID) == 0){
|
||||
*l2 = 0;
|
||||
flushtlb();
|
||||
return;
|
||||
}
|
||||
*l2 = ROUNDDN(pa, BY2PG) | Small;
|
||||
if((pa & PTEWRITE) == 0)
|
||||
*l2 |= L2AP(Uro);
|
||||
else
|
||||
*l2 |= L2AP(Urw);
|
||||
if((pa & PTEUNCACHED) == 0)
|
||||
*l2 |= Buffered | Cached;
|
||||
flushtlb();
|
||||
}
|
||||
|
||||
void
|
||||
flushmmu(void)
|
||||
{
|
||||
int s, i;
|
||||
ulong p;
|
||||
ulong *l1;
|
||||
|
||||
l1 = KADDR(L1PT);
|
||||
s = splhi();
|
||||
for(i = 0; i < nelem(up->l1); i++){
|
||||
p = l1[i];
|
||||
if(p & Small)
|
||||
free(KADDR(ROUNDDN(p, BY2PG)));
|
||||
}
|
||||
memset(up->l1, 0, sizeof up->l1);
|
||||
memset(l1, 0, sizeof up->l1);
|
||||
flushtlb();
|
||||
splx(s);
|
||||
}
|
||||
|
||||
void
|
||||
mmurelease(Proc *p)
|
||||
{
|
||||
int i;
|
||||
ulong pg;
|
||||
|
||||
if(p == up){
|
||||
flushmmu();
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < nelem(p->l1); i++){
|
||||
pg = p->l1[i];
|
||||
if(pg & Small)
|
||||
free(KADDR(ROUNDDN(pg, BY2PG)));
|
||||
}
|
||||
memset(p->l1, 0, sizeof p->l1);
|
||||
}
|
||||
|
||||
void
|
||||
countpagerefs()
|
||||
{
|
||||
panic("countpagerefs");
|
||||
}
|
||||
|
||||
void*
|
||||
KADDR(ulong pa)
|
||||
{
|
||||
if(pa < (ulong)PHYSDRAM || pa > (ulong)(PHYSDRAM + VECTORS - KZERO))
|
||||
panic("kaddr: pa=%#.8lux, pc=%p", pa, getcallerpc(&pa));
|
||||
return (void*)(pa + KZERO - PHYSDRAM);
|
||||
}
|
||||
|
||||
ulong
|
||||
paddr(void* v)
|
||||
{
|
||||
ulong va;
|
||||
|
||||
va = (ulong) v;
|
||||
if(va < KZERO)
|
||||
panic("paddr: v=%p", v);
|
||||
return va - KZERO + PHYSDRAM;
|
||||
}
|
||||
|
||||
ulong
|
||||
cankaddr(ulong arg)
|
||||
{
|
||||
if(arg < PHYSDRAM || arg > (ulong)(PHYSDRAM + VECTORS - KZERO))
|
||||
return 0;
|
||||
return PHYSDRAM - KZERO - arg;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
# panda board
|
||||
dev
|
||||
root
|
||||
cons
|
||||
env
|
||||
pipe
|
||||
# proc
|
||||
mnt
|
||||
srv
|
||||
shr
|
||||
# dup
|
||||
# arch
|
||||
# ssl
|
||||
# tls
|
||||
# bridge log
|
||||
# sdp thwack unthwack
|
||||
# cap
|
||||
# kprof
|
||||
# aoe
|
||||
# sd
|
||||
# fs
|
||||
# flash
|
||||
|
||||
# ether netif
|
||||
# ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
|
||||
|
||||
# draw screen
|
||||
# dss
|
||||
# mouse
|
||||
|
||||
# uart
|
||||
# usb
|
||||
|
||||
link
|
||||
# archoma
|
||||
# ethermedium
|
||||
# flashigep
|
||||
# loopbackmedium
|
||||
# netdevmedium
|
||||
|
||||
## avoid tickling errata 3.1.1.183
|
||||
## usbohci
|
||||
# usbehci usbehciomap
|
||||
|
||||
ip
|
||||
# tcp
|
||||
# udp
|
||||
# ipifc
|
||||
# icmp
|
||||
# icmp6
|
||||
# ipmux
|
||||
# gre
|
||||
# esp
|
||||
|
||||
misc
|
||||
# rdb
|
||||
# coproc
|
||||
# dma
|
||||
# mouse
|
||||
# sdaoe sdscsi
|
||||
# softfpu
|
||||
# syscall
|
||||
# uarti8250
|
||||
# ucalloc
|
||||
# ucallocb
|
||||
|
||||
port
|
||||
int cpuserver = 1;
|
||||
|
||||
boot cpu
|
||||
tcp
|
||||
local
|
||||
|
||||
bootdir
|
||||
boot$CONF.out boot
|
||||
/$objtype/bin/paqfs
|
||||
/$objtype/bin/auth/factotum
|
||||
bootfs.paq
|
|
@ -0,0 +1,138 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
|
||||
struct Rb
|
||||
{
|
||||
QLock;
|
||||
Rendez producer;
|
||||
Rendez consumer;
|
||||
ulong randomcount;
|
||||
uchar buf[128];
|
||||
uchar *ep;
|
||||
uchar *rp;
|
||||
uchar *wp;
|
||||
uchar next;
|
||||
uchar wakeme;
|
||||
ushort bits;
|
||||
ulong randn;
|
||||
} rb;
|
||||
|
||||
static int
|
||||
rbnotfull(void*)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = rb.rp - rb.wp;
|
||||
return i != 1 && i != (1 - sizeof(rb.buf));
|
||||
}
|
||||
|
||||
static int
|
||||
rbnotempty(void*)
|
||||
{
|
||||
return rb.wp != rb.rp;
|
||||
}
|
||||
|
||||
static void
|
||||
genrandom(void*)
|
||||
{
|
||||
up->basepri = PriNormal;
|
||||
up->priority = up->basepri;
|
||||
|
||||
for(;;){
|
||||
for(;;)
|
||||
if(++rb.randomcount > 100000)
|
||||
break;
|
||||
if(anyhigher())
|
||||
sched();
|
||||
if(!rbnotfull(0))
|
||||
sleep(&rb.producer, rbnotfull, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* produce random bits in a circular buffer
|
||||
*/
|
||||
static void
|
||||
randomclock(void)
|
||||
{
|
||||
if(rb.randomcount == 0 || !rbnotfull(0))
|
||||
return;
|
||||
|
||||
rb.bits = (rb.bits<<2) ^ rb.randomcount;
|
||||
rb.randomcount = 0;
|
||||
|
||||
rb.next++;
|
||||
if(rb.next != 8/2)
|
||||
return;
|
||||
rb.next = 0;
|
||||
|
||||
*rb.wp ^= rb.bits;
|
||||
if(rb.wp+1 == rb.ep)
|
||||
rb.wp = rb.buf;
|
||||
else
|
||||
rb.wp = rb.wp+1;
|
||||
|
||||
if(rb.wakeme)
|
||||
wakeup(&rb.consumer);
|
||||
}
|
||||
|
||||
void
|
||||
randominit(void)
|
||||
{
|
||||
addclock0link(randomclock, 1000/HZ);
|
||||
rb.ep = rb.buf + sizeof(rb.buf);
|
||||
rb.rp = rb.wp = rb.buf;
|
||||
kproc("genrandom", genrandom, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* consume random bytes from a circular buffer
|
||||
*/
|
||||
ulong
|
||||
randomread(void *xp, ulong n)
|
||||
{
|
||||
uchar *e, *p;
|
||||
ulong x;
|
||||
|
||||
p = xp;
|
||||
|
||||
if(waserror()){
|
||||
qunlock(&rb);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
qlock(&rb);
|
||||
for(e = p + n; p < e; ){
|
||||
if(rb.wp == rb.rp){
|
||||
rb.wakeme = 1;
|
||||
wakeup(&rb.producer);
|
||||
sleep(&rb.consumer, rbnotempty, 0);
|
||||
rb.wakeme = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* beating clocks will be predictable if
|
||||
* they are synchronized. Use a cheap pseudo
|
||||
* random number generator to obscure any cycles.
|
||||
*/
|
||||
x = rb.randn*1103515245 ^ *rb.rp;
|
||||
*p++ = rb.randn = x;
|
||||
|
||||
if(rb.rp+1 == rb.ep)
|
||||
rb.rp = rb.buf;
|
||||
else
|
||||
rb.rp = rb.rp+1;
|
||||
}
|
||||
qunlock(&rb);
|
||||
poperror();
|
||||
|
||||
wakeup(&rb.producer);
|
||||
|
||||
return n;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
#include "u.h"
|
||||
#include "ureg.h"
|
||||
#include "../port/lib.h"
|
||||
#include "../port/error.h"
|
||||
#include "../port/systab.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "arm.h"
|
||||
|
||||
extern uchar *periph;
|
||||
ulong *intc, *intd;
|
||||
void (*irqhandler[256])(Ureg*);
|
||||
|
||||
static char *trapname[] = {
|
||||
"reset", /* wtf */
|
||||
"undefined instruction",
|
||||
"supervisor call",
|
||||
"prefetch abort",
|
||||
"data abort",
|
||||
"unknown trap",
|
||||
"IRQ",
|
||||
"FIQ",
|
||||
};
|
||||
|
||||
void
|
||||
trapinit(void)
|
||||
{
|
||||
extern void _dataabort(), _undefined(), _prefabort(), _irq(), _fiq(), _reset(), _wtftrap(), _syscall();
|
||||
int i;
|
||||
ulong *trapv;
|
||||
|
||||
trapv = (ulong *) 0xFFFF0000;
|
||||
for(i = 0; i < 8; i++)
|
||||
trapv[i] = 0xE59FF018;
|
||||
trapv[8] = (ulong) _reset;
|
||||
trapv[9] = (ulong) _undefined;
|
||||
trapv[10] = (ulong) _syscall;
|
||||
trapv[11] = (ulong) _prefabort;
|
||||
trapv[12] = (ulong) _dataabort;
|
||||
trapv[13] = (ulong) _wtftrap;
|
||||
trapv[14] = (ulong) _irq;
|
||||
trapv[15] = (ulong) _fiq;
|
||||
|
||||
intc = (ulong *) (periph + 0x100);
|
||||
intc[1] = 0;
|
||||
intc[0] |= 1;
|
||||
intd = (ulong *) (periph + 0x1000);
|
||||
intd[0] |= 1;
|
||||
}
|
||||
|
||||
void
|
||||
intenable(int i, void (*fn)(Ureg *))
|
||||
{
|
||||
intd[0x40 + (i / 32)] |= 1 << (i % 32);
|
||||
irqhandler[i] = fn;
|
||||
}
|
||||
|
||||
void
|
||||
faultarm(Ureg *ureg)
|
||||
{
|
||||
ulong addr, sr;
|
||||
int user, n, read, nsys;
|
||||
extern ulong getdfsr(void), getifsr(void), getdfar(void), getifar(void);
|
||||
char buf[ERRMAX];
|
||||
|
||||
user = (ureg->psr & PsrMask) == PsrMusr;
|
||||
read = 1;
|
||||
if(ureg->type == 3){
|
||||
sr = getifsr();
|
||||
addr = getifar();
|
||||
}else{
|
||||
sr = getdfsr();
|
||||
addr = getdfar();
|
||||
if(sr & (1<<11))
|
||||
read = 0;
|
||||
}
|
||||
if(!user && addr >= KZERO){
|
||||
kernel:
|
||||
printureg(ureg);
|
||||
panic("kernel fault: addr=%#.8lux pc=%#.8lux sr=%#.8lux", addr, ureg->pc, sr);
|
||||
}
|
||||
if(up == nil){
|
||||
printureg(ureg);
|
||||
panic("%s fault: up=nil addr=%#.8lux pc=%#.8lux sr=%#.8lux", user ? "user" : "kernel", addr, ureg->pc, sr);
|
||||
}
|
||||
nsys = up->insyscall;
|
||||
up->insyscall = 1;
|
||||
n = fault(addr, read);
|
||||
if(n < 0){
|
||||
if(!user)
|
||||
goto kernel;
|
||||
sprint(buf, "sys: trap: fault %s addr=0x%lux", read ? "read" : "write", addr);
|
||||
postnote(up, 1, buf, NDebug);
|
||||
}
|
||||
up->insyscall = nsys;
|
||||
}
|
||||
|
||||
void
|
||||
trap(Ureg *ureg)
|
||||
{
|
||||
int user, intn, x;
|
||||
|
||||
user = (ureg->psr & PsrMask) == PsrMusr;
|
||||
if(user){
|
||||
fillureguser(ureg);
|
||||
up->dbgreg = ureg;
|
||||
}
|
||||
switch(ureg->type){
|
||||
case 3:
|
||||
case 4:
|
||||
faultarm(ureg);
|
||||
break;
|
||||
case 6:
|
||||
x = intc[3];
|
||||
intn = x & 0x3F;
|
||||
if(irqhandler[intn] != nil)
|
||||
irqhandler[intn](ureg);
|
||||
intc[4] = x;
|
||||
if(intn != 29)
|
||||
preempted();
|
||||
if(up && up->delaysched && (intn == 29)){
|
||||
sched();
|
||||
splhi();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printureg(ureg);
|
||||
panic("%s", trapname[ureg->type]);
|
||||
}
|
||||
if(user)
|
||||
up->dbgreg = nil;
|
||||
}
|
||||
|
||||
void
|
||||
syscall(Ureg *ureg)
|
||||
{
|
||||
int scall, ret;
|
||||
ulong s, sp;
|
||||
char *e;
|
||||
|
||||
m->syscall++;
|
||||
up->insyscall = 1;
|
||||
up->pc = ureg->pc;
|
||||
up->dbgreg = ureg;
|
||||
if(up->procctl == Proc_tracesyscall){
|
||||
up->procctl = Proc_stopme;
|
||||
procctl(up);
|
||||
}
|
||||
scall = ureg->r0;
|
||||
up->scallnr = scall;
|
||||
// print("%s\n", sysctab[scall]);
|
||||
spllo();
|
||||
|
||||
sp = ureg->sp;
|
||||
up->nerrlab = 0;
|
||||
ret = -1;
|
||||
if(!waserror()){
|
||||
if(scall >= nsyscall){
|
||||
postnote(up, 1, "sys: bad syscall", NDebug);
|
||||
error(Ebadarg);
|
||||
}
|
||||
validaddr(sp, sizeof(Sargs) + BY2WD, 0);
|
||||
up->s = *((Sargs*)(sp + BY2WD));
|
||||
up->psstate = sysctab[scall];
|
||||
ret = systab[scall](up->s.args);
|
||||
poperror();
|
||||
}else{
|
||||
e = up->syserrstr;
|
||||
up->syserrstr = up->errstr;
|
||||
up->errstr = e;
|
||||
}
|
||||
if(up->nerrlab != 0)
|
||||
panic("error stack");
|
||||
ureg->r0 = ret;
|
||||
|
||||
if(up->procctl == Proc_tracesyscall){
|
||||
up->procctl = Proc_stopme;
|
||||
s = splhi();
|
||||
procctl(up);
|
||||
splx(s);
|
||||
}
|
||||
up->insyscall = 0;
|
||||
up->psstate = nil;
|
||||
splhi();
|
||||
if(up->delaysched){
|
||||
sched();
|
||||
splhi();
|
||||
}
|
||||
up->dbgreg = nil;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
|
||||
extern ulong *uart;
|
||||
|
||||
void
|
||||
uartputs(char *s, int n)
|
||||
{
|
||||
for(; n--; s++){
|
||||
while(uart[17] & 1)
|
||||
;
|
||||
uart[0] = *s;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue