shithub: powernv

Download patch

ref: a691c9111a69257e206ce895d35396d0f6225929
author: Jacob Moody <moody@posixcafe.org>
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)
+{
+}