diff -Nru /sys/src/boot/vt5/archvt5.c /sys/src/boot/vt5/archvt5.c --- /sys/src/boot/vt5/archvt5.c Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/archvt5.c Fri Jun 7 00:00:00 2013 @@ -0,0 +1,69 @@ +/* virtex 5 dependencies */ +#include "include.h" +#include "qtm.h" + +uvlong myhz = 400000000; /* fixed 400MHz */ +uchar mymac[Eaddrlen] = { 0x00, 0x0A, 0x35, 0x01, 0xE1, 0x48 }; + +void +clrmchk(void) +{ + putmcsr(~0); /* clear machine check causes */ + sync(); + isync(); + putesr(0); /* clears machine check */ +} + +static vlong +myprobe(uintptr addr) +{ + vlong v; + + iprint("myprobe: addr %#lux\n", addr); + v = qtmprobeaddr(addr); + if (v < 0) + iprint("myprobe: failed for %#lux\n", addr); + flushwrbufs(); + qtmerrtestaddr(addr); + return v; +} + +/* + * size by watching for bus errors (machine checks), but avoid + * tlb faults for unmapped memory beyond the maximum we expect. + * furthermore, write entire aligned cachelines to avoid macfail + * errors if we are using qtm. + */ +uintptr +memsize(void) +{ + uintptr sz; +#ifdef AMBITIOUS /* this works on vanilla systems */ + int fault; + + /* try powers of two */ + fault = 0; + if (securemem) { + qrp->err = 0; + coherence(); + } + for (sz = 64*MB; sz != 0 && sz < MAXMEM; sz <<= 1) + if (myprobe(sz) < 0) { + fault = 1; + break; + } + + /* special handling for maximum size */ + if (sz >= MAXMEM && !fault && myprobe(MEMTOP(sz) - 2*DCACHELINESZ) < 0) + sz >>= 1; + + if (securemem) { + qrp->err = 0; /* in case we perturbed qtm */ + coherence(); + } +#else + /* the vanilla ddr2 system used to have 512MB, but now only 256MB */ + sz = 256*MB; +#endif + return securemem? MEMTOP(sz): sz; +} diff -Nru /sys/src/boot/vt5/data.h /sys/src/boot/vt5/data.h --- /sys/src/boot/vt5/data.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/data.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,231 @@ +enum { + PRINTSIZE = 256, +}; + +#define MS2NS(n) (((vlong)(n))*1000000LL) +#define TK2MS(x) ((x)*(1000/HZ)) + +#define MB (1024*1024) + +/* + * Where configuration info is left for the loaded programme. + * This will turn into a structure as more is done by the boot loader + * (e.g. why parse the .ini file twice?). + * There are 3584 bytes available at CONFADDR on the PC. + * + * The low-level boot routines in l.s leave data for us at CONFADDR, + * which we pick up before reading the plan9.ini file. + */ +#define BOOTLINELEN 64 +#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN)) +#define BOOTARGSLEN 1024 /* size reduction */ +#define MAXCONF 32 /* from 100; size reduction */ + +/* + * intc bits, as of 18 aug 2009. + * specific to rae's virtex5 design + */ +enum { + Bitllfifo, + Bittemac, + Bitdma, + Bitdma2, + Bituart, + Bitmiiphy, + Bitqtmmacfail, /* qtm only */ + Bitqtmdraminit, /* qtm only */ + + Intllfifo=1<wp - (s)->rp) + +enum { + Eaddrlen = 6, + /* next two exclude 4-byte ether CRC */ + ETHERMINTU = 60, /* minimum transmit size */ + ETHERMAXTU = 1514, /* maximum transmit size */ + ETHERHDRSIZE = 14, /* size of an ethernet header */ + + MaxEther = 1, /* from 6; size reduction */ +}; + +typedef struct { + uchar d[Eaddrlen]; + uchar s[Eaddrlen]; + uchar type[2]; + uchar data[1500]; + uchar crc[4]; +} Etherpkt; + +enum { /* returned by bootpass */ + MORE, ENOUGH, FAIL +}; +enum { + INITKERNEL, + READEXEC, + READ9TEXT, + READ9DATA, + READGZIP, + READEHDR, + READPHDR, + READEPAD, + READEDATA, + TRYBOOT, + INIT9LOAD, + READ9LOAD, + FAILED +}; + +struct Boot { + int state; + + Exec exec; + char *bp; /* base ptr */ + char *wp; /* write ptr */ + char *ep; /* end ptr */ +}; + +extern uvlong clockintrs; +extern int debug; +extern char *defaultpartition; +extern int iniread; +extern uvlong myhz; +extern int pxe; +extern int securemem; +extern int vga; diff -Nru /sys/src/boot/vt5/define.h /sys/src/boot/vt5/define.h --- /sys/src/boot/vt5/define.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/define.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1 @@ +#undef PARANOID /* scan all of dram, we don't trust it */ diff -Nru /sys/src/boot/vt5/etherif.h /sys/src/boot/vt5/etherif.h --- /sys/src/boot/vt5/etherif.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/etherif.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,68 @@ +typedef struct RingBuf { + uchar owner; + uchar unused; + ushort len; + uchar pkt[sizeof(Etherpkt)]; +} RingBuf; + +enum { + Host = 0, /* buffer owned by host */ + Interface = 1, /* buffer owned by card */ + + Nrb = 32, /* default number of receive buffers */ + Ntb = 8, /* default number of transmit buffers */ +}; + +/* + * a parsed .ini line + */ +#define ISAOPTLEN 32 +#define NISAOPT 8 +#define NAMELEN 28 + +typedef struct ISAConf { + char type[NAMELEN]; + ulong port; +// ulong irq; + ulong mem; + ulong size; + uchar ea[6]; + + int nopt; + char opt[NISAOPT][ISAOPTLEN]; +} ISAConf; + +#define CONFADDR (0x2200) /* above ppc vectors */ +#define BOOTLINE ((char*)CONFADDR) + +typedef struct Ether Ether; +struct Ether { + ISAConf; /* hardware info */ + ushort ctlrno; + ushort state; /* 0: unfound, 1: found, 2: attaching */ + + void (*attach)(Ether*); /* filled in by reset routine */ + void (*transmit)(Ether*); + int (*interrupt)(ulong bit); + void (*detach)(Ether*); + void *ctlr; + + ushort nrb; /* number of software receive buffers */ + ushort ntb; /* number of software transmit buffers */ + RingBuf *rb; /* software receive buffers */ + RingBuf *tb; /* software transmit buffers */ + + ushort rh; /* first receive buffer belonging to host */ + ushort ri; /* first receive buffer belonging to card */ + + ushort th; /* first transmit buffer belonging to host */ + ushort ti; /* first transmit buffer belonging to card */ + ushort tbusy; /* transmitter is busy */ + ushort mbps; /* zero means link down */ +}; + +extern void etherrloop(Ether*, Etherpkt*, long); +extern void addethercard(char*, int(*)(Ether*)); + +#define NEXT(x, l) (((x)+1)%(l)) +#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1) diff -Nru /sys/src/boot/vt5/fs.h /sys/src/boot/vt5/fs.h --- /sys/src/boot/vt5/fs.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/fs.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,22 @@ +struct File{ + int walked; + Fs *fs; + char *path; +}; + +struct Fs{ + int dev; /* device id */ + long (*diskread)(Fs*, void*, long); /* disk read routine */ + vlong (*diskseek)(Fs*, vlong); /* disk seek routine */ + long (*read)(File*, void*, long); + int (*walk)(File*, char*); + File root; +}; + +extern int chatty; +extern int dotini(Fs*); +extern int fswalk(Fs*, char*, File*); +extern int fsread(File*, void*, long); +extern int fsboot(Fs*, char*, Boot*); + +#define BADPTR(x) (0 && (ulong)x < 0x80000000) diff -Nru /sys/src/boot/vt5/include.h /sys/src/boot/vt5/include.h --- /sys/src/boot/vt5/include.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/include.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,9 @@ +#include "u.h" +#include "libc.h" +#include "ureg.h" +#include +#include "mem.h" +#include "define.h" +#include "data.h" +#include "etherif.h" +#include "prototype.h" diff -Nru /sys/src/boot/vt5/ip.h /sys/src/boot/vt5/ip.h --- /sys/src/boot/vt5/ip.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/ip.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,100 @@ +typedef struct Udphdr Udphdr; +struct Udphdr +{ + uchar d[6]; /* Ethernet destination */ + uchar s[6]; /* Ethernet source */ + uchar type[2]; /* Ethernet packet type */ + + uchar vihl; /* Version and header length */ + uchar tos; /* Type of service */ + uchar length[2]; /* packet length */ + uchar id[2]; /* Identification */ + uchar frag[2]; /* Fragment information */ + + /* Udp pseudo ip really starts here */ + uchar ttl; + uchar udpproto; /* Protocol */ + uchar udpplen[2]; /* Header plus data length */ + uchar udpsrc[4]; /* Ip source */ + uchar udpdst[4]; /* Ip destination */ + uchar udpsport[2]; /* Source port */ + uchar udpdport[2]; /* Destination port */ + uchar udplen[2]; /* data length */ + uchar udpcksum[2]; /* Checksum */ +}; + +typedef struct Etherhdr Etherhdr; +struct Etherhdr +{ + uchar d[6]; + uchar s[6]; + uchar type[2]; + + /* Now we have the ip fields */ + uchar vihl; /* Version and header length */ + uchar tos; /* Type of service */ + uchar length[2]; /* packet length */ + uchar id[2]; /* Identification */ + uchar frag[2]; /* Fragment information */ + uchar ttl; /* Time to live */ + uchar proto; /* Protocol */ + uchar cksum[2]; /* Header checksum */ + uchar src[4]; /* Ip source */ + uchar dst[4]; /* Ip destination */ +}; + +enum +{ + IP_VER = 0x40, + IP_HLEN = 0x05, + UDP_EHSIZE = 22, + UDP_PHDRSIZE = 12, + UDP_HDRSIZE = 20, + ETHER_HDR = 14, + IP_UDPPROTO = 17, + ET_IP = 0x800, + Bcastip = 0xffffffff, + BPportsrc = 68, + BPportdst = 67, + TFTPport = 69, + Timeout = 2000, /* milliseconds; was 5000 */ + Bootrequest = 1, + Bootreply = 2, + Tftp_READ = 1, + Tftp_WRITE = 2, + Tftp_DATA = 3, + Tftp_ACK = 4, + Tftp_ERROR = 5, + Segsize = 512, + TFTPSZ = Segsize+10, +}; + +typedef struct Bootp Bootp; +struct Bootp +{ + uchar op; /* opcode */ + uchar htype; /* hardware type */ + uchar hlen; /* hardware address len */ + uchar hops; /* hops */ + uchar xid[4]; /* a random number */ + uchar secs[2]; /* elapsed since client started booting */ + uchar pad[2]; + uchar ciaddr[4]; /* client IP address (client tells server) */ + uchar yiaddr[4]; /* client IP address (server tells client) */ + uchar siaddr[4]; /* server IP address */ + uchar giaddr[4]; /* gateway IP address */ + uchar chaddr[16]; /* client hardware address */ + char sname[64]; /* server host name (optional) */ + char file[128]; /* boot file name */ + char vend[128]; /* vendor-specific goo */ +}; + +typedef struct Netaddr Netaddr; +struct Netaddr +{ + ulong ip; + ushort port; + char ea[Eaddrlen]; +}; + +extern int eipfmt(Fmt*); diff -Nru /sys/src/boot/vt5/l.s /sys/src/boot/vt5/l.s --- /sys/src/boot/vt5/l.s Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/l.s Fri Jun 7 00:00:00 2013 @@ -0,0 +1,904 @@ +/* virtex5 ppc440x5 machine assist */ +#include "mem.h" + +#define MICROBOOT 1 /* if defined, see microboot.s for startup */ + +/* + * Special Purpose Registers of interest here (440 versions) + */ +#define SPR_CCR0 0x3b3 /* Core Configuration Register 0 */ +#define SPR_CCR1 0x378 /* core configuration register 1 */ +#define SPR_DAC1 0x13c /* Data Address Compare 1 */ +#define SPR_DAC2 0x13d /* Data Address Compare 2 */ +#define SPR_DBCR0 0x134 /* Debug Control Register 0 */ +#define SPR_DBCR1 0x135 /* Debug Control Register 1 */ +#define SPR_DBCR2 0x136 /* Debug Control Register 2 */ +#define SPR_DBSR 0x130 /* Debug Status Register */ +#define SPR_DVC1 0x13e /* Data Value Compare 1 */ +#define SPR_DVC2 0x13f /* Data Value Compare 2 */ +#define SPR_DEAR 0x3D /* Data Error Address Register */ +#define SPR_ESR 0x3E /* Exception Syndrome Register */ +#define SPR_IAC1 0x138 /* Instruction Address Compare 1 */ +#define SPR_IAC2 0x139 /* Instruction Address Compare 2 */ +#define SPR_IAC3 0x13a /* Instruction Address Compare 3 */ +#define SPR_IAC4 0x13b /* Instruction Address Compare 4 */ +#define SPR_PID 0x30 /* Process ID (not the same as 405) */ +#define SPR_PVR 0x11f /* Processor Version Register */ + +#define SPR_SPRG0 0x110 /* SPR General 0 */ +#define SPR_SPRG1 0x111 /* SPR General 1 */ +#define SPR_SPRG2 0x112 /* SPR General 2 */ +#define SPR_SPRG3 0x113 /* SPR General 3 */ + +/* beware that these registers differ in R/W ability on 440 compared to 405 */ +#define SPR_SPRG4R 0x104 /* SPR general 4; user/supervisor R */ +#define SPR_SPRG5R 0x105 /* SPR general 5; user/supervisor R */ +#define SPR_SPRG6R 0x106 /* SPR general 6; user/supervisor R */ +#define SPR_SPRG7R 0x107 /* SPR general 7; user/supervisor R */ +#define SPR_SPRG4W 0x114 /* SPR General 4; supervisor W */ +#define SPR_SPRG5W 0x115 /* SPR General 5; supervisor W */ +#define SPR_SPRG6W 0x116 /* SPR General 6; supervisor W */ +#define SPR_SPRG7W 0x117 /* SPR General 7; supervisor W */ + +#define SPR_SRR0 0x01a /* Save/Restore Register 0 */ +#define SPR_SRR1 0x01b /* Save/Restore Register 1 */ +#define SPR_CSRR0 0x03a /* Critical Save/Restore Register 0 */ +#define SPR_CSRR1 0x03b /* Critical Save/Restore Register 1 */ +#define SPR_TBL 0x11c /* Time Base Lower */ +#define SPR_TBU 0x11d /* Time Base Upper */ +#define SPR_PIR 0x11e /* Processor Identity Register */ + +#define SPR_TCR 0x154 /* timer control */ +#define SPR_TSR 0x150 /* timer status */ +#define SPR_MMUCR 0x3B2 /* mmu control */ +#define SPR_DNV0 0x390 /* data cache normal victim 0-3 */ +#define SPR_DNV1 0x391 +#define SPR_DNV2 0x392 +#define SPR_DNV3 0x393 +#define SPR_DTV0 0x394 /* data cache transient victim 0-3 */ +#define SPR_DTV1 0x395 +#define SPR_DTV2 0x396 +#define SPR_DTV3 0x397 +#define SPR_DVLIM 0x398 /* data cache victim limit */ +#define SPR_INV0 0x370 /* instruction cache normal victim 0-3 */ +#define SPR_INV1 0x371 +#define SPR_INV2 0x372 +#define SPR_INV3 0x374 +#define SPR_ITV0 0x374 /* instruction cache transient victim 0-3 */ +#define SPR_ITV1 0x375 +#define SPR_ITV2 0x376 +#define SPR_ITV3 0x377 +#define SPR_IVOR(n) (0x190+(n)) /* interrupt vector offset registers 0-15 */ +#define SPR_IVPR 0x03F /* instruction vector prefix register */ +#define SPR_IVLIM 0x399 /* instruction cache victim limit */ + +#define SPR_MCSRR0 0x23A /* 440GX only */ +#define SPR_MCSRR1 0x23B +#define SPR_MCSR 0x23C + +#define SPR_DEC 0x16 /* on 440 they've gone back to using DEC instead of PIT ... */ +#define SPR_DECAR 0x36 /* ... with the auto-reload register now visible */ + +/* 440 */ + +/* use of SPRG registers in save/restore */ +#define SAVER0 SPR_SPRG0 +#define SAVER1 SPR_SPRG1 +#define SAVELR SPR_SPRG2 +#define SAVEXX SPR_SPRG3 + +/* special instruction definitions */ +#define BDNZ BC 16,0, +#define BDNE BC 0,2, + +#define TBRL 268 /* read time base lower in MFTB */ +#define TBRU 269 /* read time base upper in MFTB */ +#define MFTB(tbr,d) WORD $((31<<26)|((d)<<21)|((tbr&0x1f)<<16)|(((tbr>>5)&0x1f)<<11)|(371<<1)) + +//#define TLBIA WORD $((31<<26)|(370<<1)) // not in 440 +#define TLBSYNC WORD $((31<<26)|(566<<1)) + +/* 400 models; perhaps others */ +#define ICCCI(a,b) WORD $((31<<26)|((a)<<16)|((b)<<11)|(966<<1)) +#define DCCCI(a,b) WORD $((31<<26)|((a)<<16)|((b)<<11)|(454<<1)) +/* these follow the source -> dest ordering */ +#define DCREAD(s,t) WORD $((31<<26)|((t)<<21)|((s)<<11)|(486<<1)) +#define DCRF(n) ((((n)>>5)&0x1F)|(((n)&0x1F)<<5)) +#define MTDCR(s,n) WORD $((31<<26)|((s)<<21)|(DCRF(n)<<11)|(451<<1)) +#define MFDCR(n,t) WORD $((31<<26)|((t)<<21)|(DCRF(n)<<11)|(323<<1)) +#define MSYNC WORD $((31<<26)|(598<<1)) +#define TLBRELO(a,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|(2<<11)|(946<<1)) +#define TLBREMD(a,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|(1<<11)|(946<<1)) +#define TLBREHI(a,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|(0<<11)|(946<<1)) +#define TLBWELO(s,a) WORD $((31<<26)|((s)<<21)|((a)<<16)|(2<<11)|(978<<1)) +#define TLBWEMD(s,a) WORD $((31<<26)|((s)<<21)|((a)<<16)|(1<<11)|(978<<1)) +#define TLBWEHI(s,a) WORD $((31<<26)|((s)<<21)|((a)<<16)|(0<<11)|(978<<1)) +#define TLBSXF(a,b,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|((b)<<11)|(914<<1)) +#define TLBSXCC(a,b,t) WORD $((31<<26)|((t)<<21)|((a)<<16)|((b)<<11)|(914<<1)|1) +/* these are useless because there aren't CE/CEI equivalents for critical interrupts */ +//#define WRTMSR_EE(s) WORD $((31<<26)|((s)<<21)|(131<<1)) +//#define WRTMSR_EEI(e) WORD $((31<<26)|((e)<<15)|(163<<1)) + +/* on some models mtmsr doesn't synchronise enough (eg, 603e) */ +#define MSRSYNC MSYNC; ISYNC + +/* + * on the 4xx series, the prefetcher madly fetches across RFI, sys call, + * and others; use BR 0(PC) to stop. + */ +#define RFI WORD $((19<<26)|(50<<1)); BR 0(PC) +// #define RFCI WORD $((19<<26)|(51<<1)); BR 0(PC) + +/* + * print progress character iff on cpu0. + * steps on R7 and R8, needs SB set and TLB entry for i/o registers set. + */ +#define STEP(c, zero, notzero) \ + MOVW SPR(SPR_PIR), R7; \ + CMP R7, R0; \ + BEQ zero; \ + CMP R7, $017; \ + BNE notzero; \ +zero: MOVW $(Uartlite+4), R7; \ + MOVW $(c), R8; \ + MOVW R8, 0(R7); \ +notzero: SYNC + +//#define STEP(c, z, nz) +#define PROG(n) MOVW $(n), R18 /* pre-uart progress indicator */ + +#define UREGSPACE (UREGSIZE+8) + + NOSCHED + +TEXT start<>(SB), 1, $-4 +PROG(1) + /* except during trap handling, R0 is zero from now on */ + MOVW $0, R0 + + /* + * setup MSR + * turn off interrupts (clear ME, CE) + * use 0x000 as exception prefix + * enable kernel vm (clear IS, DS) + * clear, then enable machine checks + */ + MOVW $~0, R3 + MOVW R3, SPR(SPR_MCSR) /* clear all bits */ + MSRSYNC + MOVW R0, SPR(SPR_ESR) + MSRSYNC +PROG(2) + MOVW $MSR_ME, R3 + MOVW R3, MSR + MSRSYNC + MOVW R0, CR + + /* setup SB for pre mmu */ + MOVW $setSB(SB), R2 + + MOVW $19, R19 + MOVW $20, R20 + MOVW $21, R21 + MOVW $22, R22 + MOVW $23, R23 + MOVW $24, R24 +PROG(3) +#ifndef MICROBOOT + /* + * Invalidate the caches. + */ + ICCCI(0, 2) /* errata cpu_121 reveals that EA is used; we'll use SB */ + DCCCI(0, 2) /* dcache must not be in use */ + MSYNC +#endif + MOVW R0, SPR(SPR_DBCR0) + MOVW R0, SPR(SPR_DBCR1) + MOVW R0, SPR(SPR_DBCR2) + ISYNC + MOVW $~0, R3 + MOVW R3, SPR(SPR_DBSR) + + /* + * CCR0: + * recover from data parity = 1 + * disable gathering = 0 + * disable trace broadcast = 1 + * force load/store alignment = 0 (was 1) + * 0: fill 1+0 speculative lines on icache miss + * CCR1: + * normal parity, normal cache operation + * cpu timer advances with tick of CPU input clock (not timer clock) TO DO? + */ +#ifndef MICROBOOT + MOVW $((1<<30)|(0<<21)|(1<<15)|(0<<8)|(0<<2)), R3 + MOVW R3, SPR(SPR_CCR0) + MOVW $(0<<7), R3 /* TCS=0 */ + MOVW R3, SPR(SPR_CCR1) +#endif + /* clear i/d cache regions */ + MOVW R0, SPR(SPR_INV0) + MOVW R0, SPR(SPR_INV1) + MOVW R0, SPR(SPR_INV2) + MOVW R0, SPR(SPR_INV3) + MOVW R0, SPR(SPR_DNV0) + MOVW R0, SPR(SPR_DNV1) + MOVW R0, SPR(SPR_DNV2) + MOVW R0, SPR(SPR_DNV3) + + /* set i/d cache limits (all normal) */ + MOVW $((0<<22)|(63<<11)|(0<<0)), R3 /* TFLOOR=0, TCEILING=63 ways, NFLOOR = 0 */ + MOVW R3, SPR(SPR_DVLIM) + MOVW R3, SPR(SPR_IVLIM) + +PROG(4) + /* + * set other system configuration values + */ + MOVW R0, SPR(SPR_TBL) + MOVW R0, SPR(SPR_TBU) + MOVW R0, SPR(SPR_DEC) + MOVW $~0, R3 + MOVW R3, SPR(SPR_TSR) + MOVW R0, SPR(SPR_TCR) + ISYNC + + /* + * on the 440, the mmu is always on; kernelmmu just adds tlb entries. + * ppc440x5 cpu core manual ยง3.1 has the story about shadow + * tlbs and the like at reset. + */ +PROG(5) + BL kernelmmu(SB) + /* now running with MMU initialised & in kernel address space */ + + TLBWEHI(0,0) + TLBWEMD(0,0) + TLBWELO(0,0) + + MOVW $setSB(SB), R2 + /* it's now safe to print */ +STEP('\r', zerobootcr, notbootcr) +STEP('\n', zerobootnl, notbootnl) +STEP('P', zerobootP, notbootP) + + /* make the vectors match the old values */ + MOVW $PHYSSRAM, R3 + MOVW R3, SPR(SPR_IVPR) /* vector prefix at PHYSSRAM */ + MOVW $INT_CI, R3 + MOVW R3, SPR(SPR_IVOR(0)) + MOVW $INT_MCHECK, R3 + MOVW R3, SPR(SPR_IVOR(1)) + MOVW $INT_DSI, R3 + MOVW R3, SPR(SPR_IVOR(2)) + MOVW $INT_ISI, R3 + MOVW R3, SPR(SPR_IVOR(3)) + MOVW $INT_EI, R3 + MOVW R3, SPR(SPR_IVOR(4)) + MOVW $INT_ALIGN, R3 + MOVW R3, SPR(SPR_IVOR(5)) + MOVW $INT_PROG, R3 + MOVW R3, SPR(SPR_IVOR(6)) + MOVW $INT_FPU, R3 + MOVW R3, SPR(SPR_IVOR(7)) /* reserved (FPU?) */ + MOVW $INT_SYSCALL, R3 + MOVW R3, SPR(SPR_IVOR(8)) /* system call */ + MOVW $INT_TRACE, R3 + MOVW R3, SPR(SPR_IVOR(9)) /* reserved (trace?) */ + MOVW $INT_PIT, R3 + MOVW R3, SPR(SPR_IVOR(10)) /* decrementer */ + MOVW $INT_FIT, R3 + MOVW R3, SPR(SPR_IVOR(11)) /* fixed interval */ + MOVW $INT_WDT, R3 + MOVW R3, SPR(SPR_IVOR(12)) /* watchdog */ + MOVW $INT_DMISS, R3 + MOVW R3, SPR(SPR_IVOR(13)) /* data TLB */ + MOVW $INT_IMISS, R3 + MOVW R3, SPR(SPR_IVOR(14)) /* instruction TLB */ + MOVW $INT_DEBUG, R3 + MOVW R3, SPR(SPR_IVOR(15)) /* debug */ +STEP('l', zerobootl, notbootl) + + /* + * Set up SB, vector space (16KiB, 64KiB aligned), + * extern registers (m->, up->) and stack. + * Mach (and stack) will be cleared along with the + * rest of BSS below if this is CPU#0. + * Memstart is the first free memory location + * after the kernel. + */ + /* set R2 to correct value */ + MOVW $setSB(SB), R2 + + /* invalidate the caches again to flush any addresses below KZERO */ + ICCCI(0, 2) /* errata cpu_121 reveals that EA is used; we'll use SB */ + ISYNC + + MOVW SPR(SPR_PIR), R7 + CMP R7, $017 + BNE notcpu0b + MOVW R0, R7 +notcpu0b: + CMP R0, R7 + BNE notcpu0 + + /* set up Mach */ + /* for cpu0 */ + MOVW $mach0(SB), R(MACH) + /* put stack in sram below microboot temporarily */ + MOVW $0xfffffe00, R1 +// ADD $(MACHSIZE-8), R(MACH), R1 /* set stack */ + +// SUB $4, R(MACH), R3 +// ADD $4, R1, R4 +//clrmach: +// MOVWU R0, 4(R3) +// CMP R3, R4 +// BNE clrmach + +STEP('a', zeroboota, notboota) + + MOVW $PHYSSRAM, R6 /* vectors at bottom of sram */ + MOVW R0, R(USER) /* up-> */ + MOVW R0, 0(R(MACH)) + +_CPU0: /* boot processor */ + MOVW $edata-4(SB), R3 + MOVW R1, R4 /* stop before microboot */ +_clrbss: /* clear BSS */ + MOVWU R0, 4(R3) + CMP R3, R4 + BNE _clrbss + +STEP('n', zerobootn, notbootn) +// MOVW R4, memstart(SB) /* start of unused memory */ + MOVW R0, memstart(SB) /* start of unused memory: dram */ + MOVW R6, vectorbase(SB) /* 64KiB aligned vector base, for trapinit */ + +STEP(' ', zerobootsp, notbootsp) + BL main(SB) + BR 0(PC) /* paranoia -- not reached */ + +notcpu0: + MOVW $mach0(SB), R(MACH) + ADD $(MACHSIZE-8), R(MACH) /* cpu1 */ + /* put stack in sram below microboot & cpu0's stack temporarily */ + MOVW $0xfffffb00, R1 + + /* give cpu0 time to set things up */ + MOVW $(10*1024*1024), R3 +spin: + SUB $1, R3 + CMP R0, R3 + BNE spin + + BL main(SB) + BR 0(PC) /* paranoia -- not reached */ + + +GLOBL mach0(SB), $(MAXMACH*BY2PG) + +TEXT kernelmmu(SB), 1, $-4 +PROG(6) +#ifndef MICROBOOT + /* make following TLB entries shared, TID=PID=0 */ + MOVW R0, SPR(SPR_PID) + + /* + * allocate cache on store miss, disable U1 as transient, + * disable U2 as SWOA, no dcbf or icbi exception, tlbsx search 0. + */ + MOVW R0, SPR(SPR_MMUCR) + ISYNC +#endif + + /* map various things 1:1 */ + MOVW $tlbtab(SB), R4 + MOVW $tlbtabe(SB), R5 + MOVW $(3*4), R6 /* sizeof a tlb entry */ +// ADD R6, R4 /* skip first 2 TLB entries in tlbtab */ +// ADD R6, R4 /* skip first 2 TLB entries in tlbtab */ + SUB R4, R5 + DIVW R6, R5 /* R5 gets # of tlb entries in table */ + SUB $4, R4 /* back up before MOVWU */ + MOVW R5, CTR + MOVW $63, R3 +// SUB $2, R3 /* skip first 2 TLB entries in TLB (#62-63) */ + SYNC + ISYNC +PROG(7) +ltlb: + MOVWU 4(R4), R5 /* TLBHI */ + TLBWEHI(5,3) + MOVWU 4(R4), R5 /* TLBMD */ + TLBWEMD(5,3) + MOVWU 4(R4), R5 /* TLBLO */ + TLBWELO(5,3) + SUB $1, R3 + BDNZ ltlb +PROG(8) + /* clear all remaining entries to remove any aliasing from boot */ +#ifndef MICROBOOT + CMP R3, R0 + BEQ cltlbe + MOVW R0, R5 +cltlb: + /* can't use 0 (R0) as first operand */ + TLBWEHI(5,3) + TLBWEMD(5,3) + TLBWELO(5,3) + SUB $1, R3 + CMP R3, $0 + BGE cltlb +cltlbe: +#endif + SYNC + ISYNC /* switch to new TLBs */ +PROG(9) +#ifdef MICROBOOT + RETURN +#else + /* + * this is no longer true; the microboot has done this: + * we're currently relying on the shadow I/D TLBs. to switch to + * the new TLBs, we need a synchronising instruction. + */ + MOVW LR, R4 + MOVW R4, SPR(SPR_SRR0) + MOVW MSR, R4 + MOVW R4, SPR(SPR_SRR1) + /* + * resume in kernel mode in caller; R3 has the index of the first + * unneeded TLB entry + */ + RFI +#endif + +TEXT tlbinval(SB), 1, $-4 + TLBWEHI(0, 3) + TLBWEMD(0, 3) + TLBWELO(0, 3) + ISYNC + RETURN + +TEXT splhi(SB), 1, $-4 + MOVW MSR, R3 + RLWNM $0, R3, $~MSR_EE, R4 + RLWNM $0, R4, $~MSR_CE, R4 + MOVW R4, MSR + MSRSYNC + MOVW LR, R31 + MOVW R31, 4(R(MACH)) /* save PC in m->splpc */ + RETURN + +TEXT splx(SB), 1, $-4 + MOVW LR, R31 + MOVW R31, 4(R(MACH)) /* save PC in m->splpc */ + /* fall though */ + +TEXT splxpc(SB), 1, $-4 + MOVW MSR, R4 + RLWMI $0, R3, $MSR_EE, R4 + RLWMI $0, R3, $MSR_CE, R4 + MOVW R4, MSR + MSRSYNC + RETURN + +TEXT spllo(SB), 1, $-4 + MOVW MSR, R3 + OR $MSR_EE, R3, R4 + OR $MSR_CE, R4 + MOVW R4, MSR + MSRSYNC + RETURN + +TEXT spldone(SB), 1, $-4 + RETURN + +TEXT islo(SB), 1, $-4 + MOVW MSR, R3 + MOVW $(MSR_EE|MSR_CE), R4 + AND R4, R3 + RETURN + +/* invalidate region of i-cache */ +TEXT icflush(SB), 1, $-4 /* icflush(virtaddr, count) */ + MOVW n+4(FP), R4 + RLWNM $0, R3, $~(ICACHELINESZ-1), R5 + SUB R5, R3 + ADD R3, R4 + ADD $(ICACHELINESZ-1), R4 + SRAW $ICACHELINELOG, R4 + MOVW R4, CTR +icf0: ICBI (R5) + ADD $ICACHELINESZ, R5 + BDNZ icf0 + ISYNC + RETURN + +TEXT sync(SB), 1, $0 + SYNC + RETURN + +TEXT isync(SB), 1, $0 + ISYNC + RETURN + +/* write-back then invalidate region of d-cache */ +TEXT dcflush(SB), 1, $-4 /* dcflush(virtaddr, count) */ + MOVW n+4(FP), R4 + RLWNM $0, R3, $~(DCACHELINESZ-1), R5 + CMP R4, $0 + BLE dcf1 + SYNC + SUB R5, R3 + ADD R3, R4 + ADD $(DCACHELINESZ-1), R4 + SRAW $DCACHELINELOG, R4 + MOVW R4, CTR +dcf0: DCBF (R5) + ADD $DCACHELINESZ, R5 + BDNZ dcf0 +dcf1: + SYNC + RETURN + +TEXT cacheson(SB), 1, $-4 + MOVW $1, R3 /* return value: true iff caches on */ + RETURN + +TEXT cachesinvalidate(SB), 1, $-4 + ICCCI(0, 2) /* errata cpu_121 reveals that EA is used; we'll use SB */ + DCCCI(0, 2) /* dcache must not be in use (or just needs to be clean?) */ + MSYNC + RETURN + +TEXT getpit(SB), 1, $0 + MOVW SPR(SPR_DEC), R3 /* they've moved it back to DEC */ + RETURN + +TEXT putpit(SB), 1, $0 + MOVW R3, SPR(SPR_DEC) + MOVW R3, SPR(SPR_DECAR) + RETURN + +TEXT putpid(SB), 1, $0 + MOVW R3, SPR(SPR_PID) + MOVW SPR(SPR_MMUCR), R4 + RLWMI $0, R3, $0xFF, R4 + MOVW R4, SPR(SPR_MMUCR) + RETURN + +TEXT getpid(SB), 1, $0 + MOVW SPR(SPR_PID), R3 + RETURN + +TEXT getpir(SB), 1, $-4 + MOVW SPR(SPR_PIR), R3 + CMP R3, $017 + BNE normal + MOVW R0, R3 +normal: + RETURN + +TEXT putstid(SB), 1, $0 + MOVW SPR(SPR_MMUCR), R4 + RLWMI $0, R3, $0xFF, R4 + MOVW R4, SPR(SPR_MMUCR) + RETURN + +TEXT getstid(SB), 1, $0 + MOVW SPR(SPR_MMUCR), R3 + RLWNM $0, R3, $0xFF, R3 + RETURN + +TEXT gettbl(SB), 1, $0 + MFTB(TBRL, 3) + RETURN + +TEXT gettbu(SB), 1, $0 + MFTB(TBRU, 3) + RETURN + +TEXT gettsr(SB), 1, $0 + MOVW SPR(SPR_TSR), R3 + RETURN + +TEXT puttsr(SB), 1, $0 + MOVW R3, SPR(SPR_TSR) + RETURN + +TEXT puttcr(SB), 1, $0 + MOVW R3, SPR(SPR_TCR) + RETURN + +TEXT getpvr(SB), 1, $0 + MOVW SPR(SPR_PVR), R3 + RETURN + +TEXT getmsr(SB), 1, $0 + MOVW MSR, R3 + RETURN + +TEXT putmsr(SB), 1, $0 + SYNC + MOVW R3, MSR + MSRSYNC + RETURN + +TEXT getmcsr(SB), 1, $0 + MOVW SPR(SPR_MCSR), R3 + RETURN + +TEXT putmcsr(SB), 1, $-4 + MOVW R3, SPR(SPR_MCSR) + RETURN + +TEXT getesr(SB), 1, $0 + MOVW SPR(SPR_ESR), R3 + RETURN + +TEXT putesr(SB), 1, $0 + MOVW R3, SPR(SPR_ESR) + RETURN + +TEXT putevpr(SB), 1, $0 + MOVW R3, SPR(SPR_IVPR) + RETURN + +TEXT getccr0(SB), 1, $-4 + MOVW SPR(SPR_CCR0), R3 + RETURN + +TEXT setsp(SB), 1, $0 + MOVW R3, R1 + RETURN + +TEXT getsp(SB), 1, $0 + MOVW R1, R3 + RETURN + +TEXT getdear(SB), 1, $0 + MOVW SPR(SPR_DEAR), R3 + RETURN + +TEXT tas32(SB), 1, $0 + SYNC + MOVW R3, R4 + MOVW $0xdead,R5 +tas1: + DCBF (R4) /* fix for 603x bug */ + LWAR (R4), R3 + CMP R3, $0 + BNE tas0 + STWCCC R5, (R4) + BNE tas1 +tas0: + SYNC + ISYNC + RETURN + +TEXT eieio(SB), 1, $0 + EIEIO + RETURN + +TEXT syncall(SB), 1, $0 + SYNC + ISYNC + RETURN + +TEXT _xinc(SB), 1, $0 /* void _xinc(long *); */ + MOVW R3, R4 +xincloop: + DCBF (R4) /* fix for 603x bug */ + LWAR (R4), R3 + ADD $1, R3 + STWCCC R3, (R4) + BNE xincloop + RETURN + +TEXT _xdec(SB), 1, $0 /* long _xdec(long *); */ + MOVW R3, R4 +xdecloop: + DCBF (R4) /* fix for 603x bug */ + LWAR (R4), R3 + ADD $-1, R3 + STWCCC R3, (R4) + BNE xdecloop + RETURN + +TEXT cas32(SB), 1, $0 /* int cas32(void*, u32int, u32int) */ + MOVW R3, R4 /* addr */ + MOVW old+4(FP), R5 + MOVW new+8(FP), R6 + DCBF (R4) /* fix for 603x bug? */ + LWAR (R4), R3 + CMP R3, R5 + BNE fail + STWCCC R6, (R4) + BNE fail + MOVW $1, R3 + RETURN +fail: + MOVW $0, R3 + RETURN + +TEXT tlbwrx(SB), 1, $-4 + MOVW hi+4(FP), R5 + MOVW mid+8(FP), R6 + MOVW lo+12(FP), R7 + MSYNC + TLBWEHI(5, 3) + TLBWEMD(6, 3) + TLBWELO(7, 3) + ISYNC + RETURN + +TEXT tlbrehi(SB), 1, $-4 + TLBREHI(3, 3) + RETURN + +TEXT tlbremd(SB), 1, $-4 + TLBREMD(3, 3) + RETURN + +TEXT tlbrelo(SB), 1, $-4 + TLBRELO(3, 3) + RETURN + +TEXT tlbsxcc(SB), 1, $-4 + TLBSXCC(0, 3, 3) + BEQ tlbsxcc0 + MOVW $-1, R3 /* not found */ +tlbsxcc0: + RETURN + +TEXT gotopc(SB), 1, $0 + MOVW R3, CTR + MOVW LR, R31 /* for trace back */ + BR (CTR) + + +/* + * following Book E, traps thankfully leave the mmu on. + * the following code has been executed at the exception + * vector location already: + * MOVW R0, SPR(SAVER0) + * MOVW LR, R0 + * MOVW R0, SPR(SAVELR) + * BL trapvec(SB) + */ +TEXT trapvec(SB), 1, $-4 + MOVW LR, R0 + MOVW R0, SPR(SAVEXX) /* save ivoff--interrupt vector offset */ +/* entry point for critical interrupts, machine checks, and faults */ +trapcommon: + MOVW R1, SPR(SAVER1) /* save stack pointer */ + /* did we come from user space? */ + MOVW SPR(SPR_SRR1), R0 + MOVW CR, R1 + MOVW R0, CR + BC 4,17,ktrap /* if MSR[PR]=0, we are in kernel space */ + + /* switch to kernel stack */ + MOVW R1, CR + + MOVW SPR(SPR_SPRG7R), R1 /* up->kstack+KSTACK-UREGSPACE, set in touser and sysrforkret */ + + BL saveureg(SB) + MOVW $mach0(SB), R(MACH) + MOVW 8(R(MACH)), R(USER) + BL trap(SB) + BR restoreureg + +ktrap: + MOVW R1, CR + MOVW SPR(SAVER1), R1 + SUB $UREGSPACE, R1 /* push onto current kernel stack */ + BL saveureg(SB) + BL trap(SB) + +restoreureg: + MOVMW 48(R1), R2 /* r2:r31 */ + /* defer R1 */ + MOVW 40(R1), R0 + MOVW R0, SPR(SAVER0) + MOVW 36(R1), R0 + MOVW R0, CTR + MOVW 32(R1), R0 + MOVW R0, XER + MOVW 28(R1), R0 + MOVW R0, CR /* CR */ + MOVW 24(R1), R0 + MOVW R0, LR + MOVW 20(R1), R0 + MOVW R0, SPR(SPR_SPRG7W) /* kstack for traps from user space */ + MOVW 16(R1), R0 + MOVW R0, SPR(SPR_SRR0) /* old PC */ + MOVW 12(R1), R0 + RLWNM $0, R0, $~MSR_WE, R0 /* remove wait state */ + MOVW R0, SPR(SPR_SRR1) /* old MSR */ + /* cause, skip */ + MOVW 44(R1), R1 /* old SP */ + MOVW SPR(SAVER0), R0 + RFI + +/* + * critical trap/interrupt. + * the only one we can take is machine check, synchronously, and + * outside any other trap handler. + * [MSR_ME not cleared => handler may be interrupted by machine check] + */ +TEXT trapcritvec(SB), 1, $-4 + MOVW LR, R0 + MOVW R0, SPR(SAVEXX) + MOVW SPR(SPR_CSRR0), R0 /* PC or excepting insn */ + MOVW R0, SPR(SPR_SRR0) + MOVW SPR(SPR_CSRR1), R0 /* old MSR */ + MOVW R0, SPR(SPR_SRR1) + BR trapcommon + +/* + * machine check. + * make it look like the others. + */ +TEXT trapmvec(SB), 1, $-4 + MOVW LR, R0 + MOVW R0, SPR(SAVEXX) + MOVW SPR(SPR_MCSRR0), R0 /* PC or excepting insn */ + MOVW R0, SPR(SPR_SRR0) + MOVW SPR(SPR_MCSRR1), R0 /* old MSR */ + MOVW R0, SPR(SPR_SRR1) + BR trapcommon + +/* + * enter with stack set and mapped. + * on return, SB (R2) has been set, and R3 has the Ureg*, + * the MMU has been re-enabled, kernel text and PC are in KSEG, + * Stack (R1), R(MACH) and R(USER) are set by caller, if required. + */ +TEXT saveureg(SB), 1, $-4 +/* + * save state + */ + MOVMW R2, 48(R1) /* save gprs r2 to r31 */ + MOVW $setSB(SB), R2 + MOVW SPR(SAVER1), R4 + MOVW R4, 44(R1) + MOVW SPR(SAVER0), R5 + MOVW R5, 40(R1) + MOVW CTR, R6 + MOVW R6, 36(R1) + MOVW XER, R4 + MOVW R4, 32(R1) + MOVW CR, R5 + MOVW R5, 28(R1) + MOVW SPR(SAVELR), R6 /* LR */ + MOVW R6, 24(R1) + MOVW SPR(SPR_SPRG7R), R6 /* up->kstack+KSTACK-UREGSPACE */ + MOVW R6, 20(R1) + MOVW SPR(SPR_SRR0), R0 + MOVW R0, 16(R1) /* PC of excepting insn (or next insn) */ + MOVW SPR(SPR_SRR1), R0 + MOVW R0, 12(R1) /* old MSR */ + MOVW SPR(SAVEXX), R0 + MOVW R0, 8(R1) /* cause/vector */ + ADD $8, R1, R3 /* Ureg* */ + STWCCC R3, (R1) /* break any pending reservations */ + MOVW $0, R0 /* compiler/linker expect R0 to be zero */ + RETURN + +/* + * restore state from Ureg and return from trap/interrupt + */ +TEXT sysrforkret(SB), 1, $-4 + MOVW R1, 20(R1) /* up->kstack+KSTACK-UREGSPACE set in ureg */ + BR restoreureg + +/* + * 4xx specific + */ +TEXT firmware(SB), 1, $0 + MOVW $(3<<28), R3 + MOVW R3, SPR(SPR_DBCR0) /* system reset */ + BR 0(PC) diff -Nru /sys/src/boot/vt5/libc.h /sys/src/boot/vt5/libc.h --- /sys/src/boot/vt5/libc.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/libc.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,102 @@ +/* + * functions (possibly) linked in, complete, from libc. + */ +#define nelem(x) (sizeof(x)/sizeof((x)[0])) +#define offsetof(s, m) (ulong)(&(((s*)0)->m)) +#define assert(x) if(x){}else _assert("x") + +/* + * mem routines + */ +extern void* memset(void*, int, ulong); +extern int memcmp(void*, void*, ulong); +extern void* memmove(void*, void*, ulong); + +/* + * string routines + */ +extern int cistrcmp(char *, char *); +extern int cistrncmp(char *, char *, int); +extern char *strchr(char *, int); +extern int strcmp(char *, char *); +extern char* strecpy(char*, char*, char*); +extern long strlen(char*); +extern int strncmp(char *, char *, int); +extern char* strncpy(char*, char*, long); +extern char* strstr(char *, char *); +extern int tokenize(char*, char**, int); + +/* + * malloc + */ +extern void free(void*); +extern void* malloc(ulong); +extern void* mallocalign(ulong, ulong, long, ulong); +extern int mallocinit(void*, ulong); + +/* + * print routines + */ +typedef struct Fmt Fmt; +struct Fmt { + uchar runes; /* output buffer is runes or chars? */ + void* start; /* of buffer */ + void* to; /* current place in the buffer */ + void* stop; /* end of the buffer; overwritten if flush fails */ + int (*flush)(Fmt*); /* called when to == stop */ + void* farg; /* to make flush a closure */ + int nfmt; /* num chars formatted so far */ + va_list args; /* args passed to dofmt */ + int r; /* % format Rune */ + int width; + int prec; + ulong flags; +}; + +extern int print(char*, ...); +extern char* seprint(char*, char*, char*, ...); +extern char* vseprint(char*, char*, char*, va_list); + +#pragma varargck argpos print 1 +#pragma varargck argpos seprint 3 + +#pragma varargck type "lld" vlong +#pragma varargck type "llx" vlong +#pragma varargck type "lld" uvlong +#pragma varargck type "llx" uvlong +#pragma varargck type "ld" long +#pragma varargck type "lx" long +#pragma varargck type "ld" ulong +#pragma varargck type "lx" ulong +#pragma varargck type "d" int +#pragma varargck type "x" int +#pragma varargck type "c" int +#pragma varargck type "C" int +#pragma varargck type "d" uint +#pragma varargck type "x" uint +#pragma varargck type "c" uint +#pragma varargck type "C" uint +#pragma varargck type "s" char* +#pragma varargck type "q" char* +#pragma varargck type "S" Rune* +#pragma varargck type "%" void +#pragma varargck type "p" uintptr +#pragma varargck type "p" void* +#pragma varargck flag ',' +#pragma varargck type "E" uchar* /* eipfmt */ +#pragma varargck type "V" uchar* /* eipfmt */ + +extern int fmtinstall(int, int (*)(Fmt*)); +extern int dofmt(Fmt*, char*); + +/* + * one-of-a-kind + */ +extern void _assert(char*); +extern uintptr getcallerpc(void*); +extern long strtol(char*, char**, int); +extern ulong strtoul(char*, char**, int); +extern void longjmp(jmp_buf, int); +extern int setjmp(jmp_buf); + +extern char etext[], edata[], end[]; diff -Nru /sys/src/boot/vt5/mem.h /sys/src/boot/vt5/mem.h --- /sys/src/boot/vt5/mem.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/mem.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,209 @@ +/* + * Memory and machine-specific definitions. Used in C and assembler. + */ +#define KiB 1024u /* Kibi 0x0000000000000400 */ +#define MiB 1048576u /* Mebi 0x0000000000100000 */ +#define GiB 1073741824u /* Gibi 000000000040000000 */ +#define TiB 1099511627776ull /* Tebi 0x0000010000000000 */ +#define PiB 1125899906842624ull /* Pebi 0x0004000000000000 */ +#define EiB 1152921504606846976ull /* Exbi 0x1000000000000000 */ + +#define HOWMANY(x, y) (((x)+((y)-1))/(y)) +#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) +#define ROUNDDN(x, y) (((x)/(y))*(y)) +#define MIN(a, b) ((a) < (b)? (a): (b)) +#define MAX(a, b) ((a) > (b)? (a): (b)) + +/* + * Sizes + */ +#define BI2BY 8 /* bits per byte */ +#define BY2V 8 /* bytes per vlong */ +#define BY2SE 4 /* bytes per stack element */ +#define BY2WD 4 /* bytes per int */ +#define BY2PG 4096 /* bytes per page */ +#define PGSHIFT 12 /* log(BY2PG) */ +#define PGROUND(s) ROUNDUP(s, BY2PG) +#define UTROUND(t) ROUNDUP((t), 0x100000) +#define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */ + +#define ICACHESIZE 32768 /* 0, 4, 8, 16, or 32 KB */ +#define ICACHEWAYSIZE (ICACHESIZE/64) /* 64-way set associative */ +#define ICACHELINELOG 5 /* 8 words (4 bytes) per line */ +#define ICACHELINESZ (1< */ +#define USER 29 /* R29 is up-> */ + +/* + * Virtual MMU + */ +#define PTEMAPMEM (1024*1024) +#define PTEPERTAB (PTEMAPMEM/BY2PG) +#define SEGMAPSIZE 1984 +#define SSEGMAPSIZE 16 +#define PPN(x) ((x)&~(BY2PG-1)) + +#define PTEVALID (1<<0) +#define PTEWRITE (1<<1) +#define PTERONLY (0<<1) +#define PTEUNCACHED (1<<2) + +/* + * Physical MMU + */ +#define NTLB 64 /* number of entries */ +#define NTLBPID 256 /* number of hardware pids (0 = global) */ + +/* TLBHI */ +#define TLBEPN(x) ((x) & ~0x3FF) +#define TLB1K (0<<4) +#define TLB4K (1<<4) +#define TLB16K (2<<4) +#define TLB64K (3<<4) +#define TLB256K (4<<4) +#define TLB1MB (5<<4) +/* 4Mbyte not implemented */ +#define TLB16MB (7<<4) +/* 32Mbyte not implemented */ +#define TLB256MB (9<<4) +#define TLBVALID (1<<9) +#define TLBTS (1<<8) /* Translation address space */ + +/* TLBMID */ +#define TLBRPN(x) ((x) & ~0x3FF) +#define TLBERPN(uv) (((uv)>>32)&0xF) /* with full address as uvlong */ + +/* TLBLO */ +#define TLBU0 (1<<15) /* user definable */ +#define TLBU1 (1<<14) /* user definable */ +#define TLBU2 (1<<13) /* user definable */ +#define TLBU3 (1<<12) /* user definable */ +#define TLBW (1<<11) /* write-through? */ +#define TLBI (1<<10) /* cache inhibit */ +#define TLBM (1<<9) /* memory coherent */ +#define TLBG (1<<8) /* guarded */ +#define TLBLE (1<<7) /* little endian mode */ +#define TLBUX (1<<5) /* user execute enable */ +#define TLBUW (1<<4) /* user writable */ +#define TLBUR (1<<3) /* user readable */ +#define TLBSX (1<<2) /* supervisor execute enable */ +#define TLBSW (1<<1) /* supervisor writable */ +#define TLBSR (1<<0) /* supervisor readable */ + +#define TLBWR (TLBSW|TLBSR) + +/* + * software TLB (for quick reload by [id]tlbmiss) + */ +#define STLBLOG 10 +#define STLBSIZE (1< ]+,/{ + tab = "\t"; + if(length($1) < 8) + sep = tab tab; + else + sep = tab; + split($3, a, ","); + printf "#define %s%s%s", $1, sep, a[1]; + if(match($0, /\/\*.*\*\/$/)){ + len = length(a[1]); + sep = ""; + while(len < 24){ + sep = sep tab; + len += 8; + } + printf "%s%s", sep, substr($0, RSTART); + } + printf "\n" +} + +/^$/{ + printf "\n"; +} + +END{ +}' $* diff -Nru /sys/src/boot/vt5/mkfile /sys/src/boot/vt5/mkfile --- /sys/src/boot/vt5/mkfile Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/mkfile Fri Jun 7 00:00:00 2013 @@ -0,0 +1,56 @@ +CONF=vt5load +CONFLIST=vt5load +BASE=0xfffe2100 # first location after vectors; see PHYSSRAM + +objtype=power +$target.list + $LD -o $target -l -T$BASE -R4 $OBJ $LIB + size $target + nm -n $target | tail -5 + nm -n $target >$target.names + +$OBJ: $HFILES + +${objtype}a.h:D: $objtype.h + rc mkenum $objtype.h > $target + +install:V: $p$CONF $p$CONF.elf microboot.elf + cp -x $prereq /power + { 9fs lookout && cp -x $prereq /n/lookout/power } & + { 9fs piestand && cp -x $prereq /n/piestand/power } & + { 9fs slocum && cp $prereq /n/slocum/home/rae/hbsr/ml510 } & + wait + +microboot.hex microboot.elf: microboot.q + # ignore "_main: odd branch target address" + $LD -a -o microboot.elf -s -l -H5 -T0xfffffee8 -R4 $prereq >microboot.hex + +nuke clean:V: + rm -f *.[$OS] *.out *.acid *.elf $p$CONF^* $O.* diff -Nru /sys/src/boot/vt5/mkfilelist /sys/src/boot/vt5/mkfilelist --- /sys/src/boot/vt5/mkfilelist Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/mkfilelist Fri Jun 7 00:00:00 2013 @@ -0,0 +1,12 @@ +#!/bin/rc + +rfork e +switch($#*){ +case 1 + RE=`{echo *.c | sed 's/ /|/g; s/.*/^(&)$/'} + LIST=`{builtin cd $1; ls *.c | grep -v ''$RE''} + echo $LIST | sed 's/\.c//g; s/ +/|/g' +case * + exit 'usage' +} +exit '' diff -Nru /sys/src/boot/vt5/parse /sys/src/boot/vt5/parse --- /sys/src/boot/vt5/parse Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/parse Fri Jun 7 00:00:00 2013 @@ -0,0 +1,536 @@ +BEGIN{ + oargc = 0; + for(argc = 1; argc < ARGC; argc++){ + if(ARGV[argc] !~ /^-.+/ || ARGV[argc] ~ /--/) + break; + if(ARGV[argc] != "-D") + oargv[ARGV[argc]] = oargc++; + else + DEBUG = 1; + ARGV[argc] = ""; + } + + objtype = ENVIRON["objtype"]; + + while(getline > 0){ + if(/^[ \t]*$/ || /^#/) + continue; + + if(/^[^ \t]/){ + #section[$1] = 0; + tag = $1; + } + if(!tag) + continue; + sub(/^[ \t]*/, ""); + line[tag, section[tag]++] = $0; + } + + o = ""; + if(!oargc || ("-mkdevlist" in oargv)){ + s = mkdevlist(); + if(!("-mkdevlist" in oargv) || (oargc > 1)) + s = "DEVS=" s; + o = o s "\n"; + } + if((!oargc || ("-mkmach" in oargv)) && (objtype in section)){ + s = mkmach(); + if(!("-mkmach" in oargv) || (oargc > 1)) + s = "MACH=" s; + o = o s "\n"; + } + if((!oargc || ("-mklib" in oargv)) && ("lib" in section)){ + s = mklib(); + if(!("-mklib" in oargv) || (oargc > 1)) + s = "LIB=" s; + o = o s "\n"; + } + if((!oargc || ("-mkport" in oargv) ) && ("port" in section)){ + s = mkport(); + if(!("-mkport" in oargv) || (oargc > 1)) + s = "PORT=" s; + o = o s "\n"; + } + if("dbgflg" in section){ + for(i = 1; i < section["dbgflg"]; i++){ + n = split(line["dbgflg", i], a); + if(n < 2 || n > 4 || a[2] !~ /'[a-zA-Z]'/) + continue; + if(n > 2 && a[3] !~ /'[a-zA-Z]'/) + continue; + if(n == 4 && (a[4] < 1 || a[4] >= 128)) + continue; + dbgc[a[1]] = a[2]; + if(n == 4) + dbgflg[a[3]] = a[4]; + else if(n == 3) + dbgflg[a[3]] = 1; + } + } + if((!oargc || ("-mkrules" in oargv)) && ("dir" in section)){ + o = o mkrules(".", exists, a, c, "-I."); + for(i = 1; i < section["dir"]; i++){ + n = split(line["dir", i], a); + dir = "../" a[1]; + if(n == 1) + a[2] = "-I."; + s = a[2]; + o = o mkrules(dir, exists, a, c, s); + l = listolate(a, "|"); + if(l != ""){ + o = o "^(" l ")\\.$O:R: " dir "/\\1.s\n"; + o = o "\t$AS $AFLAGS " s " " dir "/$stem1.s\n"; + } + l = listolate(c, "|"); + if(l != ""){ + o = o "^(" l ")\\.$O:R: " dir "/\\1.c\n"; + o = o "\t$CC $CFLAGS " s " " dir "/$stem1.c\n"; + } + } + } + if((!oargc || ("-mkrootrules" in oargv)) && ("rootdir" in section)){ + mkrootrules(name, cname, src); + s = ARGV[argc] ".root.s:D:"; + for(i = 1; i < section["rootdir"]; i++) + s = s " " src[i]; + s = s "\n\tmkrootall\\\n"; + for(i = 1; i < section["rootdir"]; i++) + s = s "\t\t" name[i] " " cname[i] " " src[i] "\\\n"; + s = s "\t>$target\n"; + if(section["rootdir"] > 1) + o = o s; + } + if((!oargc || ("-mkrrrules" in oargv)) && ("rr" in section)){ + n = split(line["rr", 0], a); + if(n == 1) + a[2] = ARGV[argc] ".proto"; + s = "$CONF.rr:\tmkrr $CONF " a[2] "\n"; + s = s "\tmkrr $CONF " a[2] "\n"; + for(i = 1; i < section["rr"]; i++) + s = s "$CONF.rr:\t" line["rr", i] "\n"; + o = o s; + } + if("-mkdevc" in oargv) + o = o mkdevc(); + if("-mkerrstr" in oargv) + o = o mkerrstr(); + if("-mksystab" in oargv) + o = o mksystab(); + if("-mkbootconf" in oargv) + o = o mkbootconf(); + + # + # to do: + # bootmkfile + # mkrootall (can it be done at all?) + # + printf o; + + exit 0; +} + +function mkbootconf( a, n, s, t, u, c, d, p, r){ + s = "#include \n"; + s = s "#include \n\n"; + s = s "#include \"../boot/boot.h\"\n\n"; + s = s "Method method[] = {\n"; + + c = "0"; + d = "#S/sdC0/"; + p = "boot"; + r = "/root"; + + for(i = 0; i < section["boot"]; i++){ # NOTE: start at 0 + n = split(line["boot", i], a); + if(a[1] == "boot"){ + if(a[2] == "cpu"){ + c = "1"; + if(n == 4 && a[3] == "boot") + d = a[4]; + } + else if(a[2] == "rootdir" && n == 3) + r = a[3]; + else if(a[2] ~ /^(bboot|dosboot|romboot)$/){ + c = "1"; + p = a[2]; + } + else if(a[2] == "boot" && n == 3) + d = a[3]; + continue; + } + s = s "\t{ \"" a[1] "\", config" a[1] ", connect" a[1] ", "; + t = "nil"; + if(n > 1){ + u = line["boot", i]; + if(sub(/^[_A-Za-z][_A-Za-z0-9]*[ \t]*/, "", u)){ + if(match(u, /^".*"$/)) + u = substr(u, RSTART+1, RLENGTH-2); + t = "\"" u "\""; + } + } + s = s t ", },\n"; + } + s = s "\t{ nil },\n};\n\n"; + s = s "int cpuflag = " c ";\n"; + s = s "char* rootdir = \"" r "\";\n"; + s = s "char* bootdisk = \"" d "\";\n"; + s = s "extern void " p "(int, char**);\n\n"; + s = s "void\nmain(int argc, char **argv)\n"; + s = s "{\n\t" p "(argc, argv);\n}\n" + + t = "int (*cfs)(int) = 0;\n"; + for(i = 1; i < section["rootdir"]; i++){ + if($1 !~ /\/bin\/cfs$/) + continue; + t = "int (*cfs)(int) = cache;\n"; + break; + } + s = s t; + + return s; +} + +function mksystab( a, i, f, n, s, t){ + s = "#include \"/sys/src/libc/9syscall/sys.h\"\n\n"; + s = s "typedef void Syscall(Ar0*, va_list);\n\n"; + + t = ""; + while(getline < "/sys/src/libc/9syscall/sys.h"){ + if($1 != "#define" || NF != 3) + continue; + + f = "sys" tolower($2); + if($2 == "SYSR1") + f = "sysr1"; + if($2 == "RENDEZVOUS") + n = "Rendez"; + else if($2 == "BRK_") + n = "Brk"; + else + n = substr($2, 1, 1) tolower(substr($2, 2)); + + s = s "Syscall " f ";\n"; + t = t "\t[" $2 "]\t"; + if(length($2) < 6) + t = t "\t"; + t = t "{ \"" n "\", " f ", "; + # + # if($1 ~ "(FVERSION|FSTAT|STAT)") + # t = t "{ .u = 0 } },\n"; + # else + # + if($1 ~ "(BIND|MOUNT|FWSTAT|WSTAT)") + t = t "{ .l = 0 } },\n"; + else if($1 ~ "(EXEC|RENDEZVOUS|SEGBRK|SEGATTACH)") + t = t "{ .v = (void*)-1 } },\n"; + else + t = t "{ .i = -1 } },\n"; + } + if("syscall" in section){ + for(i = 1; i < section["syscall"]; i++){ + if(split(line["syscall", i], a) != 8) + continue; + if(line["syscall", i] !~ /#define.*{ \.[ilpuv] = .* }$/) + continue; + + f = "sys" tolower(a[2]); + n = substr(a[2], 1, 1) tolower(substr(a[2], 2)); + + s = s "\nSyscall " f ";\n"; + t = t a[1] " " a[2] "\t" a[3] "\n\t[" a[2] "]\t"; + if(length(a[2]) < 6) + t = t "\t"; + split(line["syscall", i], a, "{"); + t = t "{ \"" n "\", " f ", {" a[2] " },\n"; + } + } + s = s "struct {\n\tchar*\tn;\n\tSyscall*f;\n\tAr0\tr;\n}"; + s = s " systab[] = {\n" t "};\n\nint nsyscall = nelem(systab);\n"; + + return s; +} + +function mkerrstr( a, s){ + FS="[ \t;]+"; + while(getline < "error.h"){ + split($0, a, /\/\* | \*\//); + s = s $2 " " $3 " = \"" a[2] "\";\n"; + } + FS=" "; + + return s; +} + +function mkdevc( a, d, i, m, n, s, t, u, name, cname){ + s = "#include \"u.h\"\n"; + s = s "#include \"lib.h\"\n"; + s = s "#include \"mem.h\"\n"; + s = s "#include \"dat.h\"\n"; + s = s "#include \"fns.h\"\n"; + s = s "#include \"error.h\"\n\n"; + s = s "#include \"io.h\"\n\n"; + + t = ""; + for(i = 1; i < section["dev"]; i++){ + split(line["dev", i], a); + s = s "extern Dev " a[1] "devtab;\n"; + t = t "\t&" a[1] "devtab,\n"; + d[a[1]]++; + } + s = s "Dev* devtab[] = {\n" t "\tnil,\n};\n\n"; + + mkrootrules(name, cname, m); + t = ""; + for(i = 1; i < section["rootdir"]; i++){ + s = s "extern uchar " cname[i] "code[];\n"; + s = s "extern usize " cname[i] "len;\n"; + t = t "\taddbootfile(\"" name[i] "\", " cname[i] "code, " cname[i] "len);\n"; + } + for(i = 1; i < section["link"]; i++){ + split(line["link", i], a); + s = s "extern void " a[1] "link(void);\n"; + t = t "\t" a[1] "link();\n"; + } + s = s "void\nlinks(void)\n{\n" t "}\n\n"; + + if("ip" in d && "ip" in section){ + t = ""; + s = s "#include \"../ip/ip.h\"\n"; + for(i = 1; i < section["ip"]; i++){ + split(line["ip", i], a); + s = s "extern void " a[1] "init(Fs*);\n"; + t = t "\t" a[1] "init,\n"; + } + s = s "void (*ipprotoinit[])(Fs*) = {\n" t "\tnil,\n};\n\n"; + } + + if("sd" in d && "sd" in section){ + t = ""; + s = s "#include \"sd.h\"\n"; + for(i = 1; i < section["sd"]; i++){ + split(line["sd", i], a); + s = s "extern SDifc " a[1] "ifc;\n"; + t = t "\t&" a[1] "ifc,\n"; + } + s = s "SDifc* sdifc[] = {\n" t "\tnil,\n};\n\n"; + } + + if("uart" in d && "uart" in section){ + t = ""; + for(i = 1; i < section["uart"]; i++){ + split(line["uart", i], a); + a[1] = substr(a[1], 5, length(a[1])-4) "physuart"; + s = s "extern PhysUart " a[1] ";\n"; + t = t "\t&" a[1] ",\n"; + } + s = s "PhysUart* physuart[] = {\n" t "\tnil,\n};\n\n"; + } + + t = ""; + n = 0; + if("physseg" in section){ + for(i = 1; i < section["physseg"]; i++){ + u = line["physseg", i]; + if(u ~ /^\.[_A-Za-z][_A-Za-z0-9]*/) + t = t "\t"; + t = t "\t" u "\n"; + if(sub(/.*\.pgalloc.*=[^_A-Za-z]*/, "", u)){ + if(match(u, /^[_A-Za-z][_A-Za-z0-9]*/)){ + u = substr(u, RSTART, RLENGTH); + s = s "extern Page *(*" u ")(Segment*, uintptr);\n"; + } + } + else if(sub(/.*\.pgfree.*=[^_A-Za-z]*/, "", u)){ + if(match(u, /^[_A-Za-z][_A-Za-z0-9]*/)){ + u = substr(u, RSTART, RLENGTH); + s = s "extern void (*" u ")(Page*);\n"; + } + } + if(match(u, /}/)) + n++; + } + } + s = s "Physseg physseg[" n+8 "] = {\n"; + s = s "\t{\t.attr\t= SG_SHARED,\n"; + s = s "\t\t.name\t= \"shared\",\n"; + s = s "\t\t.size\t= SEGMAXSIZE,\n\t},\n"; + s = s "\t{\t.attr\t= SG_BSS,\n"; + s = s "\t\t.name\t= \"memory\",\n"; + s = s "\t\t.size\t= SEGMAXSIZE,\n\t},\n"; + s = s t "};\nint nphysseg = " n+8 ";\n\n"; + + s = s "char dbgflg[256]"; + t = ""; + for(u in dbgflg) + t = t "\t[" u "]\t" dbgflg[u] ",\n"; + if(t != "") + s = s " = {\n" t "}"; + s = s ";\n\n"; + + for(i in m) + delete m[i]; + + for(i = 1; i < section["misc"]; i++){ + split(line["misc", i], a); + m[a[1]] = line["misc", i]; + } + if("cache" in m){ + s = s "extern void cinit(void);\n"; + s = s "extern void copen(Chan*);\n"; + s = s "extern int cread(Chan*, uchar*, int, vlong);\n"; + s = s "extern void cupdate(Chan*, uchar*, int, vlong);\n"; + s = s "extern void cwrite(Chan*, uchar*, int, vlong);\n\n"; + s = s "void (*mfcinit)(void) = cinit;\n"; + s = s "void (*mfcopen)(Chan*) = copen;\n"; + s = s "int (*mfcread)(Chan*, uchar*, int, vlong) = cread;\n"; + s = s "void (*mfcupdate)(Chan*, uchar*, int, vlong) = cupdate;\n"; + s = s "void (*mfcwrite)(Chan*, uchar*, int, vlong) = cwrite;\n\n"; + } + else{ + s = s "void (*mfcinit)(void) = nil;\n"; + s = s "void (*mfcopen)(Chan*) = nil;\n"; + s = s "int (*mfcread)(Chan*, uchar*, int, vlong) = nil;\n"; + s = s "void (*mfcupdate)(Chan*, uchar*, int, vlong) = nil;\n"; + s = s "void (*mfcwrite)(Chan*, uchar*, int, vlong) = nil;\n\n"; + } + if(!("rdb" in misc)){ + s = s "void\n"; + s = s "rdb(void)\n"; + s = s "{\n"; + s = s "\tsplhi();\n"; + s = s "\tiprint(\"rdb...not installed\\n\");\n"; + s = s "\tfor(;;);\n"; + s = s "}\n\n"; + } + + if("conf" in section){ + for(i = 1; i < section["conf"]; i++) + s = s line["conf", i] "\n"; + s = s "\n"; + } + t = "."; + while("pwd" | getline > 0){ + if($0 ~ /^\//) + t = $0; + } + s = s "char* conffile = \"" t "/" ARGV[argc] "\";\n"; + s = s "ulong kerndate = KERNDATE;\n"; + + return s; +} + +function mkrootrules(name, cname, src, a, i, n){ + for(i = 1; i < section["rootdir"]; i++){ + n = split(line["rootdir", i], a); + if(n >= 2) + name[i] = a[2]; + else + name[i] = a[1]; + sub(/.*\//, "", name[i]); + cname[i] = a[1]; + gsub(/[^a-zA-Z0-9_]/, "_", cname[i]); + src[i] = a[1]; + } +} + +function mkrules(dir, exists, ameta, cmeta, flags, f, i, s, t){ + for(i in ameta) + delete ameta[i]; + for(i in cmeta) + delete cmeta[i]; + + s = ""; + while("cd " dir "; /bin/ls *.[cs]" | getline > 0){ + if($0 !~ /^[A-Za-z0-9]*\.[cs]$/) + continue; + f = $0; + if(!sub(/\.[cs]$/, "")) + continue; + if($0 in exists) + continue; + exists[$0] = dir; + if(f ~ /\.c$/){ + if(!($0 in dbgc)){ + cmeta[$0]++; + continue; + } + t = "$CC $CFLAGS " flags; + } + else{ + if(!($0 in dbgc)){ + ameta[$0]++; + continue; + } + t = "$AS $AFLAGS " flags; + } + s = s $0 ".$O:\t" dir "/" f "\n"; + s = s "\t" t " -D'_DBGC_='" dbgc[$0] "'' " dir "/" f "\n"; + } + return s; +} + +function mkport( array){ + arrayify(array, "port", "", ".$O", 1); + + return listolate(array, " "); +} + +function mklib( array){ + arrayify(array, "lib", "/$objtype/lib/", ".a", 1); + + return listolate(array," "); +} + +function mkmach( a, i, s){ + s = ""; + for(i = 1; i < section[objtype]; i++){ + if(!split(line[objtype, i], a)) + continue; + if(s == "") + s = a[1] ".$O"; + else + s = s " " a[1] ".$O"; + } + + return s; +} + +function mkdevlist( a, array, i, j, n, s){ + for(s in section){ + if(line[s, 0] !~ /[ \t]\+dev[^_A-Za-z0-9]*/) + continue; + if(s == "dev") + arrayify(array, s, "dev", ".$O", 1); + else if(s == objtype) + arrayify(array, s, "", ".$O", 0); + else + arrayify(array, s, "", ".$O", 1); + } + + return listolate(array, " "); +} + +function listolate(array, sep, a, s){ + s = ""; + for(a in array){ + if(s == "") + s = a; + else + s = a sep s; + } + + return s; +} + +function arrayify(array, tag, prefix, suffix, one, a, i, j, n){ + for(i = 1; i < section[tag]; i++){ + n = split(line[tag, i], a); + if(one) + array[prefix a[1] suffix]++; + for(j = 2; j <= n; j++){ + if(a[$j] ~ /[+=-].*/) + continue; + array[a[j] suffix]++; + } + } +} diff -Nru /sys/src/boot/vt5/physmem.h /sys/src/boot/vt5/physmem.h --- /sys/src/boot/vt5/physmem.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/physmem.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,31 @@ +/* + * Memory-mapped IO + */ + +/* + * virtex5 system loses top 1/5th of 512MB to ECC in the secure memory system. + */ +#define MEMTOP(phys) ((((((phys)/DCACHELINESZ)*4)/5) * DCACHELINESZ) & -128) +#define MAXMEM (512*MB) + +/* memory map for rae's virtex4 design */ +#define PHYSDRAM 0 +#define PHYSSRAM 0xfffe0000 /* 128K long, in top 128M */ +#define PHYSMMIO Io + +#define Io 0xf0000000 /* ~512K of IO registers */ +#define Uartlite 0xf0000000 +#define Gpio 0xf0010000 +#define Intctlr 0xf0020000 +#define Temac 0xf0030000 +#define Llfifo 0xf0040000 +#define Dmactlr 0xf0050000 +#define Dmactlr2 0xf0060000 +/* + * if these devices exist in a given hardware configuration, + * they will be at these addresses. + */ +#define Qtm 0xf0070000 /* encrypted memory control */ +#define Mpmc 0xf0080000 /* multi-port memory controller */ +/* setting low bit interrupts cpu0; don't set Hie */ +#define Intctlr2 0xf0090000 /* sw interrupt controller */ diff -Nru /sys/src/boot/vt5/portmkfile /sys/src/boot/vt5/portmkfile --- /sys/src/boot/vt5/portmkfile Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/portmkfile Fri Jun 7 00:00:00 2013 @@ -0,0 +1,16 @@ +%.$O: %.s + $AS $AFLAGS $stem.s + +%.$O: %.c + $CC $CFLAGS $stem.c + +%.$O: include.h +%.$O: /$objtype/include/u.h +%.$O: libc.h +%.$O: define.h +%.$O: data.h portdata.h +%.$O: prototype.h portprototype.h +%.$O: glue.h + +clean:V: + rm -f *.[$OS] *.out *.m *.acid $p$CONF *.elf diff -Nru /sys/src/boot/vt5/portprototype.h /sys/src/boot/vt5/portprototype.h --- /sys/src/boot/vt5/portprototype.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/portprototype.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,2 @@ +extern void ilock(Lock*); +extern void iunlock(Lock*); diff -Nru /sys/src/boot/vt5/prototype.h /sys/src/boot/vt5/prototype.h --- /sys/src/boot/vt5/prototype.h Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/prototype.h Fri Jun 7 00:00:00 2013 @@ -0,0 +1,199 @@ +#define PTR2UINT(p) ((uintptr)(p)) +#define UINT2PTR(i) ((void*)(i)) + +/* physical == virtual in our world! */ +#define PADDR(a) ((ulong)(a) & ~0xF0000000) + +#define GSHORT(p) (((p)[1]<<8)|(p)[0]) +#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p)) +#define GLSHORT(p) (((p)[0]<<8)|(p)[1]) +#define GLLONG(p) (((ulong)GLSHORT(p)<<16)|GLSHORT(p+2)) +#define PLLONG(p,v) (p)[3]=(v);(p)[2]=(v)>>8;(p)[1]=(v)>>16;(p)[0]=(v)>>24 + +#define mallocalign(n, a, o, s) ialloc((n), (a)) + +/* emergency debugging printing, from uart.c */ +#define Uarttxfifo ((ulong *)(Uartlite + 4)) +#define PROG(c) { coherence(); *Uarttxfifo = (uchar)(c); coherence(); } + +/* + * l32p.s + */ +void cachesinvalidate(void); +void dcbi(void*); +void dcflush(uintptr, usize); +void eieio(void); +u32int esrget(void); +void esrput(u32int); +// char* getconf(char*); +#define getconf(s) nil +u32int getccr0(void); +u32int getdar(void); +u32int getdear(void); +u32int getdec(void); +u32int getesr(void); +u32int getmsr(void); +u32int getpid(void); +u32int getpir(void); +u32int getpit(void); +u32int getpvr(void); +uintptr getsp(void); +u32int gettbl(void); +u32int gettsr(void); +void icflush(uintptr, usize); +int islo(void); +void isync(void); +void microdelay(int); +u32int mmucrget(void); +void mmucrput(u32int); +void putdec(ulong); +void putesr(ulong); +void putevpr(ulong); +void putmcsr(u32int); +void putmsr(u32int); +void putpid(u32int); +void putpit(u32int); +void putsdr1(u32int); +void puttcr(u32int); +void puttsr(u32int); +void setsp(uintptr); +void spldone(void); +int splhi(void); +int spllo(void); +void splx(int); +void splxpc(int); +void sync(void); +void syncall(void); +int tas32(uint*); +void trapvec(void); +int _xdec(long *); +int _xinc(long *); + +/* + * trap.c + */ +void trapdisable(void); +void trapinit(void); + +/* + * intr.c + */ +void intr(Ureg *ur); +void intrack(ulong); +void intrenable(ulong bit, int (*func)(ulong)); +void intrinit(void); +ulong lddbg(void); + +/* + * uart.c + */ +int vuartgetc(void); +void vuartputc(int c); +int vuartputs(char *s, int len); + +/* + * clock.c + */ +void clockinit(void); +void clockintr(Ureg *ureg); +void delay(int); +void prcpuid(void); +void timerintr(Ureg*); + +/* + * dma.c + */ +void dmacpy(void *dest, void *src, ulong len, ulong flags); +void dmainit(void); +void dmastart(void *dest, void *src, ulong len, ulong flags); +void dmawait(void); + +/* + * ether.c + */ +uchar *etheraddr(int ctlrno); +int etherinit(void); +void etherinitdev(int, char*); +void etherprintdevs(int); +int etherrxflush(int ctlrno); +int etherrxpkt(int ctlrno, Etherpkt* pkt, int timo); +int ethertxpkt(int ctlrno, Etherpkt* pkt, int len, int); + +/* + * llfifo.c + */ +void llfifoinit(Ether *); +int llfifointr(ulong bit); +void llfiforeset(void); +void llfifotransmit(uchar *ubuf, unsigned len); + +/* + * load.c + */ +int getfields(char*, char**, int, char); +void* ialloc(ulong, int); + +/* + * boot.c + */ +int bootpass(Boot *b, void *vbuf, int nbuf); + +/* + * bootp.c + */ +int bootpboot(int, char*, Boot*); +void* pxegetfspart(int, char*, int); + +/* + * conf.c + */ +int dotini(Fs *fs); + +/* + * console.c + */ +void consinit(char*, char*); +int getstr(char*, char*, int, char*, int); +void kbdinit(void); +void warp86(char*, ulong); +void warp9(ulong); + +/* + * inflate.c + */ +int gunzip(uchar*, int, uchar*, int); + +/* + * misc. + */ + +void ilock(Lock*); +void iunlock(Lock*); +int lock(Lock*); +void unlock(Lock*); + +void panic(char *fmt, ...); + +#define TAS(l) tas32(l) + +#define iprint print + +#define coherence() eieio() +#define exit(n) for(;;) ; + +void cacheline0(uintptr addr); +ulong cacheson(void); +void clrmchk(void); +void dump(void *, int); +void dumpregs(Ureg *); +void flushwrbufs(void); +uintptr memsize(void); +vlong probeaddr(uintptr addr); +/* + * qtm.c + */ +int qtmerrfmt(char *, int); +void qtmerrtest(char *); +void qtmerrtestaddr(ulong); +int qtmmemreset(void); +vlong qtmprobeaddr(uintptr addr); diff -Nru /sys/src/boot/vt5/tlb.s /sys/src/boot/vt5/tlb.s --- /sys/src/boot/vt5/tlb.s Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/tlb.s Fri Jun 7 00:00:00 2013 @@ -0,0 +1,42 @@ +/* virtex5 ppc440x5 bootstrap tlb entries */ +#include "mem.h" + +#define MB (1024*1024) + +/* + * TLB prototype entries, loaded once-for-all at startup, + * remaining unchanged thereafter. + * Limit the table size to ensure it fits in small TLBs. + * First entry will be tlb entry #63 and we count down from there. + * + * Add TLBW for write-through caching. + * TLBM doesn't help on the Xilinx virtex 5, alas. + * The low 4 bits of the middle word are high bits (33-36) of the RPN; + * we set them to zero. + */ +#define TLBE(hi, md, lo) WORD $(hi); WORD $(md); WORD $(lo) + +TEXT tlbtab(SB), 1, $-4 + + /* + * SRAM, 128K. put vectors here. + * the `microboot' at the end of SRAM has already installed these + * TLB entries for SRAM. + */ + TLBE(PHYSSRAM | TLB64K | TLBVALID, PHYSSRAM, + TLBSR | TLBSX | TLBSW) + TLBE(PHYSSRAM+(64*1024) | TLB64K | TLBVALID, PHYSSRAM+(64*1024), + TLBSR | TLBSX | TLBSW) + + /* DRAM, 512MB */ + TLBE(PHYSDRAM | TLB256MB | TLBVALID, PHYSDRAM, + TLBSR | TLBSX | TLBSW) + TLBE(PHYSDRAM+(256*MB) | TLB256MB | TLBVALID, PHYSDRAM+(256*MB), + TLBSR | TLBSX | TLBSW) + + /* memory-mapped IO, 1MB */ + TLBE(PHYSMMIO | TLB1MB | TLBVALID, PHYSMMIO, + TLBSR | TLBSW | TLBI | TLBG) + +TEXT tlbtabe(SB), 1, $-4 + RETURN diff -Nru /sys/src/boot/vt5/trap.c /sys/src/boot/vt5/trap.c --- /sys/src/boot/vt5/trap.c Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/trap.c Fri Jun 7 00:00:00 2013 @@ -0,0 +1,327 @@ +/* + * power pc 440 traps + */ +#include "include.h" + +static struct { + ulong off; + char *name; +} intcause[] = { + { INT_CI, "critical input" }, + { INT_MCHECK, "machine check" }, + { INT_DSI, "data access" }, + { INT_ISI, "instruction access" }, + { INT_EI, "external interrupt" }, + { INT_ALIGN, "alignment" }, + { INT_PROG, "program exception" }, + { INT_FPU, "floating-point unavailable" }, + { INT_DEC, "decrementer" }, + { INT_SYSCALL, "system call" }, + { INT_TRACE, "trace trap" }, + { INT_FPA, "floating point unavailable" }, + { INT_APU, "auxiliary processor unavailable" }, + { INT_PIT, "programmable interval timer interrrupt" }, + { INT_FIT, "fixed interval timer interrupt" }, + { INT_WDT, "watch dog timer interrupt" }, + { INT_DMISS, "data TLB miss" }, + { INT_IMISS, "instruction TLB miss" }, + { INT_DEBUG, "debug interrupt" }, + { 0, "unknown interrupt" } +}; + +static char *excname(ulong, u32int); + +char *regname[]={ + "CAUSE", "SRR1", + "PC", "GOK", + "LR", "CR", + "XER", "CTR", + "R0", "R1", + "R2", "R3", + "R4", "R5", + "R6", "R7", + "R8", "R9", + "R10", "R11", + "R12", "R13", + "R14", "R15", + "R16", "R17", + "R18", "R19", + "R20", "R21", + "R22", "R23", + "R24", "R25", + "R26", "R27", + "R28", "R29", + "R30", "R31", +}; + +void intr(Ureg *ur); + +static int probing, trapped; +static jmp_buf probenv; + +static void +sethvec(uintptr v, void (*r)(void)) +{ + u32int *vp; + ulong o, ra; + long d; + + vp = UINT2PTR(v); + vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */ + vp[1] = 0x7c0802a6; /* MOVW LR, R0 */ + vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */ + d = (uchar*)r - (uchar*)&vp[3]; + o = (ulong)d >> 25; + if(o != 0 && o != 0x7F){ + /* a branch too far: running from ROM */ + ra = (ulong)r; + vp[3] = (15<<26)|(ra>>16); /* MOVW $r&~0xFFFF, R0 */ + vp[4] = (24<<26)|(ra&0xFFFF); /* OR $r&0xFFFF, R0 */ + vp[5] = 0x7c0803a6; /* MOVW R0, LR */ + vp[6] = 0x4e800021; /* BL (LR) */ + } + else + vp[3] = (18<<26)|(d&0x3FFFFFC)|1; /* BL (relative) */ + dcflush(PTR2UINT(vp), 8*sizeof(u32int)); +} + +static void +sethvec2(uintptr v, void (*r)(void)) +{ + u32int *vp; + long d; + + vp = UINT2PTR(v); + d = (uchar*)r - (uchar*)&vp[0]; + vp[0] = (18<<26)|(d & 0x3FFFFFC); /* B (relative) */ + dcflush(PTR2UINT(vp), sizeof(*vp)); +} + +extern uintptr vectorbase; + +void +trapinit(void) +{ + uintptr e, s; + + putesr(0); /* clears machine check */ + coherence(); + + /* + * set all exceptions to trap + */ + s = vectorbase + 0x100; /* Mach is at vectorbase */ + /* 0x2000 is last documented 405 vector */ + for(e = s+0x2100; s < e; s += 0x100) + sethvec(s, trapvec); + coherence(); + + /* + * set exception handlers + */ +// sethvec(vectorbase + INT_RESET, trapcritvec); +// sethvec(vectorbase + INT_MCHECK, trapcritvec); + sethvec(vectorbase + INT_DSI, trapvec); + sethvec(vectorbase + INT_ISI, trapvec); + sethvec(vectorbase + INT_EI, trapvec); /* external non-critical intrs */ + sethvec(vectorbase + INT_ALIGN, trapvec); + sethvec(vectorbase + INT_PROG, trapvec); + sethvec(vectorbase + INT_FPU, trapvec); + sethvec(vectorbase + INT_SYSCALL, trapvec); + sethvec(vectorbase + INT_APU, trapvec); + sethvec(vectorbase + INT_PIT, trapvec); + sethvec(vectorbase + INT_FIT, trapvec); +// sethvec(vectorbase + INT_WDT, trapcritvec); +// sethvec2(vectorbase + INT_DMISS, dtlbmiss); +// sethvec2(vectorbase + INT_IMISS, itlbmiss); +// sethvec(vectorbase + INT_DEBUG, trapcritvec); + syncall(); + + /* l.s already set EVPR */ + putmsr(getmsr() | MSR_CE | MSR_ME); /* no MSR_EE here */ + coherence(); +} + +void +trapdisable(void) +{ + putmsr(getmsr() & ~( MSR_EE | MSR_CE | MSR_ME)); /* MSR_DE as well? */ +} + +static char* +excname(ulong ivoff, u32int esr) +{ + int i; + + if(ivoff == INT_PROG){ + if(esr & ESR_PIL) + return "illegal instruction"; + if(esr & ESR_PPR) + return "privileged"; + if(esr & ESR_PTR) + return "trap with successful compare"; + if(esr & ESR_PEU) + return "unimplemented APU/FPU"; + if(esr & ESR_PAP) + return "APU exception"; + if(esr & ESR_U0F) + return "data storage: u0 fault"; + } + for(i=0; intcause[i].off != 0; i++) + if(intcause[i].off == ivoff) + break; + return intcause[i].name; +} + +void +dumpstack(void) +{ + /* sorry. stack is in dram, not Mach now */ +} + +void +dumpregs(Ureg *ureg) +{ + int i; + uintptr *l; + + iprint("cpu%d: registers for boot\n", m->machno); + + l = &ureg->cause; + for(i = 0; i < nelem(regname); i += 2, l += 2) + iprint("%s\t%.8p\t%s\t%.8p\n", regname[i], l[0], regname[i+1], l[1]); +} + +static void +faultpower(Ureg *ureg, ulong addr, int read) +{ + USED(read); + dumpregs(ureg); + panic("boot fault: 0x%lux", addr); +} + +void +trap(Ureg *ur) +{ + int ecode; + u32int esr; + + ur->cause &= 0xFFE0; + ecode = ur->cause; + if(ecode < 0 || ecode >= 0x2000) + ecode = 0x3000; + esr = getesr(); + putesr(0); + + switch(ecode){ + case INT_SYSCALL: + panic("syscall in boot: srr1 %#4.4luX pc %#p\n", + ur->srr1, ur->pc); + + case INT_PIT: + clockintr(ur); + break; + + case INT_MCHECK: + if (probing) { + trapped++; + longjmp(probenv, 1); + } + if(esr & ESR_MCI){ + //iprint("mcheck-mci %lux\n", ur->pc); + faultpower(ur, ur->pc, 1); + break; + } + //iprint("mcheck %#lux esr=%#ux dear=%#ux\n", ur->pc, esr, getdear()); + ur->pc -= 4; /* back up to faulting instruction */ + /* fall through */ + case INT_DSI: + case INT_DMISS: + faultpower(ur, getdear(), !(esr&ESR_DST)); + break; + + case INT_ISI: + case INT_IMISS: + faultpower(ur, ur->pc, 1); + break; + + case INT_EI: + intr(ur); + break; + + case INT_PROG: + default: + print("boot %s pc=%#lux\n", excname(ecode, esr), ur->pc); + dumpregs(ur); + dumpstack(); + if(m->machno == 0) + spllo(); + exit(1); + } + splhi(); +} + +static Lock fltlck; + +vlong +probeaddr(uintptr addr) +{ + vlong v; + + ilock(&fltlck); + probing = 1; + /* + * using setjmp & longjmp is a sleazy hack; see ../../9k/vt4/trap.c + * for a less sleazy hack. + */ + if (setjmp(probenv) == 0) + v = *(ulong *)addr; /* this may cause a fault */ + else + v = -1; + probing = 0; + iunlock(&fltlck); + return v; +} + +vlong +qtmprobeaddr(uintptr addr) +{ + int i; + vlong v, junk; + vlong *ptr; + + ilock(&fltlck); + probing = 1; + trapped = 0; + v = 0; + /* + * using setjmp & longjmp is a sleazy hack; see ../../9k/vt4/trap.c + * for a less sleazy hack. + */ + if (setjmp(probenv) == 0) { + syncall(); + clrmchk(); + syncall(); + + /* write entire cache lines, unless we get a bus error */ + ptr = (vlong *)(addr & ~(DCACHELINESZ - 1)); + for (i = 0; !trapped && !(getesr() & ESR_MCI) && + i < DCACHELINESZ/sizeof *ptr; i++) { + ptr[i] = 0; + coherence(); + } + junk = ptr[0]; + USED(junk); + } else + v = -1; + + syncall(); + if(getesr() & ESR_MCI) + v = -1; + syncall(); + clrmchk(); + syncall(); + probing = 0; + iunlock(&fltlck); + return v; +} diff -Nru /sys/src/boot/vt5/vt5load /sys/src/boot/vt5/vt5load --- /sys/src/boot/vt5/vt5load Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/vt5load Fri Jun 7 00:00:00 2013 @@ -0,0 +1,28 @@ +# rae's virtex5 ml510 boot +power + l + tlb + load + trap + archvt5 + clock + intr + uart + ethertemac + llfifo + fakeqtm +# port stuff + portclock + malloc + print + console + taslock + ether + boot + fs + bootp +dir + vt4 +lib + libip + libc diff -Nru /sys/src/boot/vt5/words /sys/src/boot/vt5/words --- /sys/src/boot/vt5/words Thu Jan 1 00:00:00 1970 +++ /sys/src/boot/vt5/words Fri Jun 7 00:00:00 2013 @@ -0,0 +1,21 @@ +This bootstrap is intended to load a Plan 9 kernel via bootp and tftp +into a Xilinx Virtex 5 ML510 board. Most of its source is in ../vt4. +The mkfile generates an elf file which is then fed into the Xilinx CAD +tool to generate a bitstream for loading into the FPGA on the ML510. + +This bootstrap will almost certainly not work for you without some +changes. In particular, the addresses of the I/O registers in +physmem.h will have to be changed to match yours and you'll need to +make sure that they are mapped if you have more than 512K of them. + +Because of pecularities of the PowerPC 440, there's a `micro +bootstrap' in microboot.s that kicks everything off. The bootstrap +runs with the MMU on, because it's always on on a 440. + +This bootstrap does not use dma but in principle it could, by +replacing calls to fifocpy with calls to dmacpy. dma is one more +thing that could go wrong, so we ended up using the cpu to copy words +to and from ethernet fifos. + +This code runs in high memory (above 0xfffe0000) and its global data +is thus in sram.