ref: a691c9111a69257e206ce895d35396d0f6225929
author: Jacob Moody <[email protected]>
date: Sat May 4 16:21:39 EDT 2024
initial commit
--- /dev/null
+++ b/clock.c
@@ -1,0 +1,76 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+static uvlong freq;
+
+enum {
+ Enable = 1<<0,
+ Imask = 1<<1,
+ Istatus = 1<<2,
+};
+
+void
+clockshutdown(void)
+{
+}
+
+static void
+localclockintr(Ureg *ureg, void *)
+{
+}
+
+void
+clockinit(void)
+{
+}
+
+void
+timerset(uvlong next)
+{
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+ return 0;
+}
+
+ulong
+perfticks(void)
+{
+ return fastticks(nil);
+}
+
+ulong
+µs(void)
+{
+ uvlong hz;
+ uvlong t = fastticks(&hz);
+ return (t * 1000000ULL) / hz;
+}
+
+void
+microdelay(int n)
+{
+ ulong now;
+
+ now = µs();
+ while(µs() - now < n);
+}
+
+void
+delay(int n)
+{
+ while(--n >= 0)
+ microdelay(1000);
+}
+
+void
+synccycles(void)
+{
+}
--- /dev/null
+++ b/dat.h
@@ -1,0 +1,227 @@
+/*
+ * Time.
+ *
+ * HZ should divide 1000 evenly, ideally.
+ * 100, 125, 200, 250 and 333 are okay.
+ */
+#define HZ 100 /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+
+enum {
+ Mhz = 1000 * 1000,
+
+ GpioLow = 0,
+ GpioHigh,
+ GpioRising,
+ GpioFalling,
+ GpioEdge,
+};
+
+typedef struct Conf Conf;
+typedef struct Confmem Confmem;
+typedef struct FPsave FPsave;
+typedef struct PFPU PFPU;
+typedef struct ISAConf ISAConf;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct Memcache Memcache;
+typedef struct MMMU MMMU;
+typedef struct Mach Mach;
+typedef struct Page Page;
+typedef struct PhysUart PhysUart;
+typedef struct Pcidev Pcidev;
+typedef struct PMMU PMMU;
+typedef struct Proc Proc;
+typedef u64int PTE;
+typedef struct Soc Soc;
+typedef struct Uart Uart;
+typedef struct Ureg Ureg;
+typedef uvlong Tval;
+typedef void KMap;
+
+#pragma incomplete Pcidev
+#pragma incomplete Ureg
+
+#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC (R_MAGIC)
+
+struct Lock
+{
+ ulong key;
+ u32int sr;
+ uintptr pc;
+ Proc* p;
+ Mach* m;
+ int isilock;
+};
+
+struct Label
+{
+ uintptr sp;
+ uintptr pc;
+};
+
+struct FPsave
+{
+ uvlong regs[32][2];
+
+ ulong control;
+ ulong status;
+};
+
+#define KFPSTATE
+
+struct PFPU
+{
+ int fpstate;
+ int kfpstate;
+ FPsave *fpsave;
+ FPsave *kfpsave;
+};
+
+enum
+{
+ FPinit,
+ FPactive,
+ FPinactive,
+ FPprotected,
+
+ /* bits or'd with the state */
+ FPillegal= 0x100,
+};
+
+struct Confmem
+{
+ uintptr base;
+ ulong npage;
+ uintptr limit;
+ uintptr kbase;
+ uintptr klimit;
+};
+
+struct Conf
+{
+ ulong nmach; /* processors */
+ ulong nproc; /* processes */
+ Confmem mem[3]; /* physical memory */
+ ulong npage; /* total physical pages of memory */
+ ulong 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 */
+ int monitor; /* flag */
+};
+
+/*
+ * MMU stuff in Mach.
+ */
+struct MMMU
+{
+ PTE* mmutop; /* first level user page table */
+};
+
+/*
+ * MMU stuff in proc
+ */
+#define NCOLOR 1 /* 1 level cache, don't worry about VCE's */
+
+struct PMMU
+{
+ union {
+ Page *mmufree; /* mmuhead[0] is freelist head */
+ Page *mmuhead[PTLEVELS];
+ };
+ Page *mmutail[PTLEVELS];
+ int asid;
+ uintptr tpidr;
+};
+
+#include "../port/portdat.h"
+
+struct Mach
+{
+ int machno; /* physical id of processor */
+ uintptr splpc; /* pc of last caller to splhi */
+ Proc* proc; /* current process on this processor */
+ /* end of offsets known to asm */
+
+ MMMU;
+
+ PMach;
+
+ int fpstate;
+ FPsave *fpsave;
+
+ int cputype;
+ ulong delayloop;
+
+ int stack[1];
+};
+
+struct
+{
+ char machs[MAXMACH]; /* active CPUs */
+ int exiting; /* shutdown */
+}active;
+
+#define MACHP(n) ((Mach*)MACHADDR(n))
+
+extern register Mach* m; /* R27 */
+extern register Proc* up; /* R26 */
+extern int normalprint;
+
+/*
+ * a parsed plan9.ini line
+ */
+#define NISAOPT 8
+
+struct ISAConf {
+ char *type;
+ uvlong port;
+ int irq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char *opt[NISAOPT];
+};
+
+/*
+ * Horrid. But the alternative is 'defined'.
+ */
+#ifdef _DBGC_
+#define DBGFLG (dbgflg[_DBGC_])
+#else
+#define DBGFLG (0)
+#endif /* _DBGC_ */
+
+int vflag;
+extern char dbgflg[256];
+
+#define dbgprint print /* for now */
+
+/*
+ * hardware info about a device
+ */
+typedef struct {
+ ulong port;
+ int size;
+} Devport;
+
+struct DevConf
+{
+ ulong intnum; /* interrupt number */
+ char *type; /* card type, malloced */
+ int nports; /* Number of ports */
+ Devport *ports; /* The ports themselves */
+};
--- /dev/null
+++ b/fns.h
@@ -1,0 +1,173 @@
+#include "../port/portfns.h"
+
+/* l.s */
+extern void sev(void);
+extern int tas(void *);
+extern int cmpswap(long*, long, long);
+extern void coherence(void);
+extern void idlehands(void);
+extern uvlong vcycles(void);
+#define cycles(ip) *(ip) = vcycles()
+extern int splfhi(void);
+extern void splflo(void);
+extern void touser(uintptr sp);
+extern void forkret(void);
+extern void noteret(void);
+extern void returnto(void*);
+extern void fpon(void);
+extern void fpoff(void);
+extern void fpsaveregs(void*);
+extern void fploadregs(void*);
+extern void hvccall(Ureg*);
+
+extern void setttbr(uintptr pa);
+extern uintptr getfar(void);
+
+extern void flushasidva(uintptr asidva);
+extern void tlbivae1is(uintptr asidva);
+
+extern void flushasidvall(uintptr asidva);
+extern void tlbivale1is(uintptr asidva);
+
+extern void flushasid(uintptr asid);
+extern void tlbiaside1is(uintptr asid);
+
+extern void flushtlb(void);
+extern void tlbivmalle1(void);
+
+extern void flushlocaltlb(void);
+extern void tlbivmalle1(void);
+
+/* cache */
+extern ulong cachesize(int level);
+
+extern void cacheiinvse(void*, int);
+extern void cacheuwbinv(void);
+extern void cacheiinv(void);
+
+extern void cachedwbse(void*, int);
+extern void cacheduwbse(void*, int);
+extern void cachedinvse(void*, int);
+extern void cachedwbinvse(void*, int);
+
+extern void cachedwb(void);
+extern void cachedinv(void);
+extern void cachedwbinv(void);
+
+extern void l2cacheuwb(void);
+extern void l2cacheuinv(void);
+extern void l2cacheuwbinv(void);
+
+/* mmu */
+#define getpgcolor(a) 0
+extern uintptr paddr(void*);
+#define PADDR(a) paddr((void*)(a))
+extern uintptr cankaddr(uintptr);
+extern void* kaddr(uintptr);
+#define KADDR(a) kaddr(a)
+extern void kmapinval(void);
+#define VA(k) ((uintptr)(k))
+extern KMap *kmap(Page*);
+extern void kunmap(KMap*);
+extern uintptr mmukmap(uintptr, uintptr, usize);
+extern void kmapram(uintptr, uintptr);
+extern void* vmap(uvlong, vlong);
+extern void vunmap(void*, vlong);
+extern void mmu1init(void);
+extern void putasid(Proc*);
+
+/* mem */
+extern void mmuidmap(uintptr*);
+extern void mmu0init(uintptr*);
+extern void meminit(void);
+
+/* clock */
+extern void clockinit(void);
+extern void synccycles(void);
+extern void armtimerset(int);
+extern void clockshutdown(void);
+
+/* fpu */
+extern void fpuinit(void);
+extern void fpuprocsetup(Proc*);
+extern void fpuprocfork(Proc*);
+extern void fpuprocsave(Proc*);
+extern void fpuprocrestore(Proc*);
+extern FPsave* fpukenter(Ureg*);
+extern void fpukexit(Ureg*, FPsave*);
+extern void mathtrap(Ureg*);
+
+/* trap */
+extern void trapinit(void);
+extern int userureg(Ureg*);
+extern void evenaddr(uintptr);
+extern void setkernur(Ureg*, Proc*);
+extern void procfork(Proc*);
+extern void procsetup(Proc*);
+extern void procsave(Proc*);
+extern void procrestore(Proc *);
+extern void trap(Ureg*);
+extern void syscall(Ureg*);
+extern void noted(Ureg*, ulong);
+extern void faultarm64(Ureg*);
+extern void dumpstack(void);
+extern void dumpregs(Ureg*);
+
+/* irq */
+extern void intrinit(void);
+extern void intrcpushutdown(void);
+extern void intrsoff(void);
+extern void intrenable(int, void (*)(Ureg*, void*), void*, int, char*);
+extern void intrdisable(int, void (*)(Ureg*, void*), void*, int, char*);
+extern int irq(Ureg*);
+extern void fiq(Ureg*);
+
+/* sysreg */
+extern uvlong sysrd(ulong);
+extern void syswr(ulong, uvlong);
+
+/* uartimx */
+extern void uartconsinit(void);
+
+/* dma */
+extern void dmaflush(int, void*, ulong);
+
+/* main */
+extern char *getconf(char *name);
+extern void setconfenv(void);
+extern void writeconf(void);
+
+extern int isaconfig(char*, int, ISAConf*);
+extern void links(void);
+
+/* ccm */
+extern void setclkgate(char *name, int on);
+extern void setclkrate(char *name, char *source, int freq);
+extern int getclkrate(char *name);
+
+/* gpc */
+extern void powerup(char *dom);
+
+/* lcd */
+extern void lcdinit(void);
+
+/* iomux */
+extern void iomuxpad(char *pads, char *sel, char *cfg);
+extern uint iomuxgpr(int gpr, uint set, uint mask);
+
+/* gpio */
+#define GPIO_PIN(n, m) ((n)<<5 | (m))
+extern void gpioout(uint pin, int set);
+extern int gpioin(uint pin);
+void gpiointrenable(uint pin, int mode, void (*f)(uint pin, void *a), void *a);
+void gpiointrdisable(uint pin);
+
+/* pciqemu */
+extern int pcicfgrw8(int tbdf, int rno, int data, int read);
+extern int pcicfgrw16(int tbdf, int rno, int data, int read);
+extern int pcicfgrw32(int tbdf, int rno, int data, int read);
+extern void pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a);
+extern void pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a);
+
+/* bootargs */
+extern void bootargsinit(void);
--- /dev/null
+++ b/fpu.c
@@ -1,0 +1,289 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#include "ureg.h"
+#include "../arm64/sysreg.h"
+
+/* libc */
+extern ulong getfcr(void);
+extern void setfcr(ulong fcr);
+extern ulong getfsr(void);
+extern void setfsr(ulong fsr);
+
+static FPsave fpsave0;
+
+static void
+fpsave(FPsave *p)
+{
+ p->control = getfcr();
+ p->status = getfsr();
+ fpsaveregs(p->regs);
+ fpoff();
+}
+
+static void
+fprestore(FPsave *p)
+{
+ fpon();
+ setfcr(p->control);
+ setfsr(p->status);
+ fploadregs(p->regs);
+}
+
+static void
+fpinit(void)
+{
+ fprestore(&fpsave0);
+}
+
+void
+fpuinit(void)
+{
+ m->fpstate = FPinit;
+ m->fpsave = nil;
+ fpoff();
+}
+
+static FPsave*
+fpalloc(void)
+{
+ FPsave *save;
+
+ while((save = mallocalign(sizeof(FPsave), 16, 0, 0)) == nil){
+ spllo();
+ resrcwait("no memory for FPsave");
+ splhi();
+ }
+ return save;
+}
+
+static void
+fpfree(FPsave *save)
+{
+ free(save);
+}
+
+
+/*
+ * Protect or save FPU state and setup new state
+ * (lazily in the case of user process) for the kernel.
+ * All syscalls, traps and interrupts (except mathtrap()!)
+ * are handled between fpukenter() and fpukexit(),
+ * so they can use floating point and vector instructions.
+ */
+FPsave*
+fpukenter(Ureg*)
+{
+ if(up == nil){
+ switch(m->fpstate){
+ case FPactive:
+ fpsave(m->fpsave);
+ /* wet floor */
+ case FPinactive:
+ m->fpstate = FPinit;
+ return m->fpsave;
+ }
+ return nil;
+ }
+
+ switch(up->fpstate){
+ case FPactive:
+ up->fpstate = FPprotected;
+ fpoff();
+ /* wet floor */
+ case FPprotected:
+ return nil;
+ }
+
+ switch(up->kfpstate){
+ case FPactive:
+ fpsave(up->kfpsave);
+ /* wet floor */
+ case FPinactive:
+ up->kfpstate = FPinit;
+ return up->kfpsave;
+ }
+ return nil;
+}
+
+void
+fpukexit(Ureg *ureg, FPsave *save)
+{
+ if(up == nil){
+ switch(m->fpstate){
+ case FPactive:
+ fpoff();
+ /* wet floor */
+ case FPinactive:
+ fpfree(m->fpsave);
+ m->fpstate = FPinit;
+ }
+ m->fpsave = save;
+ if(save != nil)
+ m->fpstate = FPinactive;
+ return;
+ }
+
+ if(up->fpstate == FPprotected){
+ if(userureg(ureg)){
+ up->fpstate = FPactive;
+ fpon();
+ }
+ return;
+ }
+
+ switch(up->kfpstate){
+ case FPactive:
+ fpoff();
+ /* wet floor */
+ case FPinactive:
+ fpfree(up->kfpsave);
+ up->kfpstate = FPinit;
+ }
+ up->kfpsave = save;
+ if(save != nil)
+ up->kfpstate = FPinactive;
+}
+
+void
+fpuprocsetup(Proc *p)
+{
+ p->fpstate = FPinit;
+}
+
+void
+fpuprocfork(Proc *p)
+{
+ int s;
+
+ s = splhi();
+ switch(up->fpstate & ~FPillegal){
+ case FPprotected:
+ fpon();
+ /* wet floor */
+ case FPactive:
+ fpsave(up->fpsave);
+ up->fpstate = FPinactive;
+ /* wet floor */
+ case FPinactive:
+ if(p->fpsave == nil)
+ p->fpsave = fpalloc();
+ memmove(p->fpsave, up->fpsave, sizeof(FPsave));
+ p->fpstate = FPinactive;
+ }
+ splx(s);
+}
+
+void
+fpuprocsave(Proc *p)
+{
+ if(p->state == Moribund){
+ if(p->fpstate == FPactive || p->kfpstate == FPactive)
+ fpoff();
+ fpfree(p->fpsave);
+ fpfree(p->kfpsave);
+ p->fpsave = p->kfpsave = nil;
+ p->fpstate = p->kfpstate = FPinit;
+ return;
+ }
+ if(p->kfpstate == FPactive){
+ fpsave(p->kfpsave);
+ p->kfpstate = FPinactive;
+ return;
+ }
+ if(p->fpstate == FPprotected)
+ fpon();
+ else if(p->fpstate != FPactive)
+ return;
+ fpsave(p->fpsave);
+ p->fpstate = FPinactive;
+}
+
+void
+fpuprocrestore(Proc*)
+{
+ /*
+ * when the scheduler switches,
+ * we can discard its fp state.
+ */
+ switch(m->fpstate){
+ case FPactive:
+ fpoff();
+ /* wet floor */
+ case FPinactive:
+ fpfree(m->fpsave);
+ m->fpsave = nil;
+ m->fpstate = FPinit;
+ }
+}
+
+void
+mathtrap(Ureg *ureg)
+{
+ if(!userureg(ureg)){
+ if(up == nil){
+ switch(m->fpstate){
+ case FPinit:
+ m->fpsave = fpalloc();
+ m->fpstate = FPactive;
+ fpinit();
+ break;
+ case FPinactive:
+ fprestore(m->fpsave);
+ m->fpstate = FPactive;
+ break;
+ default:
+ panic("floating point error in irq");
+ }
+ return;
+ }
+
+ if(up->fpstate == FPprotected){
+ fpon();
+ fpsave(up->fpsave);
+ up->fpstate = FPinactive;
+ }
+
+ switch(up->kfpstate){
+ case FPinit:
+ up->kfpsave = fpalloc();
+ up->kfpstate = FPactive;
+ fpinit();
+ break;
+ case FPinactive:
+ fprestore(up->kfpsave);
+ up->kfpstate = FPactive;
+ break;
+ default:
+ panic("floating point error in trap");
+ }
+ return;
+ }
+
+ if(up->fpstate & FPillegal){
+ postnote(up, 1, "sys: floating point in note handler", NDebug);
+ return;
+ }
+ switch(up->fpstate){
+ case FPinit:
+ if(up->fpsave == nil)
+ up->fpsave = fpalloc();
+ up->fpstate = FPactive;
+ fpinit();
+ break;
+ case FPinactive:
+ fprestore(up->fpsave);
+ up->fpstate = FPactive;
+ break;
+ case FPprotected:
+ up->fpstate = FPactive;
+ fpon();
+ break;
+ case FPactive:
+ postnote(up, 1, "sys: floating point error", NDebug);
+ break;
+ }
+}
--- /dev/null
+++ b/init9.c
@@ -1,0 +1,7 @@
+extern void startboot(char*, char**);
+
+void
+bootmain(char *argv0)
+{
+ startboot(argv0, &argv0);
+}
--- /dev/null
+++ b/io.h
@@ -1,0 +1,1 @@
+#define BUSUNKNOWN (-1)
--- /dev/null
+++ b/l.s
@@ -1,0 +1,207 @@
+#include "mem.h"
+
+TEXT _main(SB), $-8
+ MOVD $0, R0
+ MOVD $setSB-KZERO(SB),R2
+
+ MOVD $0x1234567800000000, R11
+ MOVD $0x1, R12
+ MOVD $0x2, R13
+
+ MOVD R8,R13 /* opal BASE */
+ MOVD R9,R14 /* opal entry point */
+ MOVD R3,R15 /* device tree pointer */
+ MOVD R4,R8 /* where _main is now */
+
+ /* Relocate our binary from here to where we want to be */
+ MOVD $_main-KZERO(SB), R9
+ MOVD $etext-KZERO(SB), R10
+ MOVD $0x0, R11
+copy:
+ MOVD (R8), R5
+ MOVD R5, (R9)
+ ADD $8, R8
+ ADD $8, R9
+ CMP R9, R10
+ BNE copy
+
+ ADD $1,R11,R11
+ CMP R11,$0x2
+ BEQ bss
+
+ /* Next part goes to DATA */
+ MOVD $bdata-KZERO(SB), R9
+ MOVD $edata-KZERO(SB), R10
+ BR copy
+
+bss:
+ /* Zero BSS */
+ MOVD R10, R9
+ MOVD $end-KZERO(SB), R10
+bsscopy:
+ CMP R9, R10
+ BEQ done
+ MOVD R0, (R9)
+ ADD $8, R9
+ BR bsscopy
+
+done:
+ MOVD R13, opalsb(SB)
+ MOVD R14, opalep(SB)
+ MOVD R15, devtree(SB)
+
+ /* leap to new location */
+ MOVD $main-KZERO(SB),R11
+ MOVD R11,CTR
+ BL (CTR)
+ MOVD $setSB(SB), R2
+park:
+ BR park
+
+
+/* caller must have arguments in correct registers */
+TEXT opalcall(SB), $0
+ MOVD $opalsb-KZERO(SB), R12
+ MOVD (R12), R12
+ MOVD $opalep-KZERO(SB), R13
+ MOVD (R13), R13
+
+ /* load the shotgun */
+ MOVD R11,R0
+ MOVD R12,R2
+ MOVD R13,CTR
+ BL (CTR)
+
+ /* unload the shotgun */
+ MOVD $0,R0
+ MOVD $setSB(SB),R2
+ RETURN
+
+TEXT opalshutdown(SB), $0
+ MOVD $0,R3
+ MOVD $5,R11
+ BL opalcall(SB)
+ RETURN
+
+TEXT opalconswr(SB), $0
+ MOVD R3,R5
+ MOVD $8(FP),R4
+ MOVD $0,R3
+ MOVD $1,R11
+ BL opalcall(SB)
+ RETURN
+
+TEXT opalconsrd(SB), $0
+ MOVD R3,R5
+ MOVD $8(FP),R4
+ MOVD $0,R3
+ MOVD $2,R11
+ BL opalcall(SB)
+ RETURN
+
+TEXT islo(SB), $0
+ MOVD MSR, R3
+ RLWNM $0, R3, $(MSR_EE>>32), R3
+ RETURN
+
+TEXT splhi(SB), $0
+ MOVD MSR, R3
+ RLWNM $0, R3, $((~MSR_EE)>>32), R4
+ SYNC
+ MOVD R4, MSR
+ SYNC
+ RETURN
+
+TEXT splx(SB), $0
+ MOVD MSR, R4
+ RLWMI $0, R3, $(MSR_EE>>32), R4
+ SYNC
+ MOVD R4, MSR
+ SYNC
+ RETURN
+
+TEXT spllo(SB), $0
+ MOVD MSR, R3
+ MOVD $MSR_EE, R5
+ OR R5, R3, R4
+ SYNC
+ MOVD R4, MSR
+ SYNC
+ RETURN
+
+TEXT coherence(SB), $0
+ EIEIO
+ RETURN
+
+TEXT setlabel(SB), $-8
+ MOVD LR, R31
+ MOVD R1, 0(R3)
+ MOVD R31, 8(R3)
+ MOVD $0, R3
+ RETURN
+
+TEXT gotolabel(SB), $-8
+ MOVD 8(R3), R31
+ MOVD R31, LR
+ MOVD 0(R3), R1
+ MOVD $1, R3
+ RETURN
+
+TEXT returnto(SB), $-8
+ MOVD R3, 0(R1)
+ RETURN
+
+TEXT _tas(SB), $0
+TEXT tas(SB), $0
+ SYNC
+ MOVD R3, R4
+ MOVWZ $0xdeaddead,R5
+tas1:
+ SYNC
+ LWAR (R4), R3
+ CMP R3, $0
+ BNE tas0
+ STWCCC R5, (R4)
+ BNE tas1
+tas0:
+ SYNC
+ ISYNC
+ RETURN
+
+TEXT cas(SB), $0
+TEXT cmpswap(SB), $0
+ SYNC
+ MOVD ov+8(FP), R4
+ MOVD nv+8(FP), R5
+cas1:
+ SYNC
+ LWAR (R3), R4
+ CMP R4, R6
+ BNE cas0
+ STWCCC R5, (R3)
+ BNE cas1
+ SYNC
+ ISYNC
+ MOVD $1, R3
+ RETURN
+cas0:
+ SYNC
+ ISYNC
+ MOVD $0, R3
+ RETURN
+
+TEXT fpsaveregs(SB), $0
+TEXT fpoff(SB), $0
+TEXT fpon(SB), $0
+TEXT fploadregs(SB), $0
+TEXT idlehands(SB), $0
+TEXT vcycles(SB), $0
+TEXT noteret(SB), $0
+ RETURN
+
+DATA opalsb(SB)/8, $0x00
+GLOBL opalsb(SB), $0x8
+DATA opalep(SB)/8, $0x00
+GLOBL opalep(SB), $0x8
+DATA devtree(SB)/8, $0x00
+GLOBL devtree(SB), $0x8
--- /dev/null
+++ b/main.c
@@ -1,0 +1,47 @@
+#include "u.h"
+#include "tos.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "pool.h"
+#include "io.h"
+#include "ureg.h"
+
+void opalshutdown(void);
+void opalconswr(char*,vlong);
+void opalconsrd(char*,vlong);
+
+Conf conf;
+
+void
+exit(int)
+{
+ opalshutdown();
+}
+
+void
+init0(void)
+{
+
+}
+
+char*
+getconf(char *name)
+{
+ return nil;
+}
+
+void
+reboot(void*, void *code, ulong size)
+{
+}
+
+void
+main(void)
+{
+ char *p = "\nPlan 9\n";
+ opalconswr(p, strlen(p));
+ exit(0);
+}
--- /dev/null
+++ b/mem.h
@@ -1,0 +1,155 @@
+/*
+ * 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 */
+
+/*
+ * Sizes:
+ * L0 L1 L2 L3
+ * 4K 2M 1G 512G
+ * 16K 32M 64G 128T
+ * 64K 512M 4T -
+ */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define BY2PG (1ULL<<PGSHIFT) /* bytes per page */
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+
+/* effective virtual address space */
+#define EVASHIFT 42
+#define EVAMASK ((1ULL<<EVASHIFT)-1)
+
+#define PTSHIFT (PGSHIFT-3)
+#define PTLEVELS (((EVASHIFT-PGSHIFT)+PTSHIFT-1)/PTSHIFT)
+#define PTLX(v, l) ((((v) & EVAMASK) >> (PGSHIFT + (l)*PTSHIFT)) & ((1 << PTSHIFT)-1))
+#define PGLSZ(l) (1ULL << (PGSHIFT + (l)*PTSHIFT))
+
+#define PTL1X(v, l) (L1TABLEX(v, l) | PTLX(v, l))
+#define L1TABLEX(v, l) (L1TABLE(v, l) << PTSHIFT)
+#define L1TABLES ((-KSEG0+PGLSZ(2)-1)/PGLSZ(2))
+#define L1TABLE(v, l) (L1TABLES - ((PTLX(v, 2) % L1TABLES) >> (((l)-1)*PTSHIFT)) + (l)-1)
+#define L1TOPSIZE (1ULL << (EVASHIFT - PTLEVELS*PTSHIFT))
+
+#define MAXMACH 16 /* max # cpus system can run */
+#define MACHSIZE (8*KiB)
+
+#define KSTACK (8*KiB)
+#define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */
+#define TRAPFRAMESIZE (38*8)
+
+#define DTBADDR 0x40000000
+
+/*
+ * Address spaces. Kernel, sorted by address.
+ */
+#define KZERO (0xffffffff80000000ull)
+#define KTZERO (KZERO+1*MiB)
+
+#define MACHADDR(n) (KTZERO-((n)+1)*MACHSIZE)
+
+#define UZERO 0ULL /* user segment */
+#define UTZERO (UZERO+0x10000) /* user text start */
+#define USTKTOP ((EVAMASK>>1)-0xFFFF) /* user segment end +1 */
+#define USTKSIZE (16*1024*1024) /* user stack size */
+
+#define BLOCKALIGN 64 /* only used in allocb.c */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BY2SE 4
+#define BY2WD 8
+#define BY2V 8 /* only used in xalloc.c */
+
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 8192
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+#define SHARE_NONE 0
+#define SHARE_OUTER 2
+#define SHARE_INNER 3
+
+#define CACHE_UC 0
+#define CACHE_WB 1
+#define CACHE_WT 2
+#define CACHE_WB_NA 3
+
+#define MA_MEM_WB 0
+#define MA_MEM_WT 1
+#define MA_MEM_UC 2
+#define MA_DEV_nGnRnE 3
+#define MA_DEV_nGnRE 4
+#define MA_DEV_nGRE 5
+#define MA_DEV_GRE 6
+
+#define PTEVALID 1
+#define PTEBLOCK 0
+#define PTETABLE 2
+#define PTEPAGE 2
+
+#define PTEMA(x) ((x)<<2)
+#define PTEAP(x) ((x)<<6)
+#define PTESH(x) ((x)<<8)
+
+#define PTEAF (1<<10)
+#define PTENG (1<<11)
+#define PTEPXN (1ULL<<53)
+#define PTEUXN (1ULL<<54)
+
+#define PTEKERNEL PTEAP(0)
+#define PTEUSER PTEAP(1)
+#define PTEWRITE PTEAP(0)
+#define PTERONLY PTEAP(2)
+#define PTENOEXEC (PTEPXN|PTEUXN)
+
+#define PTECACHED PTEMA(MA_MEM_WB)
+#define PTEWT PTEMA(MA_MEM_WT)
+#define PTEUNCACHED PTEMA(MA_MEM_UC)
+#define PTEDEVICE PTEMA(MA_DEV_nGnRE)
+
+/*
+ * Physical machine information from here on.
+ * PHYS addresses as seen from the power64 cpu.
+ * BUS addresses as seen from peripherals
+ */
+#define PHYSDRAM 0
+
+#define MIN(a, b) ((a) < (b)? (a): (b))
+#define MAX(a, b) ((a) > (b)? (a): (b))
+
+#define BIT(i) (1<<(31-(i))) /* Silly backwards register bit numbering scheme */
+#define SBIT(n) ((ushort)1<<(15-(n)))
+#define RBIT(b,n) (1<<(8*sizeof(n)-1-(b)))
+
+/*
+ * Bit encodings for Machine State Register (MSR)
+ */
+#define MSG_SF BIT(0) /* 64 mode */
+#define MSR_HV BIT(3) /* Hypervisor State */
+#define MSR_VEC BIT(38) /* Vector Enable */
+#define MSR_VSX BIT(40) /* VSX enable */
+#define MSR_SEC BIT(41) /* Secure mode enable */
+#define MSR_EE BIT(48) /* External Interrupt enable */
+#define MSR_PR BIT(49) /* Supervisor/User privilege */
+#define MSR_FP BIT(50) /* Floating Point enable */
+#define MSR_ME BIT(51) /* Machine Check enable */
+#define MSR_FE0 BIT(52) /* Floating Exception mode 0 */
+#define MSR_SE BIT(53) /* Single Step (optional) */
+#define MSR_BE BIT(54) /* Branch Trace (optional) */
+#define MSR_FE1 BIT(55) /* Floating Exception mode 1 */
+#define MSR_IR BIT(58) /* Instruction MMU enable */
+#define MSR_DR BIT(59) /* Data MMU enable */
+#define MSR_PM BIT(61) /* Performance Monitor marked mode (604e specific) */
+#define MSR_RI BIT(62) /* Recoverable Exception */
+#define MSR_LE BIT(63) /* Little-Endian enable */
+/* SRR1 bits for TLB operations */
+#define MSR_SR0 0xf0000000 /* Saved bits from CR register */
+#define MSR_KEY BIT(12) /* Copy of Ks or Kp bit */
+#define MSR_IMISS BIT(13) /* It was an I miss */
+#define MSR_WAY BIT(14) /* TLB set to be replaced */
+#define MSR_STORE BIT(15) /* Miss caused by a store */
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,103 @@
+CONF=nv
+CONFLIST=nv
+
+loadaddr=0xffffffff80100000
+
+objtype=power64
+</$objtype/mkfile
+p=9
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+
+PORT=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ edf.$O\
+ fault.$O\
+ mul64fract.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ rdb.$O\
+ rebootcmd.$O\
+ segment.$O\
+ syscallfmt.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+ userinit.$O\
+
+OBJ=\
+ l.$O\
+ main.$O\
+ clock.$O\
+ fpu.$O\
+ mmu.$O\
+ trap.$O\
+ random.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+# HFILES=
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libip.a\
+ /$objtype/lib/libsec.a\
+ /$objtype/lib/libmp.a\
+ /$objtype/lib/libc.a\
+# /$objtype/lib/libdtracy.a\
+
+9:V: $p$CONF $p$CONF.elf
+
+$p$CONF:D: $OBJ $CONF.$O $LIB
+ $LD -o $target -T$loadaddr -R0x100000 -l $prereq
+ size $target
+
+$p$CONF.elf:D: $OBJ $CONF.$O $LIB
+ $LD -o $target -H 6 -T$loadaddr -R0x100000 -l $prereq
+
+$OBJ: $HFILES
+
+install:V: /$objtype/$p$CONF
+
+/$objtype/$p$CONF:D: $p$CONF
+ cp -x $p$CONF /$objtype/
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+initcode.out: init9.$O initcode.$O /$objtype/lib/libc.a
+ $LD -l -R1 -s -o $target $prereq
+
+$CONF.clean:
+ rm -rf $p$CONF errstr.h $CONF.c boot$CONF.c
+
+test.iso: 9nv.elf
+ rm -fr tmp $target
+ mkdir -p tmp/
+ mkdir tmp/live
+ @{
+ echo 'name 9front'
+ echo 'image /9nv.elf'
+ } > tmp/petitboot.conf
+ cp 9nv.elf tmp/
+ disk/mk9660 -p <{echo +} -s tmp $target
+ rm -fr tmp
--- /dev/null
+++ b/mmu.c
@@ -1,0 +1,151 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mmu1init(void)
+{
+}
+
+uintptr
+paddr(void *va)
+{
+ if((uintptr)va >= KZERO)
+ return (uintptr)va-KZERO;
+ panic("paddr: va=%#p pc=%#p", va, getcallerpc(&va));
+}
+
+uintptr
+cankaddr(uintptr pa)
+{
+ if(pa < (uintptr)-KZERO)
+ return -KZERO - pa;
+ return 0;
+}
+
+void*
+kaddr(uintptr pa)
+{
+ if(pa < (uintptr)-KZERO)
+ return (void*)(pa + KZERO);
+ panic("kaddr: pa=%#p pc=%#p", pa, getcallerpc(&pa));
+}
+
+static void*
+kmapaddr(uintptr pa)
+{
+ return nil;
+}
+
+KMap*
+kmap(Page *p)
+{
+ return kmapaddr(p->pa);
+}
+
+void
+kunmap(KMap*)
+{
+}
+
+void
+kmapinval(void)
+{
+}
+
+static void*
+rampage(void)
+{
+ uintptr pa;
+
+ if(conf.npage)
+ return mallocalign(BY2PG, BY2PG, 0, 0);
+
+ pa = conf.mem[0].base;
+ assert((pa % BY2PG) == 0);
+ conf.mem[0].base += BY2PG;
+ return KADDR(pa);
+}
+
+static void
+l1map(uintptr va, uintptr pa, uintptr pe, uintptr attr)
+{
+}
+
+void
+kmapram(uintptr base, uintptr limit)
+{
+}
+
+uintptr
+mmukmap(uintptr va, uintptr pa, usize size)
+{
+ return 0;
+}
+
+void*
+vmap(uvlong pa, vlong size)
+{
+ return nil;
+}
+
+void
+vunmap(void *, vlong)
+{
+}
+
+static uintptr*
+mmuwalk(uintptr va, int level)
+{
+ return nil;
+}
+
+static Proc *asidlist[256];
+
+static int
+allocasid(Proc *p)
+{
+ return 0;
+}
+
+static void
+freeasid(Proc *p)
+{
+}
+
+void
+putasid(Proc *p)
+{
+}
+
+void
+putmmu(uintptr va, uintptr pa, Page *pg)
+{
+}
+
+static void
+mmufree(Proc *p)
+{
+}
+
+void
+mmuswitch(Proc *p)
+{
+}
+
+void
+mmurelease(Proc *p)
+{
+}
+
+void
+flushmmu(void)
+{
+}
+
+void
+checkmmu(uintptr, uintptr)
+{
+}
--- /dev/null
+++ b/nv
@@ -1,0 +1,17 @@
+dev
+ root
+ cons
+ env
+ mnt
+ proc
+ shr
+ srv
+ swap
+ uart
+port
+ int cpuserver = 0;
+bootdir
+ /$objtype/bin/paqfs
+ /$objtype/bin/auth/factotum
+ bootfs.paq
+ boot
--- /dev/null
+++ b/trap.c
@@ -1,0 +1,304 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../port/systab.h"
+
+#include <tos.h>
+#include "ureg.h"
+
+int (*buserror)(Ureg*);
+
+/* SPSR bits user can modify */
+#define USPSRMASK (0xFULL<<28)
+
+void
+trapinit(void)
+{
+}
+
+static char *traps[64] = {
+ [0x00] "sys: trap: unknown",
+ [0x01] "sys: trap: WFI or WFE instruction execution",
+ [0x0E] "sys: trap: illegal execution state",
+ [0x18] "sys: trap: illegal MSR/MRS access",
+ [0x22] "sys: trap: misaligned pc",
+ [0x26] "sys: trap: stack pointer misaligned",
+ [0x30] "sys: breakpoint",
+ [0x32] "sys: software step",
+ [0x34] "sys: watchpoint",
+ [0x3C] "sys: breakpoint",
+};
+
+void
+trap(Ureg *ureg)
+{
+}
+
+void
+syscall(Ureg *ureg)
+{
+ vlong startns, stopns;
+ uintptr sp, ret;
+ ulong scallnr;
+ int i, s;
+ char *e;
+
+ if(!kenter(ureg))
+ panic("syscall from kernel");
+ fpukenter(ureg);
+
+ m->syscall++;
+ up->insyscall = 1;
+ up->pc = ureg->pc;
+
+ sp = ureg->sp;
+ up->scallnr = scallnr = ureg->r0;
+ spllo();
+
+ up->nerrlab = 0;
+ startns = 0;
+ ret = -1;
+ if(!waserror()){
+ if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+ evenaddr(sp);
+ }
+ up->s = *((Sargs*) (sp + BY2WD));
+
+ if(up->procctl == Proc_tracesyscall){
+ syscallfmt(scallnr, ureg->pc, (va_list) up->s.args);
+ s = splhi();
+ up->procctl = Proc_stopme;
+ procctl();
+ splx(s);
+ startns = todget(nil);
+ }
+
+ if(scallnr >= nsyscall || systab[scallnr] == nil){
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+ up->psstate = sysctab[scallnr];
+ ret = systab[scallnr]((va_list)up->s.args);
+ poperror();
+ }else{
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ }
+ if(up->nerrlab){
+ print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
+ for(i = 0; i < NERR; i++)
+ print("sp=%#p pc=%#p\n", up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+ ureg->r0 = ret;
+ if(up->procctl == Proc_tracesyscall){
+ stopns = todget(nil);
+ sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
+ s = splhi();
+ up->procctl = Proc_stopme;
+ procctl();
+ splx(s);
+ }
+ up->insyscall = 0;
+ up->psstate = 0;
+
+ if(scallnr == NOTED){
+ noted(ureg, *((ulong*) up->s.args));
+ /*
+ * normally, syscall() returns to forkret()
+ * not restoring general registers when going
+ * to userspace. to completely restore the
+ * interrupted context, we have to return thru
+ * noteret(). we override return pc to jump to
+ * to it when returning form syscall()
+ */
+ returnto(noteret);
+
+ splhi();
+ up->fpstate &= ~FPillegal;
+ }
+ else
+ splhi();
+
+ if(scallnr != RFORK && (up->procctl || up->nnote))
+ notify(ureg);
+
+ if(up->delaysched){
+ sched();
+ splhi();
+ }
+
+ kexit(ureg);
+ fpukexit(ureg, nil);
+}
+
+int
+notify(Ureg *ureg)
+{
+ uintptr sp;
+ char *msg;
+
+ if(up->procctl)
+ procctl();
+ if(up->nnote == 0)
+ return 0;
+
+ spllo();
+ qlock(&up->debug);
+ msg = popnote(ureg);
+ if(msg == nil){
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ sp = ureg->sp;
+ sp -= 256; /* debugging: preserve context causing problem */
+ sp -= sizeof(Ureg);
+ sp = STACKALIGN(sp);
+
+ if(!okaddr((uintptr)up->notify, 1, 0)
+ || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)
+ || ((uintptr) up->notify & 3) != 0
+ || (sp & 7) != 0){
+ qunlock(&up->debug);
+ pprint("suicide: bad address in notify: handler=%#p sp=%#p\n",
+ up->notify, sp);
+ pexit("Suicide", 0);
+ }
+
+ memmove((Ureg*)sp, ureg, sizeof(Ureg));
+ *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
+ up->ureg = (void*)sp;
+ sp -= BY2WD+ERRMAX;
+ memmove((char*)sp, msg, ERRMAX);
+ sp -= 3*BY2WD;
+ *(uintptr*)(sp+2*BY2WD) = sp+3*BY2WD;
+ *(uintptr*)(sp+1*BY2WD) = (uintptr)up->ureg;
+ ureg->r0 = (uintptr) up->ureg;
+ ureg->sp = sp;
+ ureg->pc = (uintptr) up->notify;
+ ureg->cause = 0;
+ qunlock(&up->debug);
+
+ splhi();
+ fpuprocsave(up);
+ up->fpstate |= FPillegal;
+ return 1;
+}
+
+void
+noted(Ureg *ureg, ulong arg0)
+{
+}
+
+static void
+faultnote(Ureg *ureg, char *access, uintptr addr)
+{
+}
+
+int
+userureg(Ureg* ureg)
+{
+ return 0;
+}
+
+uintptr
+userpc(void)
+{
+ Ureg *ur = up->dbgreg;
+ return ur->pc;
+}
+
+uintptr
+dbgpc(Proc *)
+{
+ Ureg *ur = up->dbgreg;
+ if(ur == nil)
+ return 0;
+ return ur->pc;
+}
+
+void
+procfork(Proc *p)
+{
+ fpuprocfork(p);
+ p->tpidr = up->tpidr;
+}
+
+void
+procsetup(Proc *p)
+{
+}
+
+void
+procsave(Proc *p)
+{
+}
+
+void
+procrestore(Proc *p)
+{
+}
+
+void
+kprocchild(Proc *p, void (*entry)(void))
+{
+}
+
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+}
+
+uintptr
+execregs(uintptr entry, ulong ssize, ulong nargs)
+{
+ return 0;
+}
+
+void
+evenaddr(uintptr addr)
+{
+}
+
+void
+callwithureg(void (*f) (Ureg *))
+{
+}
+
+void
+setkernur(Ureg *ureg, Proc *p)
+{
+}
+
+void
+setupwatchpts(Proc*, Watchpt*, int)
+{
+}
+
+void
+setregisters(Ureg* ureg, char* pureg, char* uva, int n)
+{
+}
+
+static void
+dumpstackwithureg(Ureg *ureg)
+{
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(dumpstackwithureg);
+}
+
+void
+dumpregs(Ureg *ureg)
+{
+}