From d886c9d2485faf70b0e3ebc9256cfb08f3a7f72f Mon Sep 17 00:00:00 2001 From: aiju Date: Fri, 2 Sep 2011 12:23:34 +0200 Subject: [PATCH] added omap4 kernel prototype --- sys/src/9/omap4/arch.c | 161 +++++++++++++++++++++ sys/src/9/omap4/arm.h | 246 ++++++++++++++++++++++++++++++++ sys/src/9/omap4/arm.s | 31 ++++ sys/src/9/omap4/clock.c | 117 +++++++++++++++ sys/src/9/omap4/dat.h | 144 +++++++++++++++++++ sys/src/9/omap4/fns.h | 34 +++++ sys/src/9/omap4/init9.s | 25 ++++ sys/src/9/omap4/io.h | 0 sys/src/9/omap4/l.s | 298 +++++++++++++++++++++++++++++++++++++++ sys/src/9/omap4/main.c | 194 +++++++++++++++++++++++++ sys/src/9/omap4/mem.h | 65 +++++++++ sys/src/9/omap4/mkfile | 101 +++++++++++++ sys/src/9/omap4/mmu.c | 237 +++++++++++++++++++++++++++++++ sys/src/9/omap4/panda | 78 ++++++++++ sys/src/9/omap4/random.c | 138 ++++++++++++++++++ sys/src/9/omap4/trap.c | 192 +++++++++++++++++++++++++ sys/src/9/omap4/uart.c | 18 +++ 17 files changed, 2079 insertions(+) create mode 100644 sys/src/9/omap4/arch.c create mode 100644 sys/src/9/omap4/arm.h create mode 100644 sys/src/9/omap4/arm.s create mode 100644 sys/src/9/omap4/clock.c create mode 100644 sys/src/9/omap4/dat.h create mode 100644 sys/src/9/omap4/fns.h create mode 100644 sys/src/9/omap4/init9.s create mode 100644 sys/src/9/omap4/io.h create mode 100644 sys/src/9/omap4/l.s create mode 100644 sys/src/9/omap4/main.c create mode 100644 sys/src/9/omap4/mem.h create mode 100644 sys/src/9/omap4/mkfile create mode 100644 sys/src/9/omap4/mmu.c create mode 100644 sys/src/9/omap4/panda create mode 100644 sys/src/9/omap4/random.c create mode 100644 sys/src/9/omap4/trap.c create mode 100644 sys/src/9/omap4/uart.c diff --git a/sys/src/9/omap4/arch.c b/sys/src/9/omap4/arch.c new file mode 100644 index 000000000..9f4548ac2 --- /dev/null +++ b/sys/src/9/omap4/arch.c @@ -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 <= (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); +} diff --git a/sys/src/9/omap4/arm.h b/sys/src/9/omap4/arm.h new file mode 100644 index 000000000..4914d7bf2 --- /dev/null +++ b/sys/src/9/omap4/arm.h @@ -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) diff --git a/sys/src/9/omap4/arm.s b/sys/src/9/omap4/arm.s new file mode 100644 index 000000000..b66efb96d --- /dev/null +++ b/sys/src/9/omap4/arm.s @@ -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; diff --git a/sys/src/9/omap4/clock.c b/sys/src/9/omap4/clock.c new file mode 100644 index 000000000..2129fbee6 --- /dev/null +++ b/sys/src/9/omap4/clock.c @@ -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); +} + diff --git a/sys/src/9/omap4/dat.h b/sys/src/9/omap4/dat.h new file mode 100644 index 000000000..940d95b59 --- /dev/null +++ b/sys/src/9/omap4/dat.h @@ -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 diff --git a/sys/src/9/omap4/fns.h b/sys/src/9/omap4/fns.h new file mode 100644 index 000000000..ce16bdc71 --- /dev/null +++ b/sys/src/9/omap4/fns.h @@ -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*)); diff --git a/sys/src/9/omap4/init9.s b/sys/src/9/omap4/init9.s new file mode 100644 index 000000000..1d7f2bec3 --- /dev/null +++ b/sys/src/9/omap4/init9.s @@ -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 diff --git a/sys/src/9/omap4/io.h b/sys/src/9/omap4/io.h new file mode 100644 index 000000000..e69de29bb diff --git a/sys/src/9/omap4/l.s b/sys/src/9/omap4/l.s new file mode 100644 index 000000000..1a392a870 --- /dev/null +++ b/sys/src/9/omap4/l.s @@ -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 diff --git a/sys/src/9/omap4/main.c b/sys/src/9/omap4/main.c new file mode 100644 index 000000000..efe8faaa1 --- /dev/null +++ b/sys/src/9/omap4/main.c @@ -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"); +} + diff --git a/sys/src/9/omap4/mem.h b/sys/src/9/omap4/mem.h new file mode 100644 index 000000000..cb43085aa --- /dev/null +++ b/sys/src/9/omap4/mem.h @@ -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) diff --git a/sys/src/9/omap4/mkfile b/sys/src/9/omap4/mkfile new file mode 100644 index 000000000..69160335f --- /dev/null +++ b/sys/src/9/omap4/mkfile @@ -0,0 +1,101 @@ +CONF=panda +CONFLIST=panda + +loadaddr=0xF2000000 + +objtype=arm +$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.h diff --git a/sys/src/9/omap4/mmu.c b/sys/src/9/omap4/mmu.c new file mode 100644 index 000000000..cb659eddf --- /dev/null +++ b/sys/src/9/omap4/mmu.c @@ -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; +} diff --git a/sys/src/9/omap4/panda b/sys/src/9/omap4/panda new file mode 100644 index 000000000..61f1db0ef --- /dev/null +++ b/sys/src/9/omap4/panda @@ -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 diff --git a/sys/src/9/omap4/random.c b/sys/src/9/omap4/random.c new file mode 100644 index 000000000..1f7c0983d --- /dev/null +++ b/sys/src/9/omap4/random.c @@ -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; +} diff --git a/sys/src/9/omap4/trap.c b/sys/src/9/omap4/trap.c new file mode 100644 index 000000000..a965024aa --- /dev/null +++ b/sys/src/9/omap4/trap.c @@ -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; +} diff --git a/sys/src/9/omap4/uart.c b/sys/src/9/omap4/uart.c new file mode 100644 index 000000000..7a4a40083 --- /dev/null +++ b/sys/src/9/omap4/uart.c @@ -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; + } +}