Browse Source

riscv: pull in working riscv files

This won't break any builds but this is the 'working riscv kernel'
set of files. It's essentially a squash.

Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Ronald G. Minnich 3 years ago
parent
commit
fec95fd4d9

+ 25 - 0
sys/src/9/riscv/_spl.S

@@ -0,0 +1,25 @@
+/* these are intended to be called from library functions ONLY.
+ * at some point, we can make it all more efficient, but for now,
+ * let's make it correct.
+ */
+
+#define sstatus 0x100
+#define siebitmask 2
+/* int _splhi() */
+.globl _splhi
+_splhi:
+	li	a0, siebitmask
+	csrrc	a0, sstatus, a0
+	ret
+
+/* int _spllo() */
+.globl _spllo
+_spllo:
+	li	a0, siebitmask
+	csrrs	a0, sstatus, a0
+	ret
+
+/* what a hack. Purely a marker for profiling.*/
+.globl spldone
+spldone:
+	ret

+ 3 - 3
sys/src/9/riscv/acore.c

@@ -123,12 +123,12 @@ acsched(void)
 void
 acmmuswitch(void)
 {
-	extern Page mach0pml4;
+	extern Page mach0root;
 
-	DBG("acmmuswitch mpl4 %#p mach0pml4 %#p m0pml4 %#p\n", machp()->MMU.pml4->pa, mach0pml4.pa, sys->machptr[0]->MMU.pml4->pa);
+	DBG("acmmuswitch mpl4 %#p mach0root %#p m0root %#p\n", machp()->MMU.root->pa, mach0root.pa, sys->machptr[0]->MMU.root->pa);
 
 
-	rootput(machp()->MMU.pml4->pa);
+	rootput(machp()->MMU.root->pa);
 }
 
 /*

+ 23 - 4
sys/src/9/riscv/arch.c

@@ -20,6 +20,7 @@
 #include "fns.h"
 #include "../port/error.h"
 #include "ureg.h"
+#include "encoding.h"
 
 /* the rules are different for different compilers. We need to define up. */
 // Initialize it to force it into data.
@@ -57,7 +58,7 @@ decref(Ref *r)
 
 void fpuprocrestore(Proc *p)
 {
-	panic("fpuprocrestore");
+	if (0)print("NOT DOING fpuprocrestore");
 }
 
 void
@@ -76,7 +77,7 @@ procrestore(Proc *p)
 void
 fpuprocsave(Proc *p)
 {
-	panic("fpuprocsave");
+	print("fpuprocsave -- NEED TO IMPLEMENT");
 }
 
 /*
@@ -131,8 +132,26 @@ kprocchild(Proc* p, void (*func)(void*), void* arg)
 void
 idlehands(void)
 {
-/*	if(machp()->NIX.nixtype != NIXAC)
-	halt();*/
+	uint32_t sip = 0;
+	int i;
+	extern uint64_t *mtimecmp;
+	extern uint64_t *mtime;
+	//print("idlehands, mtime is 0x%llx mtimecmp is 0x%llx\n", *mtime, *mtimecmp);
+	//print("spin waiting for an interrupt or until mtimecmp passes mtime. \n");
+	/* toolchain is broken. Again. Puts an sret in for a wfi. Bad idea.
+	if(machp()->NIX.nixtype != NIXAC)
+		__asm__ __volatile__("wfi\n");
+	if (*mtimecmp < *mtime)
+		timerset(0);
+	 */
+	sip = (uint32_t)read_csr(sip);
+	for(i = 0; *mtimecmp < *mtime; i++) {
+		if (sip & 0x666)
+			break;
+		sip = (uint32_t)read_csr(sip);
+	}
+	//print("idlehands, mtime is 0x%llx mtimecmp is 0x%llx\n", *mtime, *mtimecmp);
+	//print("Leaving idlehands. sip is 0x%x, i is %d\n", sip, i);
 }
 
 #if 0

+ 1 - 1
sys/src/9/riscv/archriscv.c

@@ -25,7 +25,7 @@ cpuiddump(void)
 int64_t
 archhz(void)
 {
-	return 1024*1024*1024ULL;
+	return 1000*1000*1000*2ULL;
 }
 
 int

+ 19 - 9
sys/src/9/riscv/asm.c

@@ -18,9 +18,9 @@
 #include "dat.h"
 #include "fns.h"
 
-#undef DBG
+//#undef DBG
 void msg(char *);
-#define DBG(fmt, ...) msg(fmt)
+//#define DBG msg
 /*
  * Address Space Map.
  * Low duty cycle.
@@ -92,7 +92,7 @@ asmfree(uintmem addr, uintmem size, int type)
 {
 	Asm *np, *pp, **ppp;
 
-	DBG("asmfree: %#P@%#P, type %d\n", size, addr, type);
+	DBG("asmfree: %#p@%#p, type 0x%x\n", size, addr, type);
 	if(size == 0)
 		return 0;
 
@@ -157,7 +157,8 @@ asmalloc(uintmem addr, uintmem size, int type, int align)
 	uintmem a, o;
 	Asm *assem, *pp;
 
-	DBG("asmalloc: %#P@%#P, type %d\n", size, addr, type);
+	DBG("asmalloc: %p@%p, type %d\n", size, addr, type);
+//msg("before asmlock\n");
 	lock(&asmlock);
 //msg("after lock\n");
 	for(pp = nil, assem = asmlist; assem != nil; pp = assem, assem = assem->next){
@@ -331,7 +332,7 @@ asmmeminit(void)
 {
 	int i, l;
 	Asm* assem;
-	PTE *pte, *pml4;
+	PTE *pte, *root;
 	uintptr va;
 	uintmem hi, lo, mem, nextmem, pa;
 #ifdef ConfCrap
@@ -342,6 +343,14 @@ asmmeminit(void)
 
 	if((pa = mmuphysaddr(sys->vmunused)) == ~0)
 		panic("asmmeminit 1");
+	// vmunmapped is the START of unmapped memory (there is none on riscv yet).
+	// it is the END of mapped memory we have not used.
+	// vmunused is the START of mapped memory that is not used and the END
+	// of memory that is used.
+	// This code falls apart if sys->vmend - sys->vmunmapped is 0.
+	// The goal is to map memory not mapped. But it's all mapped.
+	root = UINT2PTR(machp()->MMU.root->va);
+#if 0
 	pa += sys->vmunmapped - sys->vmunused;
 	mem = asmalloc(pa, sys->vmend - sys->vmunmapped, 1, 0);
 	if(mem != pa)
@@ -350,14 +359,14 @@ asmmeminit(void)
 
 	/* assume already 2MiB aligned*/
 	assert(ALIGNED(sys->vmunmapped, 2*MiB));
-	pml4 = UINT2PTR(machp()->MMU.pml4->va);
 	while(sys->vmunmapped < sys->vmend){
-		l = mmuwalk(pml4, sys->vmunmapped, 1, &pte, asmwalkalloc);
+		l = mmuwalk(root, sys->vmunmapped, 1, &pte, asmwalkalloc);
 		DBG("%#p l %d\n", sys->vmunmapped, l);
 		*pte = pa|PteRW|PteP;
 		sys->vmunmapped += 2*MiB;
 		pa += 2*MiB;
 	}
+#endif
 
 #ifdef ConfCrap
 	cx = 0;
@@ -370,7 +379,7 @@ asmmeminit(void)
 			DBG("Skipping, it's not AsmMEMORY or AsmRESERVED\n");
 			continue;
 		}
-		va = KSEG2+assem->addr;
+		va = (uintptr_t)kseg2+assem->addr;
 		DBG("asm: addr %#P end %#P type %d size %P\n",
 			assem->addr, assem->addr+assem->size,
 			assem->type, assem->size);
@@ -389,9 +398,10 @@ asmmeminit(void)
 					continue;
 				/* This page fits entirely within the range. */
 				/* Mark it a usable */
-				if((l = mmuwalk(pml4, va, i, &pte, asmwalkalloc)) < 0)
+				if((l = mmuwalk(root, va, i, &pte, asmwalkalloc)) < 0)
 					panic("asmmeminit 3");
 
+				//print("ASMMEMINIT pte is %p\n", pte);
 				if (assem->type == AsmMEMORY)
 					*pte = mem|PteRW|PteP;
 				else

+ 164 - 9
sys/src/9/riscv/assembly.S

@@ -1,26 +1,93 @@
+# main has to be in assembly because there's not telling
+# what stack firmware has set up. It calls the
+# bsp function with stack in a0 and configstring
+# pointer in a1.
+.text
+.globl bsp
+.globl m0
+.globl m0stack
+.globl main
+main:
+	csrw sscratch, x0
+	mv	a3, a0
+        lui     a5,%hi(bsp)
+        add     a5,a5,%lo(bsp)
+        mv      a0,a5
+	//li	a1, $m0
+        lui     a5,%hi(m0)
+        add     a5,a5,%lo(m0)
+        mv      a1,a5
+	//li	a2, $m0stack
+        lui     a5,%hi(m0stack)
+        add     a5,a5,%lo(m0stack)
+	li	a6, 32768
+	add 	a5, a5, a6
+        mv      a2,a5
+	mv	tp, a1
+	mv	ra,a0
+	mv	sp, a2
+	mv 	a0, a2
+	mv	a1, a3
+	ret
 # startmach starts a function after setting up the mach
 # pointer. The function is in a0, the mach pointer in a1.
 .globl startmach
-startmach: 
-	csrw	sscratch, a1
+startmach:
+	csrw sscratch, x0
+	mv	tp, a1
 	mv	ra,a0
+	mv	sp, a2
+	mv 	a0, a2
 	ret
 
 .globl machp
 machp:
-	csrr	a0,sscratch
+	mv	a0,tp
 	ret
 
+
 /*
  * Label consists of a stack pointer and a programme counter
  * 0(%rdi) is the SP, 8(%rdi) is the PC
  */
 .global gotolabel
 gotolabel:
-	LD	sp,0(a0)
-	LD	x2,16(a0)
+	LD	sp,0(a0) // X14
+	LD	s0,16(a0) // X2
+	// X0 is zero
+	// X1 and X2 are done.
+	LD x3, 48(a0)
+	// Don't restore X4, that's reserved for Mach *
+	//LD x4, 56(a0)
+	LD x5, 64(a0)
+	LD x6, 72(a0)
+	LD x7, 80(a0)
+	LD x8, 88(a0)
+	LD x9, 96(a0)
+	//LD x10, 104(a0) this is a0
+	LD x11, 112(a0)
+	LD x12, 120(a0)
+	LD x13, 128(a0)
+	// X14 done already
+	LD x15, 144(a0)
+	LD x16, 152(a0)
+	LD x17, 160(a0)
+	LD x18, 168(a0)
+	LD x19, 176(a0)
+	LD x20, 184(a0)
+	LD x21, 192(a0)
+	LD x22, 200(a0)
+	LD x23, 208(a0)
+	LD x24, 216(a0)
+	LD x25, 224(a0)
+	LD x26, 232(a0)
+	LD x27, 240(a0)
+	LD x28, 248(a0)
+	LD x29, 256(a0)
+	LD x30, 264(a0)
+	LD x30, 272(a0)
 	LD	a0,8(a0)
-	MV	ra,a0
+	MV	ra,a0 // X1 (non zero by definition I hope.
 	RET
 
 	/* save all registers on this stack, the save stack
@@ -28,13 +95,101 @@ gotolabel:
 	*/
 .global slim_setlabel
 slim_setlabel:
-	SD	sp,0(a0)
-	SD	ra,8(a0)
-	SD	x2,16(a0)
+	// don't save X0 of course. Or x31
+	/* not so slim! */
+	SD	sp,0(a0) // X14
+	SD	ra,8(a0) // X1
+	SD	s0,16(a0) // X2
+	// X0 is zero
+	// X1 and X2 are done.
+	sd x3, 48(a0)
+	sd x4, 56(a0)
+	sd x5, 64(a0)
+	sd x6, 72(a0)
+	sd x7, 80(a0)
+	sd x8, 88(a0)
+	sd x9, 96(a0)
+	sd x10, 104(a0)
+	sd x11, 112(a0)
+	sd x12, 120(a0)
+	sd x13, 128(a0)
+	// X14 done already
+	sd x15, 144(a0)
+	sd x16, 152(a0)
+	sd x17, 160(a0)
+	sd x18, 168(a0)
+	sd x19, 176(a0)
+	sd x20, 184(a0)
+	sd x21, 192(a0)
+	sd x22, 200(a0)
+	sd x23, 208(a0)
+	sd x24, 216(a0)
+	sd x25, 224(a0)
+	sd x26, 232(a0)
+	sd x27, 240(a0)
+	sd x28, 248(a0)
+	sd x29, 256(a0)
+	sd x30, 264(a0)
+	sd x31, 272(a0)
+	mv	a0,zero
 	RET
 
 
+.globl stack
+stack:
+	mv a0, sp
+	ret
+#if 0
 .globl rdtsc
 rdtsc:
 	RDCYCLE a0
 	RET
+#endif
+/* set up uregs, then jump to a0 from uregs */
+.globl touser
+touser:
+	csrw sscratch, tp
+	LD	sp,8(a0) // X14
+	LD	s0,16(a0) // X2
+	// X0 is zero
+	// X1 and X2 are done.
+	LD x3, 48(a0)
+	LD x4, 56(a0)
+	LD x5, 64(a0)
+	LD x6, 72(a0)
+	LD x7, 80(a0)
+	LD x8, 88(a0)
+	LD x9, 96(a0)
+	// a0 and a1 are restored below.
+
+	LD x12, 120(a0)
+	LD x13, 128(a0)
+	// X14 done already
+	LD x15, 144(a0)
+	LD x16, 152(a0)
+	LD x17, 160(a0)
+	LD x18, 168(a0)
+	LD x19, 176(a0)
+	LD x20, 184(a0)
+	LD x21, 192(a0)
+	LD x22, 200(a0)
+	LD x23, 208(a0)
+	LD x24, 216(a0)
+	LD x25, 224(a0)
+	LD x26, 232(a0)
+	LD x27, 240(a0)
+	LD x28, 248(a0)
+	LD x29, 256(a0)
+	LD x30, 264(a0)
+	LD x30, 272(a0)
+	LD	a1,0(a0)
+	/* Jump to a0 in S-mode */
+	//csrr t0, mstatus
+	//li t1, ~(1<<8) // clear SPP
+	//and t0, t0, t1
+	//csrw mstatus, t0
+	csrw sepc, a1
+	LD a1, 112(a0)
+	LD a0, 104(a0)
+	.long 0x10200073
+	sret

+ 56 - 0
sys/src/9/riscv/backtrace.c

@@ -0,0 +1,56 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+int backtrace_list(uintptr_t pc, uintptr_t fp, uintptr_t *pcs, size_t nr_slots)
+{
+	size_t nr_pcs = 0;
+	while (fp && nr_pcs < nr_slots) {
+		/* could put some sanity checks in here... */
+		pcs[nr_pcs++] = pc;
+		//iprint("PC %p FP %p\n", pc, fp);
+		if (fp < KTZERO)
+			break;
+		/* PC becomes the retaddr - 1.  the -1 is to put our PC back inside the
+		 * function that called us.  this was necessary in case we called as the
+		 * last instruction in a function (would have to never return).  not
+		 * sure how necessary this still is. */
+		pc = *(uintptr_t*)(fp + sizeof(uintptr_t)) - 1;
+		fp = *(uintptr_t*)fp;
+	}
+	return nr_pcs;
+}
+
+#if 0
+void backtrace_frame(uintptr_t eip, uintptr_t ebp)
+{
+	char *func_name;
+	#define MAX_BT_DEPTH 20
+	uintptr_t pcs[MAX_BT_DEPTH];
+	size_t nr_pcs = backtrace_list(eip, ebp, pcs, MAX_BT_DEPTH);
+
+	for (int i = 0; i < nr_pcs; i++) {
+		func_name = get_fn_name(pcs[i]);
+		print("#%02d [<%p>] in %s\n", i + 1,  pcs[i], func_name);
+		kfree(func_name);
+	}
+}
+
+void backtrace(void)
+{
+	uintptr_t ebp, eip;
+	ebp = read_bp();
+	/* retaddr is right above ebp on the stack.  we subtract an additional 1 to
+	 * make sure the eip we get is actually in the function that called us.
+	 * i had a couple cases early on where call was the last instruction in a
+	 * function, and simply reading the retaddr would point into another
+	 * function (the next one in the object) */
+	eip = *(uintptr_t*)(ebp + sizeof(uintptr_t)) - 1;
+	/* jump back a frame (out of backtrace) */
+	ebp = *(uintptr_t*)ebp;
+	printk("Stack Backtrace on Core %d:\n", core_id());
+	backtrace_frame(eip, ebp);
+}
+#endif

+ 14 - 6
sys/src/9/riscv/build.json

@@ -5,10 +5,10 @@
 		],
 		"Include": [
 			"core.json",
-			"../port/riscvport.json"
+			"../ip/ip.json",
+			"../port/port.json"
 		],
 		"IncludeSomedayWhenRISCVgetsvirtio": [
-			"../ip/ip.json",
 			"../port/port.json"
 		],
 		"Kernel": {
@@ -27,6 +27,7 @@
 					"cons",
 					"dup",
 					"env",
+				        "ip",
 					"mnt",
 					"mntn",
 					"pipe",
@@ -38,7 +39,7 @@
 					"uart",
 					"ws"
 				],
-				"NoIp": [
+				"Ip": [
 					"tcp",
 					"udp",
 					"ipifc",
@@ -46,13 +47,21 @@
 					"icmp6",
 					"gre"
 				],
+				"Link": [
+					"ethermedium",
+					"loopbackmedium",
+					"netdevmedium"
+				],
 				"NoUart": [
 					"pci"
 				]
 			},
-			"NoRamfiles": {
+		        "#RamFiles": [
+				"boot: /sys/src/9/boot/bootcpu.elf.out"
+			    ],
+			"Ramfiles": {
 				"bind": "/$ARCH/bin/bind",
-				"boot": "/sys/src/9/boot/bootcpu.elf.out",
+				"boot": "/$ARCH/bin/kiss",
 				"cat": "/$ARCH/bin/cat",
 				"date": "/$ARCH/bin/date",
 				"echo": "/$ARCH/bin/echo",
@@ -65,7 +74,6 @@
 				"ps": "/$ARCH/bin/ps",
 				"ed": "/$ARCH/bin/ed",
 				"rcmain": "/rc/lib/rcmain",
-				"screenconsole": "/$ARCH/bin/aux/screenconsole",
 				"srv": "/$ARCH/bin/srv"
 			},
 			"Systab": "/sys/src/libc/9syscall/sys.h"

+ 13 - 15
sys/src/9/riscv/core.json

@@ -1,6 +1,7 @@
 {
 	"core": {
 		"Cflags": [
+			"-mcmodel=medany",
 			"-O0",
 			"-static",
 			"-ffreestanding",
@@ -21,13 +22,16 @@
 			"-I", "/sys/src/libc/9syscall"
 		],
 	    "Libs": [
-			"/$ARCH/lib/klibc.a"
+			"/$ARCH/lib/klibc.a",
+                        "/$ARCH/lib/klibip.a",
+			"/$ARCH/lib/klibsec.a"
 		],
 		"Oflags": [
 			"-z",
 			"max-page-size=0x1000",
 			"-nostdlib",
 			"-g",
+			"--no-relax",
 			"-T",
 			"kernel.ld"
 		],
@@ -40,35 +44,29 @@
 			"../boot/bootconf.json",
 			"inith.json"
 		],
-	    "MissingSourceFiles": [
-		        "acore.c",
-			"archriscv.c",
-		        "coreboot.c",
-			"devarch.c",
-			"memory.c",
-			"mmu.c",
-			"mp.c",
-			"physalloc.c",
-			"systab.c",
-			"tcore.c",
-			"trap.c"
-		],
 		"SourceFiles": [
 			"assembly.S",
 			"arch.c",
+			"archriscv.c",
 			"asm.c",
 		        "acore.c",
-			"archriscv.c",
+			"backtrace.c",
+			"coreboot.c",
 			"ctype.c",
 			"devarch.c",
 			"main.c",
 			"map.c",
+			"memory.c",
 			"mmu.c",
 			"physalloc.c",
 			"qmalloc.c",
+			"spl.c",
+			"_spl.S",
 			"syscall.c",
 			"systab.c",
 		        "tcore.c",
+		        "trap.c",
+		        "trapentry.S",
 			"uart.c"
 		]
 	}

+ 43 - 0
sys/src/9/riscv/coreboot.c

@@ -0,0 +1,43 @@
+/*
+ * This file is part of the libpayload project.
+
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009 coresystems GmbH
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "coreboot.h"
+
+/* this implements the architecture-dependent call needed for port/devcoreboot.c */
+int get_coreboot_info(struct sysinfo_t *info)
+{
+	return -1;
+}

+ 10 - 4
sys/src/9/riscv/dat.h

@@ -38,7 +38,7 @@ typedef struct Vctl Vctl;
 
 /*
  * Conversion for Ureg to gdb reg. This avoids a lot of nonsense
- * in the outside world. TODO. 
+ * in the outside world. TODO.
  */
 enum regnames {
 	GDB_IP,
@@ -82,6 +82,7 @@ struct Label
 	uintptr_t	sp;
 	uintptr_t	pc;
 	uintptr_t       fp;
+	uintptr_t	x[32];
 };
 
 struct Fxsave {
@@ -168,11 +169,11 @@ struct NIX
  */
 struct MMMU
 {
-	uintptr_t FaultingAddress;
-	Page*	pml4;			/* root for this processor */
+	uintptr_t badaddr;
+	Page*   root;			/* root for this processor */
 	PTE*	pmap;			/* unused as of yet */
 
-	Page	pml4kludge;		/* NIX KLUDGE: we need a page */
+	Page	nixkludge;		/* NIX KLUDGE: we need a page */
 };
 
 /*
@@ -247,6 +248,8 @@ enum {
  *	proc	- syscallentry
  *	stack	- acsyscall
  *	externup - externup()
+ *
+ * riscv uses tp for mach.
  */
 struct Mach
 {
@@ -319,6 +322,8 @@ struct Stackframe
 struct Sys {
 	unsigned char	machstk[MACHSTKSZ];
 
+	Page    root;
+
 	union {
 		Mach	mach;
 		unsigned char	machpage[MACHSZ];
@@ -389,6 +394,7 @@ struct
 extern uintptr_t kseg0;
 
 extern char*rolename[];
+extern void *kseg2;
 
 
 

+ 67 - 4
sys/src/9/riscv/devarch.c

@@ -15,6 +15,7 @@
 #include "../port/error.h"
 
 #include "ureg.h"
+#include "encoding.h"
 
 /* leave this for now; we might want to keep track of MMIO apart from memory. */
 typedef struct IOMap IOMap;
@@ -519,11 +520,53 @@ numcoresread(Chan* c, void *a, int32_t n, int64_t off)
         return readstr(off, a, n, buf);
 }
 
+Queue *keybq;
+void putchar(int);
+/* total hack. */
+void
+kbdputsc(int data, int _)
+{
+	static char line[512];
+	static int len;
+	putchar(data);
+	line[len++] = data;
+	if (keybq && (data == '\n')) {
+		qiwrite(keybq, line, len);
+		len = 0;
+	}
+}
+
+static int32_t
+consoleread(Chan* c, void *vbuf, int32_t len, int64_t off64)
+{
+	int amt;
+	if (!keybq) {
+		keybq = qopen(32, 0, 0, 0);
+		if (!keybq)
+			panic("keyboard queue alloc failed");
+	}
+	amt = qread(keybq, vbuf, len);
+	print("consoleread: amt is %d\n", amt);
+	return amt;
+}
+
+static int32_t
+consolewrite(Chan* _, void *vbuf, int32_t len, int64_t off64)
+{
+	char *c = vbuf;
+
+	for(int i = 0; i < len; i++)
+		putchar(c[i]);
+	return len;
+}
+
+
 void
 archinit(void)
 {
 	addarchfile("cputype", 0444, cputyperead, nil);
 	addarchfile("numcores", 0444, numcoresread, nil);
+	addarchfile("cons", 0666, consoleread, consolewrite);
 }
 
 void
@@ -552,14 +595,34 @@ ms(void)
 
 /*
  *  set next timer interrupt
+ *  incoming units are in ns.
+ *  cycles and mtime are not connected to
+ *  other. Get the delta in ns, convert to
+ *  100 ns units, add to mtime, store in
+ *  mtimecmp.
  */
 void
 timerset(uint64_t x)
 {
-	panic("apictimerset");
-//	extern void apictimerset(uint64_t);
-
-//	apictimerset(x);
+	extern uint64_t *mtimecmp;
+	extern uint64_t *mtime;
+	uint64_t now;
+	int64_t delta;
+
+	now = rdtsc();
+	//print("now 0x%llx timerset to 0x%llx\n", now , x);
+	// I have no fucking clue why scaling it breaks this but it does.
+	//now = fastticks2ns(now);
+	//print("now 0x%llx timerset to 0x%llx\n", now , x);
+	delta = x - now;
+	//print("delta is %llx\n", delta);
+	delta /= 200;
+	if (delta < 1) {
+		print("BUST!\n");
+		delta = 10 /* one microsecond */ * 1000 /* one millisecond */ ;
+	}
+	//print("adjest x to timer ticks, divide by 500 ... 0x%llx %llx %llx \n", *mtime , delta, *mtime + delta);
+	*mtimecmp = *mtime + delta; //+ 10 /* one microsecond */ * 1000 /* one millisecond */ * 100; /* 100 milliseconds */
 }
 
 void

+ 8 - 5
sys/src/9/riscv/fns.h

@@ -10,7 +10,8 @@
 #include "../port/portfns.h"
 
 /* assembly code support from asm.S */
-void startmach(void (*f)(void), void *m);
+/* Startmach is passed an argument which is its own stack. */
+void startmach(void (*f)(void*), void *m, void *stack);
 Mach *machp(void);
 
 /* other functions */
@@ -58,6 +59,7 @@ void	dumpmmu(Proc*);
 void	dumpmmuwalk(uint64_t pa);
 void	dumpptepg(int lvl,uintptr_t pa);
 #define	evenaddr(x)				/* x86 doesn't care */
+void *findKSeg2(void);
 int	fpudevprocio(Proc*, void*, int32_t, uintptr_t, int);
 void	fpuinit(void);
 void	fpunoted(void);
@@ -111,7 +113,7 @@ void	mapraminit(uint64_t, uint64_t);
 void	mapupainit(uint64_t, uint32_t);
 void	meminit(void);
 void	mfence(void);
-void	mmuflushtlb(uint64_t);
+void	mmuflushtlb(void);
 void	mmuinit(void);
 uintptr_t	mmukmap(uintptr_t, uintptr_t, usize);
 int	mmukmapsync(uint64_t);
@@ -183,7 +185,7 @@ uint64_t	fas64(uint64_t*, uint64_t);
 #define TAS(addr)	tas32((addr))
 #define	FASP(p, v)	((void*)fas64((uint64_t*)(p), (uint64_t)(v)))
 
-void	touser(uintptr_t);
+void	touser(Ureg*);
 void	syscallentry(void);
 void	acsyscallentry(void);
 void	syscallreturn(void);
@@ -263,8 +265,9 @@ int backtrace_list(uintptr_t pc, uintptr_t fp, uintptr_t *pcs, size_t nr_slots);
 /* horror */
 static inline void __clobber_callee_regs(void)
 {
-	panic("FIX ME!");
-	//asm volatile ("" : : : "rbx", "r12", "r13", "r14", "r15");
+	// Arrived at through trial and error, this toolchain is a pain.
+	asm volatile ("" : : : "x2", "x3", "x4", "x5", "x6", "x7", /*"x8", */"x9", "x10", "x11", "x12", "x13"/*, "x15"*/);
+	// TODO: f0-f15?
 }
 
 int slim_setlabel(Label*) __attribute__((returns_twice));

+ 10 - 1
sys/src/9/riscv/init9.c

@@ -12,11 +12,20 @@ extern void startboot(char*, char**);
 void
 main(char* argv0)
 {
+	char *ar[2] = {"boot", };
+#if 0
+	// let's do this later when we want true hell.
+	extern int _gp;
+	void *v = &_gp;
+	__asm__ __volatile__ ("1:auipc gp, %pcrel_hi(_gp)\n\taddi gp, gp, %pcrel_lo(1b)\n");
+#endif
+
 	int write(int, void *, int);
+	//write(1, v, 8);
 	//do it this way to make sure it doesn't end up in .data
 	char a[1];
 	a[1] = '0';
 	write(1, a, 1);
-	startboot(argv0, &argv0);
+	startboot("*init*", ar); //argv0, &argv0);
 //	while(1) write(1, "hi\n", 3);
 }

+ 3 - 1
sys/src/9/riscv/inith.json

@@ -17,7 +17,9 @@
 		"Oflags": [
 			"-e_main",
 			"-static",
-			"-Ttext=0x200000"
+			"--no-relax",
+			"-Ttext=0x200000",
+			"-Tdata=0x400000"
 		],
 		"Post": [
 			"elf2c init > init.h"

+ 1 - 38
sys/src/9/riscv/io.h

@@ -8,44 +8,7 @@
  */
 
 enum {
-	VectorNMI	= 2,		/* non-maskable interrupt */
-	VectorBPT	= 3,		/* breakpoint */
-	VectorUD	= 6,		/* invalid opcode exception */
-	VectorCNA	= 7,		/* coprocessor not available */
-	Vector2F	= 8,		/* double fault */
-	VectorCSO	= 9,		/* coprocessor segment overrun */
-	VectorPF	= 14,		/* page fault */
-	Vector15	= 15,		/* reserved */
-	VectorCERR	= 16,		/* coprocessor error */
-
-	VectorPIC	= 32,		/* external i8259 interrupts */
-	IrqCLOCK	= 0,
-	IrqKBD		= 1,
-	IrqUART1	= 3,
-	IrqUART0	= 4,
-	IrqPCMCIA	= 5,
-	IrqFLOPPY	= 6,
-	IrqLPT		= 7,
-	IrqIRQ7		= 7,
-	IrqAUX		= 12,		/* PS/2 port */
-	IrqIRQ13	= 13,		/* coprocessor on 386 */
-	IrqATA0		= 14,
-	IrqATA1		= 15,
-	MaxIrqPIC	= 15,
-
-	VectorLAPIC	= VectorPIC+16,	/* local APIC interrupts */
-	IrqLINT0	= VectorLAPIC+0,
-	IrqLINT1	= VectorLAPIC+1,
-	IrqTIMER	= VectorLAPIC+2,
-	IrqERROR	= VectorLAPIC+3,
-	IrqPCINT	= VectorLAPIC+4,
-	IrqSPURIOUS	= VectorLAPIC+15,
-	MaxIrqLAPIC	= VectorLAPIC+15,
-
-	VectorSYSCALL	= 64,
-
-	VectorAPIC	= 65,		/* external APIC interrupts */
-	MaxVectorAPIC	= 255,
+	IrqTIMER	= 5,
 };
 
 typedef struct Vkey {

+ 488 - 111
sys/src/9/riscv/main.c

@@ -15,15 +15,24 @@
 
 #include "init.h"
 #include "io.h"
+#include "encoding.h"
+#include "ureg.h"
+#include <tos.h>
+
+
+int cpuserver = 1;
 
 extern void (*consuartputs)(char*, int);
+void query_mem(const char *config_string, uintptr_t *base, size_t *size);
+void query_rtc(const char *config_string, uintptr_t *mtime);
+void query_uint(const char *config_string, char *name, uintptr_t *val);
 
-void testPrint(uint8_t c);
+void putchar(uint8_t c);
 
 void msg(char *s)
 {
 	while (*s)
-		testPrint(*s++);
+		putchar(*s++);
 }
 void die(char *s)
 {
@@ -40,24 +49,38 @@ ndnr(void)
 static void puts(char * s, int n)
 {
 	while (n--)
-		testPrint(*s++);
+		putchar(*s++);
 }
 
-static int x = 0x123456;
-
-/* mach struct for hart 0. */
+/* mach info for hart 0. */
 /* in many plan 9 implementations this stuff is all reserved in early assembly.
  * we don't have to do that. */
-static uint64_t m0stack[4096];
-static Mach m0;
+uint64_t m0stack[4096];
+Mach m0;
+
 Sys asys, *sys=&asys;
 Conf conf;
 uintptr_t kseg0 = KZERO;
 char *cputype = "riscv";
+int64_t hz;
+uintptr_t rtc;
 
 /* I forget where this comes from and I don't care just now. */
 uint32_t kerndate;
+int maxcores = 1;
+int nosmp = 1;
+uint64_t mtimepa, mtimecmppa;
+uint64_t *mtime, *mtimecmp;
+/*
+ * kseg2 is the base of the virtual address space.
+ * it is not a constant as in amd64; in riscv there are many possible
+ * values, even on the same SOC. It is determined by firmware.
+ */
+void *kseg2;
 
+char *configstring; /* from coreboot, first arg to main */
+
+static uintptr_t sp;		/* XXX - must go - user stack of init proc */
 
 /* general purpose hart startup. We call this via startmach.
  * When we enter here, the machp() function is usable.
@@ -69,27 +92,348 @@ void hart(void)
 	die("not yet");
 }
 
-void bsp(void)
+uint64_t
+rdtsc(void)
+{
+	uint64_t cycles;
+//	msg("rdtsc\n");
+	cycles = read_csr(/*s*/cycle);
+//print("cycles in rdtsc is 0x%llx\n", cycles);
+//	msg("done rdts\n");
+	return cycles;
+}
+
+void
+loadenv(int argc, char* argv[])
+{
+	char *env[2];
+
+	/*
+	 * Process command line env options
+	 */
+	while(--argc > 0){
+		char* next = *++argv;
+		if(next[0] !='-'){
+			if (gettokens(next, env, 2, "=")  == 2){;
+				ksetenv(env[0], env[1], 0);
+			}else{
+				print("Ignoring parameter with no value: %s\n", env[0]);
+			}
+		}
+	}
+}
+
+void
+init0(void)
+{
+	Proc *up = externup();
+	char buf[2*KNAMELEN];
+	Ureg u;
+
+	up->nerrlab = 0;
+
+	/*
+	 * if(consuart == nil)
+	 * i8250console("0");
+	 */
+	spllo();
+
+	/*
+	 * These are o.k. because rootinit is null.
+	 * Then early kproc's will have a root and dot.
+	 */
+print("init0: up is %p\n", up);
+	up->slash = namec("#/", Atodir, 0, 0);
+print("1\n");
+	pathclose(up->slash->path);
+print("1\n");
+	up->slash->path = newpath("/");
+print("1\n");
+	up->dot = cclone(up->slash);
+print("1\n");
+
+	devtabinit();
+print("1\n");
+
+	if(!waserror()){
+		//snprint(buf, sizeof(buf), "%s %s", "AMD64", conffile);
+		//loadenv(oargc, oargv);
+		ksetenv("terminal", buf, 0);
+		ksetenv("cputype", cputype, 0);
+		ksetenv("pgsz", "2097152", 0);
+		// no longer. 	confsetenv();
+		poperror();
+	}
+	kproc("alarm", alarmkproc, 0);
+	//nixprepage(-1);
+	print("TOUSER: kstack is %p\n", up->kstack);
+	//debugtouser((void *)UTZERO);
+	memset(&u, 0, sizeof(u));
+	u.ip = (uintptr_t)init_main;
+	u.sp = sp;
+	u.a2 = USTKTOP-sizeof(Tos);
+	touser(&u);
+}
+
+/*
+ * Option arguments from the command line.
+ * oargv[0] is the boot file.
+ * TODO: do it.
+ */
+static int64_t oargc;
+static char* oargv[20];
+static char oargb[1024];
+static int oargblen;
+
+void
+bootargs(uintptr_t base)
 {
+	int i;
+	uint32_t ssize;
+	char **av, *p;
+
+	/*
+	 * Push the boot args onto the stack.
+	 * Make sure the validaddr check in syscall won't fail
+	 * because there are fewer than the maximum number of
+	 * args by subtracting sizeof(up->arg).
+	 */
+	i = oargblen+1;
+	p = UINT2PTR(STACKALIGN(base + BIGPGSZ - sizeof(((Proc*)0)->arg) - i));
+	memmove(p, oargb, i);
+
+	/*
+	 * Now push argc and the argv pointers.
+	 * This isn't strictly correct as the code jumped to by
+	 * touser in init9.[cs] calls startboot (port/initcode.c) which
+	 * expects arguments
+	 * 	startboot(char* argv0, char* argv[])
+	 * not the usual (int argc, char* argv[]), but argv0 is
+	 * unused so it doesn't matter (at the moment...).
+	 */
+	av = (char**)(p - (oargc+2)*sizeof(char*));
+	ssize = base + BIGPGSZ - PTR2UINT(av);
+	print("Stack size in boot args is %p\n", ssize);
+	*av++ = (char*)oargc;
+	for(i = 0; i < oargc; i++)
+		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BIGPGSZ);
+	*av = nil;
+
+	sp = USTKTOP - ssize;
+	print("New sp in bootargs is %p\n", sp);
+}
+
+void
+userinit(void)
+{
+	Proc *up = externup();
+	Proc *p;
+	Segment *s;
+	KMap *k;
+	Page *pg;
+	int sno;
+
+	p = newproc();
+	p->pgrp = newpgrp();
+	p->egrp = smalloc(sizeof(Egrp));
+	p->egrp->r.ref = 1;
+	p->fgrp = dupfgrp(nil);
+	p->rgrp = newrgrp();
+	p->procmode = 0640;
+
+	kstrdup(&eve, "");
+	kstrdup(&p->text, "*init*");
+	kstrdup(&p->user, eve);
+
+	/*
+	 * Kernel Stack
+	 *
+	 * N.B. make sure there's enough space for syscall to check
+	 *	for valid args and
+	 *	space for gotolabel's return PC
+	 * AMD64 stack must be quad-aligned.
+	 */
+	p->sched.pc = PTR2UINT(init0);
+	p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->arg)-sizeof(uintptr_t));
+	p->sched.sp = STACKALIGN(p->sched.sp);
+
+	/*
+	 * User Stack
+	 *
+	 * Technically, newpage can't be called here because it
+	 * should only be called when in a user context as it may
+	 * try to sleep if there are no pages available, but that
+	 * shouldn't be the case here.
+	 */
+	sno = 0;
+	print("newseg(0x%x, %p, 0x%llx)\n", SG_STACK|SG_READ|SG_WRITE, (void *)USTKTOP-USTKSIZE, USTKSIZE/ BIGPGSZ);
+	s = newseg(SG_STACK|SG_READ|SG_WRITE, USTKTOP-USTKSIZE, USTKSIZE/ BIGPGSZ);
+	p->seg[sno++] = s;
+	pg = newpage(1, 0, USTKTOP-BIGPGSZ, BIGPGSZ, -1);
+	segpage(s, pg);
+	k = kmap(pg);
+	bootargs(VA(k));
+	kunmap(k);
+
+	/*
+	 * Text
+	 */
+	s = newseg(SG_TEXT|SG_READ|SG_EXEC, UTZERO, 1);
+	s->flushme++;
+	p->seg[sno++] = s;
+	pg = newpage(1, 0, UTZERO, BIGPGSZ, -1);
+	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+	segpage(s, pg);
+	k = kmap(s->map[0]->pages[0]);
+	/* UTZERO is only needed until we make init not have 2M block of zeros at the front. */
+	memmove(UINT2PTR(VA(k) + init_code_start - UTZERO), init_code_out, sizeof(init_code_out));
+	kunmap(k);
+
+	/*
+	 * Data
+	 */
+	s = newseg(SG_DATA|SG_READ|SG_WRITE, UTZERO + BIGPGSZ, 1);
+	s->flushme++;
+	p->seg[sno++] = s;
+	pg = newpage(1, 0, UTZERO + BIGPGSZ, BIGPGSZ, -1);
+	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+	segpage(s, pg);
+	k = kmap(s->map[0]->pages[0]);
+	/* This depends on init having a text segment < 2M. */
+	memmove(UINT2PTR(VA(k) + init_data_start - (UTZERO + BIGPGSZ)), init_data_out, sizeof(init_data_out));
+
+	kunmap(k);
+	ready(p);
+}
+
+void
+confinit(void)
+{
+	int i;
+
+	conf.npage = 0;
+	for(i=0; i<nelem(conf.mem); i++)
+		conf.npage += conf.mem[i].npage;
+	conf.nproc = 1000;
+	conf.nimage = 200;
+}
+
+/* check checks simple atomics and anything else that is critical to correct operation.
+ * You can make the prints optional on errors cases, not have it print all tests,
+ * but you should never remove check or the call to it. It found some nasty problems. */
+static void
+check(void)
+{
+	uint64_t f2ns;
+	// cas test
+	uint32_t t = 0;
+	int fail = 0;
+	int _42 = 42;
+	int a = _42, b;
+	int x = cas32(&t, 0, 1);
+
+	print("cas32 done x %d (want 1) t %d (want 1)\n", x, t);
+	if ((t != 1) || (x != 1))
+		fail++;
+
+	x = cas32(&t, 0, 1);
+	print("cas32 done x %d (want 0) t %d (want 1)\n", x, t);
+	if ((t != 1) || (x != 0))
+		fail++;
+
+	print("t is now %d before final cas32\n", t);
+	x = cas32(&t, 1, 2);
+	print("cas32 done x %d (want 1) t %d (want 2)\n", x, t);
+	if ((t != 2) || (x != 1))
+		fail++;
+
+	t = 0;
+	x = tas32(&t);
+	print("tas done x %d (want 0) t %d (want 1)\n", x, t);
+	if ((t != 1) || (x != 0))
+		fail++;
+
+	x = tas32(&t);
+	print("tas done x %d (want 1) t %d (want 1)\n", x, t);
+	if ((t != 1) || (x != 1))
+		fail++;
+
+	t = 0;
+	x = tas32(&t);
+	print("tas done x %d (want ) t %d (want 1)\n", x, t);
+	if ((t != 1) || (x != 0))
+		fail++;
+
+	b = ainc(&a);
+	print("after ainc a is %d (want 43) b is %d (want 43)\n", a, b);
+	if ((b != _42 + 1) || (a != _42 + 1))
+		fail++;
+
+	b = ainc(&a);
+	print("after ainc a is %d (want 44) b is %d (want 44)\n", a, b);
+	if ((b != _42 + 2) || (a != _42 + 2))
+		fail++;
+
+	b = adec(&a);
+	print("after ainc a is %d (want 43) b is %d (want 43)\n", a, b);
+	if ((b != _42 + 1) || (a != _42 + 1))
+		fail++;
+
+	if (fail) {
+		print("%d failures in check();\n", fail);
+		panic("FIX ME");
+	}
+
+	f2ns = fastticks2ns(10);
+	if ((f2ns < 1) || (f2ns > 10)) {
+		print("fastticks2ns(1) is nuts: %d\n", f2ns);
+		panic("Should be in the range 1 to 10, realistically");
+	}
+
+	f2ns = ns2fastticks(1);
+	if ((f2ns < 2) || (f2ns > 100)) {
+		print("ns2fastticks(1) is nuts: %d\n", f2ns);
+		panic("Should be in the range 2 to 100, realistically");
+	}
+
+}
+
+void bsp(void *stack, uintptr_t _configstring)
+{
+	kseg2 = findKSeg2();
+	msg("HIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n");
+	configstring = KADDR(_configstring);
+	msg(configstring);
 	Mach *mach = machp();
 	if (mach != &m0)
 		die("MACH NOT MATCH");
 	msg("memset mach\n");
 	memset(mach, 0, sizeof(Mach));
 	msg("done that\n");
+	MACHP(0) = mach;
 
+	msg(configstring);
 	mach->self = (uintptr_t)mach;
 	msg("SET SELF OK\n");
 	mach->machno = 0;
 	mach->online = 1;
 	mach->NIX.nixtype = NIXTC;
-	mach->stack = PTR2UINT(m0stack);
+	mach->stack = PTR2UINT(stack);
 	*(uintptr_t*)mach->stack = STACKGUARD;
+	msg(configstring);
 	mach->externup = nil;
 	active.nonline = 1;
 	active.exiting = 0;
 	active.nbooting = 0;
 
+	consuartputs = puts;
+	msg("call asminit\n");
+	msg("==============================================\n");
+	asminit();
+	msg(",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n");
+	asmmapinit(0x81000000, 0x3f000000, 1);
+
+	msg(configstring);
 	/*
 	 * Need something for initial delays
 	 * until a timebase is worked out.
@@ -98,50 +442,118 @@ void bsp(void)
 	mach->cpumhz = 2000;
 	sys->cyclefreq = mach->cpuhz;
 
-	// this is in 386, so ... not yet. i8250console("0");
-	// probably pull in the one from coreboot for riscv.
+	sys->nmach = 1;
 
-	consuartputs = puts;
-	msg("call asminit\n");
-	asminit();
-	msg("call fmtinit\n");
+	msg(configstring);
 	fmtinit();
-	msg("done fmtinit\n");
-	static uint64_t i = 0, j;
-	j = tas32(&i);
-	if (j) msg ("tas is weird, i was set\n"); else msg("i was not set in first tas\n");
-	j = tas32(&i);
-	if (j) msg ("tas is ok, i was set\n"); else die("i was not set in second tas\n");
-
-	i = 5;
-	cas32(&i, 5, 6);
-	if (i != 6) die("i is not 6 after cas\n"); else msg ("i is 6 after cas\n");
-
-	static Lock l; // to ensure initialization.
-	if (canlock(&l)) msg ("L can be locked\n"); else die("Can't lock L\n");
-	ilock(&l);
-	if (canlock(&l)) msg ("L can be NOT be locked OK\n"); else die("Can lock L after lock\n");
-	iunlock(&l);
-	if (canlock(&l)) msg ("L can be locked after unlock\n"); else die("Can't lock L afterunlock\n");
-	
-	
 	print("\nHarvey\n");
-
+print("KADDR OF (uintptr_t) 0x40001000 is %p\n", KADDR((uintptr_t) 0x40001000));
+
+	/* you're going to love this. Print does not print the whole
+	 * string. msg does. Bug. */
+	print("Config string:%p '%s'\n", configstring, configstring);
+	msg("Config string via msg\n");
+	msg(configstring);
+	msg("\n");
+	mach->perf.period = 1;
+	if((hz = archhz()) != 0ll){
+		mach->cpuhz = hz;
+		mach->cyclefreq = hz;
+		sys->cyclefreq = hz;
+		mach->cpumhz = hz/1000000ll;
+	}
+
+	print("print a number like 5 %d\n", 5);
+	/*
+	 * Mmuinit before meminit because it
+	 * flushes the TLB via machp()->pml4->pa.
+	 */
+	mmuinit();
+
+	ioinit(); print("ioinit\n");
+print("IOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIO\n");
+	meminit();print("meminit\n");
+print("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n");
+	confinit();print("confinit\n");
+print("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n");
+	archinit();print("archinit\n");
+print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n");
+	mallocinit();print("mallocinit\n");
+
+	/* test malloc. It's easier to find out it's broken here,
+	 * not deep in some call chain.
+	 * See next note.
+	 *
+	 */
+	if (1) {
+		void *v = malloc(1234);
+		msg("allocated\n ");
+		free(v);
+		msg("free ok\n");
+	}
+
+	query_rtc(configstring, &rtc);
+	print("rtc: %p\n", rtc);
+
+	query_uint(configstring, "rtc{addr", (uintptr_t*)&mtimepa);
+	mtime = KADDR(mtimepa);
+	query_uint(configstring, "core{0{0{timecmp", (uintptr_t*)&mtimecmppa);
+	mtimecmp = KADDR(mtimecmppa);
+
+	print("mtime is %p and mtimecmp is %p\n", mtime, mtimecmp);
+	umeminit();
+
+	procinit0();
+	print("before mpacpi, maxcores %d\n", maxcores);
+	trapinit();
+	print("trapinit done\n");
+	/* Forcing to single core if desired */
+	if(!nosmp) {
+		// smp startup
+	}
+//working.
+	// not needed. teardownidmap(mach);
+	timersinit();print("	timersinit();\n");
+	// ? fpuinit();
+	psinit(conf.nproc);print("	psinit(conf.nproc);\n");
+	initimage();print("	initimage();\n");
+	links();
+
+	devtabreset();print("	devtabreset();\n");
+	pageinit();print("	pageinit();\n");
+	swapinit();print("	swapinit();\n");
+	userinit();print("	userinit();\n");
+	/* Forcing to single core if desired */
+	if(!nosmp) {
+		//nixsquids();
+		//testiccs();
+	}
+
+	print("NO profiling until you set upa alloc_cpu_buffers()\n");
+	//alloc_cpu_buffers();
+
+	print("CPU Freq. %dMHz\n", mach->cpumhz);
+	// set the trap vector
+	void *supervisor_trap_entry(void);
+	write_csr(/*stvec*/0x105, supervisor_trap_entry);
+	// enable all interrupt sources.
+	uint64_t ints = read_csr(sie);
+	ints |= 0x666;
+	write_csr(sie, ints);
+
+	dumpmmuwalk(0xfffffffffffff000ULL);
+
+	check();
+
+	void consread(void);
+	addclock0link(consread, 0);
+
+	print("schedinit...\n");
+
+	schedinit();
 	die("Completed hart for bsp OK!\n");
 }
 
-void
-main(uint32_t mbmagic, uint32_t mbaddress)
-{
-
-	testPrint('0');
-	if (x != 0x123456)
-		die("Data is not set up correctly\n");
-	//memset(edata, 0, end - edata);
-	msg("got somewhere");
-	startmach(bsp, &m0);
-}
-
 /* stubs until we implement in assembly */
 int corecolor(int _)
 {
@@ -150,6 +562,8 @@ int corecolor(int _)
 
 Proc *externup(void)
 {
+	if (! machp())
+		return nil;
 	return machp()->externup;
 }
 
@@ -157,12 +571,6 @@ void errstr(char *s, int i) {
 	panic("errstr");
 }
 
-void
-oprof_alarm_handler(Ureg *u)
-{
-	panic((char *)__func__);
-}
-
 void
 hardhalt(void)
 {
@@ -178,18 +586,15 @@ ureg2gdb(Ureg *u, uintptr_t *g)
 int
 userureg(Ureg*u)
 {
-	panic((char *)__func__);
-	return -1;
-}
-
-uintptr_t
-userpc(Ureg*u)
-{
-	panic((char *)__func__);
-	return 0;
+	int64_t ip = (int64_t)u->ip;
+	if (ip < 0) {
+		//print("RETURNING 0 for userureg\n");
+		return 0;
+	}
+	//print("Returning 1 for userureg; need a better test\n");
+	return 1;
 }
 
-
 void    exit(int _)
 {
 	panic((char *)__func__);
@@ -202,17 +607,23 @@ void fpunoted(void)
 
 void fpunotify(Ureg*_)
 {
-	panic((char *)__func__);
+	print("fpunotify: doing nothing since FPU is disabled\n");
 }
 
 void fpusysrfork(Ureg*_)
 {
-	panic((char *)__func__);
+	print((char *)__func__);
+	print("IGNORING\n");
 }
 
-void kexit(Ureg*_)
+void sysrforkret(void)
 {
-	panic((char *)__func__);
+	void *stack(void);
+	void *sp = stack();
+	if(0) print("sysrforkret: stack is %p\n", sp);
+	if(0) dumpgpr((Ureg *)sp);
+void _sysrforkret();
+	_sysrforkret();
 }
 
 void
@@ -223,17 +634,14 @@ reboot(void*_, void*__, int32_t ___)
 
 void fpusysprocsetup(Proc *_)
 {
-	panic((char *)__func__);
-}
-
-void sysrforkret(void)
-{
-	panic((char *)__func__);
+	print((char *)__func__);
+	print("THIS IS GONNA SCREW YOU IF YOU DO NOT FIX IT\n");
 }
 
 void     fpusysrforkchild(Proc*_, Proc*__)
 {
-	panic((char *)__func__);
+	print((char *)__func__);
+	print("THIS IS GONNA SCREW YOU IF YOU DO NOT FIX IT\n");
 }
 
 int
@@ -243,50 +651,19 @@ fpudevprocio(Proc*p, void*v, int32_t _, uintptr_t __, int ___)
 	return -1;
 }
 
-void
-setregisters(Ureg*u, char*f, char*t, int amt)
-{
-	panic((char *)__func__);
-}
-
 void cycles(uint64_t *p)
 {
-	return;
 	*p = rdtsc();
 }
 
 int islo(void)
 {
-	panic((char *)__func__);
-	return 0;
-}
-
-uintptr_t
-dbgpc(Proc*p)
-{
-	panic((char *)__func__);
-	return 0;
-}
-
-
-void dumpstack(void)
-{
-	panic((char *)__func__);
+//	msg("isloc\n");
+	uint64_t ms = read_csr(sstatus);
+//	msg("read it\n");
+	return ms & MSTATUS_SIE;
 }
 
-void
-dumpgpr(Ureg* ureg)
-{
-	panic((char *)__func__);
-}
-
-void
-setkernur(Ureg*u, Proc*p)
-{
-	panic((char *)__func__);
-}
-
-
 void
 stacksnippet(void)
 {
@@ -326,7 +703,7 @@ HERE(void)
 /* Keep to debug trap.c */
 void wave(int c)
 {
-	testPrint(c);
+	putchar(c);
 }
 
 void hi(char *s)

+ 13 - 12
sys/src/9/riscv/map.c

@@ -16,23 +16,22 @@
 #define _KADDR(pa)	UINT2PTR(kseg0+((uintptr)(pa)))
 #define _PADDR(va)	PTR2UINT(((uintptr)(va)) - kseg0)
 
-#define TMFM		(64*MiB)
+/* physical is from 2 -> 4 GiB */
+#define TMFM		(4ULL*GiB)
 
+/* the wacko hole in RISCV address space makes KADDR a bit more complex. */
 int km, ku, k2;
 void*
 KADDR(uintptr_t pa)
 {
-	uint8_t* va;
-
-	va = UINT2PTR(pa);
-	if(pa < TMFM) {
+	if((pa > 2 * GiB) && (pa < TMFM)) {
 		km++;
-		return KSEG0+va;
+		return (void *)(KSEG0|pa);
 	}
 
-	assert(pa < KSEG2);
+	assert(pa < (uintptr_t)kseg2);
 	k2++;
-	return KSEG2+va;
+	return (void *)((uintptr_t)kseg2|pa);
 }
 
 uintmem
@@ -41,10 +40,12 @@ PADDR(void* va)
 	uintmem pa;
 
 	pa = PTR2UINT(va);
-	if(pa >= KSEG0 && pa < KSEG0+TMFM)
-		return pa-KSEG0;
-	if(pa > KSEG2)
-		return pa-KSEG2;
+	if(pa >= KSEG0) {
+		return (uintmem)(uint32_t)pa; //-KSEG0;
+	}
+	if(pa > (uintptr_t)kseg2) {
+		return pa-(uintptr_t)kseg2;
+	}
 
 	panic("PADDR: va %#p pa #%p @ %#p\n", va, _PADDR(va), getcallerpc());
 	return 0;

+ 4 - 13
sys/src/9/riscv/mem.h

@@ -94,11 +94,13 @@
 #define UTZERO		(0+2*MiB)		/* first address in user text */
 #define UTROUND(t)	ROUNDUP((t), BIGPGSZ)
 #ifndef __ASSEMBLER__
-#define USTKTOP		(0x00007ffffffff000ull & ~(BIGPGSZ-1))
+#define USTKTOP		(0x3fffffffffULL & ~(BIGPGSZ-1))
 #else
-#define USTKTOP         (0x00007ffffffff000 & ~(BIGPGSZ-1))
+#define USTKTOP         (0x3fffffffffULL & ~(BIGPGSZ-1))
 #endif
+/* U means "user" */
 #define USTKSIZE	(16*1024*1024)		/* size of user stack */
+/* T means "temporary" */
 #define TSTKTOP		(USTKTOP-USTKSIZE)	/* end of new stack in sysexec */
 #define	NIXCALL		(TSTKTOP-USTKSIZE)	/* nix syscall queues (2MiB) */
 #ifndef __ASSEMBLER__
@@ -116,25 +118,14 @@
  */
 
 #ifndef __ASSEMBLER__
-#define KSEG2		(0xfffffe0000000000ull)	/* 1TB - KMAP */
-/*			 0xffffff0000000000ull	end of KSEG2 */
-#define VMAP		(0xffffffffe0000000ull)
-#define VMAPSZ		(256*MiB)
 #define KSEG0		(0xffffffff80000000ull)	/* 256MB - this is confused */
 #define KZERO		(0xffffffff80000000ull)
 #define KTZERO		(KZERO+1*MiB+64*KiB)
-#define PDMAP		(0xffffffffff800000ull)
-#define PMAPADDR		(0xffffffffffe00000ull)	/* unused as of yet */
 /*			 0xffffffffffffffffull	end of KSEG0 */
 #else
-#define KSEG2           (0xfffffe0000000000)
-#define VMAPSZ          (256*MiB)
-#define VMAP            (0xffffffffe0000000)
 #define KSEG0           (0xffffffff80000000)
 #define KZERO           (0xffffffff80000000)
 #define KTZERO          (KZERO+1*MiB+64*KiB)
-#define PDMAP           (0xffffffffff800000)
-#define PMAPADDR        (0xffffffffffe00000)
 #endif
 
 /*

+ 31 - 0
sys/src/9/riscv/memory.c

@@ -0,0 +1,31 @@
+/*
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+meminit(void)
+{
+	extern void asmmeminit(void);
+
+print("meminit\n");
+	asmmeminit();
+}
+
+void
+umeminit(void)
+{
+	extern void asmumeminit(void);
+
+	asmumeminit();
+}

+ 224 - 335
sys/src/9/riscv/mmu.c

@@ -16,18 +16,33 @@
 #include "encoding.h"
 #include "mmu.h"
 
+#undef DBGFLG
+#define DBGFLG 0
+
+/* this gets pretty messy. RV64 has *at least* two modes:
+ * 4 level and 3 level page tables. And people wonder why
+ * I like soft TLB so much. Anyway, for now, not sure
+ * how to handle it.
+ * Would be cool to work out a way to Do The Right Thing
+ * without regard to page size, so that's what I'm going to
+ * try to do.
+ */
+void msg(char *);
 /*
  * To do:
  *	PteNX;
  *	mmukmapsync grot for >1 processor;
- *	replace vmap with newer version (no PDMAP);
  *	mmuptcopy (PteSHARED trick?);
  *	calculate and map up to TMFM (conf crap);
  */
 
-#define TMFM		(64*MiB)		/* kernel memory */
+/* strike off 2M so it won't wrap to 0. Sleazy. */
+#define TMFM		(2*GiB-2*MiB)		/* kernel memory */
 
 #define PPN(x)		((x)&~(PGSZ-1))
+#define PTE2PPN(p) ((p)>>10)
+#define PTE2PA(p) (((p)>>10)<<12)
+
 
 #if 0
 /* Print the page table structures to the console */
@@ -71,15 +86,15 @@ rootput(uintptr_t root)
 
 }
 void
-mmuflushtlb(uint64_t u)
+mmuflushtlb(void)
 {
 
 	machp()->tlbpurge++;
-	if(machp()->MMU.pml4->daddr){
-		memset(UINT2PTR(machp()->MMU.pml4->va), 0, machp()->MMU.pml4->daddr*sizeof(PTE));
-		machp()->MMU.pml4->daddr = 0;
+	if(machp()->MMU.root->daddr){
+		memset(UINT2PTR(machp()->MMU.root->va), 0, machp()->MMU.root->daddr*sizeof(PTE));
+		machp()->MMU.root->daddr = 0;
 	}
-	rootput((uintptr_t) machp()->MMU.pml4->pa);
+	rootput((uintptr_t) machp()->MMU.root->pa);
 }
 
 void
@@ -118,7 +133,7 @@ mmuptpfree(Proc* proc, int clear)
 		proc->MMU.mmuptp[l] = nil;
 	}
 
-	machp()->MMU.pml4->daddr = 0;
+	machp()->MMU.root->daddr = 0;
 }
 
 static void
@@ -168,25 +183,32 @@ dumpmmu(Proc *p)
 				" daddr %#lx next %#p prev %#p\n",
 				pg, pg->va, pg->pa, pg->daddr, pg->next, pg->prev);
 	}
-	print("pml4 %#llx\n", machp()->MMU.pml4->pa);
-	if(0)dumpptepg(4, machp()->MMU.pml4->pa);
+	print("root %#llx\n", machp()->MMU.root->pa);
+	if(0)dumpptepg(4, machp()->MMU.root->pa);
 }
 
 void
 dumpmmuwalk(uint64_t addr)
 {
 	int l;
-	PTE *pte, *pml4;
-
-	pml4 = UINT2PTR(machp()->MMU.pml4->va);
-	if((l = mmuwalk(pml4, addr, 3, &pte, nil)) >= 0)
-		print("cpu%d: mmu l%d pte %#p = %llx\n", machp()->machno, l, pte, *pte);
-	if((l = mmuwalk(pml4, addr, 2, &pte, nil)) >= 0)
-		print("cpu%d: mmu l%d pte %#p = %llx\n", machp()->machno, l, pte, *pte);
-	if((l = mmuwalk(pml4, addr, 1, &pte, nil)) >= 0)
-		print("cpu%d: mmu l%d pte %#p = %llx\n", machp()->machno, l, pte, *pte);
-	if((l = mmuwalk(pml4, addr, 0, &pte, nil)) >= 0)
-		print("cpu%d: mmu l%d pte %#p = %llx\n", machp()->machno, l, pte, *pte);
+	PTE *pte, *root;
+
+	root = UINT2PTR(machp()->MMU.root->va);
+	print("root is %p\n", root);
+	if((l = mmuwalk(root, addr, 2, &pte, nil)) >= 0) {
+		print("\tcpu%d: mmu l%d pte %#p = ", machp()->machno, l, pte);
+		print("%llx, PA is %llx\n", *pte, PTE2PA(*pte));
+	}
+	if((l = mmuwalk(root, addr, 1, &pte, nil)) >= 0) {
+		print("\tcpu%d: mmu l%d pte %#p = ", machp()->machno, l, pte);
+		print("%llx, PA is %llx\n", *pte, PTE2PA(*pte));
+	}
+	if((l = mmuwalk(root, addr, 0, &pte, nil)) >= 0) {
+		print("\tcpu%d: mmu l%d pte %#p = ", machp()->machno, l, pte);
+		print("%llx, PA is %llx\n", *pte, PTE2PA(*pte));
+	}
+	if (PTE2PA(*pte) != 0)
+		hexdump(KADDR(PTE2PA(*pte)), 32);
 }
 
 static Page mmuptpfreelist;
@@ -259,21 +281,29 @@ mmuswitch(Proc* proc)
 		proc->newtlb = 0;
 	}
 
-	if(machp()->MMU.pml4->daddr){
-		memset(UINT2PTR(machp()->MMU.pml4->va), 0, machp()->MMU.pml4->daddr*sizeof(PTE));
-		machp()->MMU.pml4->daddr = 0;
+	/* daddr is the number of user PTEs in use in the root. */
+	if(machp()->MMU.root->daddr){
+		print("memsg(%p, 0, %d\n", UINT2PTR(machp()->MMU.root->va), 0, machp()->MMU.root->daddr*sizeof(PTE));
+		memset(UINT2PTR(machp()->MMU.root->va), 0, machp()->MMU.root->daddr*sizeof(PTE));
+		machp()->MMU.root->daddr = 0;
 	}
 
-	pte = UINT2PTR(machp()->MMU.pml4->va);
+	pte = UINT2PTR(machp()->MMU.root->va);
+
+	if (0)print("pte %p\n", pte);
+	/* N.B. On RISCV, we DO NOT SET any of X, R, W  bits at this level since
+	 * that we point to page table pages on level down.  Also, these are
+	 * explicitly user level pages, so PteU is set. */
 	for(page = proc->MMU.mmuptp[3]; page != nil; page = page->next){
-		pte[page->daddr] = PPN(page->pa)|PteU|PteRW|PteP;
-		if(page->daddr >= machp()->MMU.pml4->daddr)
-			machp()->MMU.pml4->daddr = page->daddr+1;
-		page->prev = machp()->MMU.pml4;
+		pte[page->daddr] = PPN(page->pa)|PteU|PteP;
+		if(page->daddr >= machp()->MMU.root->daddr)
+			machp()->MMU.root->daddr = page->daddr+1;
+		page->prev = machp()->MMU.root;
 	}
 
-	//tssrsp0(machp(), STACKALIGN(PTR2UINT(proc->kstack+KSTACK)));
-	rootput((uintptr_t) machp()->MMU.pml4->pa);
+	if (0)print("rootput %p\n", (void *)(uintptr_t) machp()->MMU.root->pa);
+	rootput((uintptr_t) machp()->MMU.root->pa);
+	if (0)print("splx\n");
 	splx(pl);
 }
 
@@ -299,37 +329,30 @@ mmurelease(Proc* proc)
 		wakeup(&pga.rend);
 	proc->MMU.mmuptp[0] = nil;
 
-	panic("tssrsp0");
-	//tssrsp0(machp(), STACKALIGN(machp()->stack+MACHSTKSZ));
-	rootput(machp()->MMU.pml4->pa);
+	rootput(machp()->MMU.root->pa);
 }
 
 static void
 checkpte(uintmem ppn, void *a)
 {
 	int l;
-	PTE *pte, *pml4;
+	PTE *pte, *root;
 	uint64_t addr;
 	char buf[240], *s;
 
 	addr = PTR2UINT(a);
-	pml4 = UINT2PTR(machp()->MMU.pml4->va);
+	root = UINT2PTR(machp()->MMU.root->va);
 	pte = 0;
 	s = buf;
 	*s = 0;
-	if((l = mmuwalk(pml4, addr, 3, &pte, nil)) < 0 || (*pte&PteP) == 0)
-		goto Panic;
-	s = seprint(buf, buf+sizeof buf,
-		"check3: l%d pte %#p = %llx\n",
-		l, pte, pte?*pte:~0);
-	if((l = mmuwalk(pml4, addr, 2, &pte, nil)) < 0 || (*pte&PteP) == 0)
+	if((l = mmuwalk(root, addr, 2, &pte, nil)) < 0 || (*pte&PteP) == 0)
 		goto Panic;
 	s = seprint(s, buf+sizeof buf,
 		"check2: l%d  pte %#p = %llx\n",
 		l, pte, pte?*pte:~0);
 	if(*pte&PteFinal)
 		return;
-	if((l = mmuwalk(pml4, addr, 1, &pte, nil)) < 0 || (*pte&PteP) == 0)
+	if((l = mmuwalk(root, addr, 1, &pte, nil)) < 0 || (*pte&PteP) == 0)
 		goto Panic;
 	seprint(s, buf+sizeof buf,
 		"check1: l%d  pte %#p = %llx\n",
@@ -357,7 +380,7 @@ mmuptpcheck(Proc *proc)
 
 	if(proc == nil)
 		return;
-	lp = machp()->MMU.pml4;
+	lp = machp()->MMU.root;
 	for(lvl = 3; lvl >= 2; lvl--){
 		npgs = 0;
 		for(p = proc->MMU.mmuptp[lvl]; p != nil; p = p->next){
@@ -422,7 +445,8 @@ pteflags(uint attr)
 void
 invlpg(uintptr_t _)
 {
-	panic("invlpage");
+	// TOODO
+	if (0) print("invlpage is not implemented, continuing anyway (addr is %p)\n", _);
 }
 
 /*
@@ -439,20 +463,31 @@ mmuput(uintptr_t va, Page *pg, uint attr)
 	PTE *pte;
 	Page *page, *prev;
 	Mpl pl;
-	uintmem pa, ppn;
+	uintmem pa, ppage;
 	char buf[80];
 
-	ppn = 0;
+	if (DBGFLG) {
+		print("mmuput: %p\n", va);
+		dumpmmuwalk(va);
+		print("now try the put");
+	}
+	ppage = 0;
 	pa = pg->pa;
 	if(pa == 0)
 		panic("mmuput: zero pa");
+	if(va == 0)
+		panic("mmuput: zero va");
 
 	if(DBGFLG){
 		snprint(buf, sizeof buf, "cpu%d: up %#p mmuput %#p %#P %#x\n",
 			machp()->machno, up, va, pa, attr);
 		print("%s", buf);
 	}
-	assert(pg->pgszi >= 0);
+	if (pg->pgszi < 0) {
+		print("mmuput(%p, %p, 0x%x): bad pgszi %d for pa %p\n",
+			va, pg, attr, pg->pgszi, pa);
+		assert(pg->pgszi >= 0);
+	}
 	pgsz = sys->pgsz[pg->pgszi];
 	if(pa & (pgsz-1))
 		panic("mmuput: pa offset non zero: %#llx\n", pa);
@@ -462,13 +497,15 @@ mmuput(uintptr_t va, Page *pg, uint attr)
 	if(DBGFLG)
 		mmuptpcheck(up);
 	user = (va < KZERO);
-	x = PTLX(va, 3);
+	x = PTLX(va, 2);
+	if (0) print("user is %d, index for %p is 0x%x, ", user, va, x);
 
-	pte = UINT2PTR(machp()->MMU.pml4->va);
+	pte = UINT2PTR(machp()->MMU.root->va);
 	pte += x;
-	prev = machp()->MMU.pml4;
+	prev = machp()->MMU.root;
 
-	for(lvl = 3; lvl >= 0; lvl--){
+	if (DBGFLG) print("starting PTE at l2 is %p\n", pte);
+	for(lvl = 2; lvl >= 0; lvl--){
 		if(user){
 			if(pgsz == 2*MiB && lvl == 1)	 /* use 2M */
 				break;
@@ -479,49 +516,59 @@ mmuput(uintptr_t va, Page *pg, uint attr)
 			if(page->prev == prev && page->daddr == x){
 				if(*pte == 0){
 					print("mmu: jmk and nemo had fun\n");
-					*pte = PPN(page->pa)|PteU|PteRW|PteP;
+					*pte = (PPN(page->pa)>>2)|PteP;
+					if (DBGFLG) print("level %d: set pte %p to 0x%llx for pa %p\n", lvl, pte, *pte, pa);
 				}
 				break;
 			}
 
 		if(page == nil){
-			if(up->MMU.mmuptp[0] == nil)
+			if(up->MMU.mmuptp[0] == nil) {
 				page = mmuptpalloc();
-			else {
+				if (DBGFLG) print("\tallocated page %p\n", page);
+			} else {
 				page = up->MMU.mmuptp[0];
 				up->MMU.mmuptp[0] = page->next;
+				if (DBGFLG) print("\tReused page %p\n", page);
 			}
 			page->daddr = x;
 			page->next = up->MMU.mmuptp[lvl];
 			up->MMU.mmuptp[lvl] = page;
 			page->prev = prev;
-			*pte = PPN(page->pa)|PteU|PteRW|PteP;
-			if(lvl == 3 && x >= machp()->MMU.pml4->daddr)
-				machp()->MMU.pml4->daddr = x+1;
+			*pte = (PPN(page->pa)>>2)|PteP;
+			if (DBGFLG) print("\tlevel %d: set pte %p to 0x%llx for pa %p\n", lvl, pte, *pte, PPN(page->pa));
+			if(lvl == 2 && x >= machp()->MMU.root->daddr)
+				machp()->MMU.root->daddr = x+1;
 		}
 		x = PTLX(va, lvl-1);
+		if (DBGFLG) print("\tptlx(%p,%d) is %p\n", va, lvl-1,x);
 
-		ppn = PPN(*pte);
-		if(ppn == 0)
+		ppage = PTE2PA(*pte);
+		if (DBGFLG) print("\tpa for pte %p val 0x%llx ppage %p\n", pte, *pte, ppage);
+		if(ppage == 0)
 			panic("mmuput: ppn=0 l%d pte %#p = %#P\n", lvl, pte, *pte);
 
-		pte = UINT2PTR(KADDR(ppn));
+		pte = UINT2PTR(KADDR(ppage));
 		pte += x;
+		if (DBGFLG) print("\tpte for next iteration is %p\n", pte);
 		prev = page;
 	}
 
+	if (DBGFLG) print("\tAFTER LOOP pte %p val 0x%llx ppn %p\n", pte, *pte, pa);
 	if(DBGFLG)
-		checkpte(ppn, pte);
-	*pte = pa|PteU;
+		checkpte(ppage, pte);
+	*pte = (pa>>2)|PteU;
+	if (DBGFLG) print("\tAFTER SET pte %p val 0x%llx ppn %p\n", pte, *pte, pa);
 
 	if(user)
 		switch(pgsz){
 		case 2*MiB:
 		case 1*GiB:
-			*pte |= attr & PteFinal | PteP;
+			*pte |= attr | PteFinal | PteP | 0x1f;
+			if (DBGFLG) print("\tUSER PAGE pte %p val 0x%llx\n", pte, *pte);
 			break;
 		default:
-			panic("mmuput: user pages must be 2M or 1G");
+			panic("\tmmuput: user pages must be 2M or 1G");
 		}
 	splx(pl);
 
@@ -532,12 +579,14 @@ mmuput(uintptr_t va, Page *pg, uint attr)
 	}
 
 	invlpg(va);			/* only if old entry valid? */
+	//dumpmmuwalk(va);
+	//hexdump((void *)va, 16);
+	if (DBGFLG) print("returning from mmuput\n");
 }
 
 #if 0
 static Lock mmukmaplock;
 #endif
-static Lock vmaplock;
 
 #define PML4X(v)	PTLX((v), 3)
 #define PDPX(v)		PTLX((v), 2)
@@ -552,227 +601,26 @@ mmukmapsync(uint64_t va)
 	return 0;
 }
 
-#if 0
-static PTE
-pdeget(uintptr_t va)
-{
-	PTE *pdp;
-
-	if(va < 0xffffffffc0000000ull)
-		panic("pdeget(%#p)", va);
-
-	pdp = (PTE*)(PDMAP+PDX(PDMAP)*4096);
-
-	return pdp[PDX(va)];
-}
-
-#endif
-/*
- * Add kernel mappings for pa -> va for a section of size bytes.
- * Called only after the va range is known to be unoccupied.
- */
-static int
-pdmap(uintptr_t pa, int attr, uintptr_t va, usize size)
-{
-	uintptr_t pae;
-	PTE *pd, *pde, *pt, *pte;
-	int pdx, pgsz;
-	Page *pg;
-
-	pd = (PTE*)(PDMAP+PDX(PDMAP)*4096);
-
-	for(pae = pa + size; pa < pae; pa += pgsz){
-		pdx = PDX(va);
-		pde = &pd[pdx];
-
-		/*
-		 * Check if it can be mapped using a big page,
-		 * i.e. is big enough and starts on a suitable boundary.
-		 * Assume processor can do it.
-		 */
-		if(ALIGNED(pa, PGLSZ(1)) && ALIGNED(va, PGLSZ(1)) && (pae-pa) >= PGLSZ(1)){
-			assert(*pde == 0);
-			/* attr had better include one of Pte{W,R,X}*/
-			*pde = pa|attr|PteP;
-			pgsz = PGLSZ(1);
-		}
-		else{
-			if(*pde == 0){
-				pg = mmuptpalloc();
-				assert(pg != nil && pg->pa != 0);
-				*pde = pg->pa|PteRW|PteP;
-				memset((PTE*)(PDMAP+pdx*4096), 0, 4096);
-			}
-			assert(*pde != 0);
-
-			pt = (PTE*)(PDMAP+pdx*4096);
-			pte = &pt[PTX(va)];
-			assert(!(*pte & PteP));
-			*pte = pa|attr|PteP;
-			pgsz = PGLSZ(0);
-		}
-		va += pgsz;
-	}
-
-	return 0;
-}
-
-static int
-findhole(PTE* a, int n, int count)
+// findKSeg2 finds kseg2, i.e., the lowest virtual
+// address mapped by firmware. We need to know this so we can
+// correctly and easily compute KADDR and PADDR.
+// TODO: actually to it.
+// It is *possible* that we'll be able to pick this up from
+// the configstring.
+void *
+findKSeg2(void)
 {
-	int have, i;
-
-	have = 0;
-	for(i = 0; i < n; i++){
-		if(a[i] == 0)
-			have++;
-		else
-			have = 0;
-		if(have >= count)
-			return i+1 - have;
-	}
-
-	return -1;
+	// return the Sv39 address that we know coreboot
+	// set up.
+	return (void *)(~0ULL<<38);
 }
-
-/*
- * Look for free space in the vmap.
- */
-static uintptr_t
-vmapalloc(usize size)
-{
-	int i, n, o;
-	PTE *pd, *pt;
-	int pdsz, ptsz;
-
-	pd = (PTE*)(PDMAP+PDX(PDMAP)*4096);
-	pd += PDX(VMAP);
-	pdsz = VMAPSZ/PGLSZ(1);
-
-	/*
-	 * Look directly in the PD entries if the size is
-	 * larger than the range mapped by a single entry.
-	 */
-	if(size >= PGLSZ(1)){
-		n = HOWMANY(size, PGLSZ(1));
-		if((o = findhole(pd, pdsz, n)) != -1)
-			return VMAP + o*PGLSZ(1);
-		return 0;
-	}
-
-	/*
-	 * Size is smaller than that mapped by a single PD entry.
-	 * Look for an already mapped PT page that has room.
-	 */
-	n = HOWMANY(size, PGLSZ(0));
-	ptsz = PGLSZ(0)/sizeof(PTE);
-	for(i = 0; i < pdsz; i++){
-		if(!(pd[i] & PteP) || (pd[i] & PteFinal))
-			continue;
-
-		pt = (PTE*)(PDMAP+(PDX(VMAP)+i)*4096);
-		if((o = findhole(pt, ptsz, n)) != -1)
-			return VMAP + i*PGLSZ(1) + o*PGLSZ(0);
-	}
-
-	/*
-	 * Nothing suitable, start using a new PD entry.
-	 */
-	if((o = findhole(pd, pdsz, 1)) != -1)
-		return VMAP + o*PGLSZ(1);
-
-	return 0;
-}
-
-/*
- * KSEG0 maps low memory.
- * KSEG2 maps almost all memory, but starting at an address determined
- * by the address space map (see asm.c).
- * Thus, almost everything in physical memory is already mapped, but
- * there are things that fall in the gap
- * (acpi tables, device memory-mapped registers, etc.)
- * for those things, we also want to disable caching.
- * vmap() is required to access them.
- */
-void*
-vmap(uintptr_t pa, usize size)
-{
-	uintptr_t va;
-	usize o, sz;
-
-	DBG("vmap(%#p, %lu) pc=%#p\n", pa, size, getcallerpc());
-
-	if(machp()->machno != 0)
-		print("vmap: machp()->machno != 0");
-
-	/*
-	 * This is incomplete; the checks are not comprehensive
-	 * enough.
-	 * Sometimes the request is for an already-mapped piece
-	 * of low memory, in which case just return a good value
-	 * and hope that a corresponding vunmap of the address
-	 * will have the same address.
-	 * To do this properly will require keeping track of the
-	 * mappings; perhaps something like kmap, but kmap probably
-	 * can't be used early enough for some of the uses.
-	 */
-	if(pa+size < 1ull*MiB)
-		return KADDR(pa);
-	if(pa < 1ull*MiB)
-		return nil;
-
-	/*
-	 * Might be asking for less than a page.
-	 * This should have a smaller granularity if
-	 * the page size is large.
-	 */
-	o = pa & ((1<<PGSHFT)-1);
-	pa -= o;
-	sz = ROUNDUP(size+o, PGSZ);
-
-	if(pa == 0){
-		print("vmap(0, %lu) pc=%#p\n", size, getcallerpc());
-		return nil;
-	}
-	ilock(&vmaplock);
-	if((va = vmapalloc(sz)) == 0 || pdmap(pa, /*PtePCD|*/PteRW, va, sz) < 0){
-		iunlock(&vmaplock);
-		return nil;
-	}
-	iunlock(&vmaplock);
-
-	DBG("vmap(%#p, %lu) => %#p\n", pa+o, size, va+o);
-
-	return UINT2PTR(va + o);
-}
-
-void
-vunmap(void* v, usize size)
-{
-	uintptr_t va;
-
-	DBG("vunmap(%#p, %lu)\n", v, size);
-
-	if(machp()->machno != 0)
-		print("vmap: machp()->machno != 0");
-
-	/*
-	 * See the comments above in vmap.
-	 */
-	va = PTR2UINT(v);
-	if(va >= KZERO && va+size < KZERO+1ull*MiB)
-		return;
-
-	/*
-	 * Here will have to deal with releasing any
-	 * resources used for the allocation (e.g. page table
-	 * pages).
-	 */
-	DBG("vunmap(%#p, %lu)\n", v, size);
-}
-
+/* mmuwalk will walk the page tables as far as we ask (level)
+ * or as far as possible (you might hit a tera/giga/mega PTE).
+ * If it gets a valid PTE it will return it in ret; test for
+ * validity by testing PetP. To see how far it got, check
+ * the return value. */
 int
-mmuwalk(PTE* pml4, uintptr_t va, int level, PTE** ret,
+mmuwalk(PTE* root, uintptr_t va, int level, PTE** ret,
 	uint64_t (*alloc)(usize))
 {
 	int l;
@@ -780,12 +628,18 @@ mmuwalk(PTE* pml4, uintptr_t va, int level, PTE** ret,
 	PTE *pte;
 
 	Mpl pl;
-
 	pl = splhi();
-	if(DBGFLG > 1)
-		DBG("mmuwalk%d: va %#p level %d\n", machp()->machno, va, level);
-	pte = &pml4[PTLX(va, 3)];
-	for(l = 3; l >= 0; l--){
+	if(DBGFLG > 1) {
+		print("mmuwalk%d: va %#p level %d\n", machp()->machno, va, level);
+		print("PTLX(%p, 2) is 0x%x\n", va, PTLX(va,2));
+		print("root is %p\n", root);
+	}
+	pte = &root[PTLX(va, 2)];
+	if(DBGFLG > 1) {
+		print("pte is %p\n", pte);
+		print("*pte is %p\n", *pte);
+	}
+	for(l = 2; l >= 0; l--){
 		if(l == level)
 			break;
 		if(!(*pte & PteP)){
@@ -799,8 +653,12 @@ mmuwalk(PTE* pml4, uintptr_t va, int level, PTE** ret,
 		}
 		else if(*pte & PteFinal)
 			break;
-		pte = UINT2PTR(KADDR(PPN(*pte)));
+		pte = UINT2PTR(KADDR((*pte&~0x3ff)<<2)); // PPN(*pte)));
+		if (DBGFLG > 1)
+			print("pte is %p: ", pte);
 		pte += PTLX(va, l-1);
+		if (DBGFLG > 1)
+			print("and pte after index is %p\n", pte);
 	}
 	*ret = pte;
 	splx(pl);
@@ -812,40 +670,49 @@ mmuphysaddr(uintptr_t va)
 {
 	int l;
 	PTE *pte;
+	uint64_t ppn;
 	uintmem mask, pa;
 
+msg("mmyphysaddr\n");
 	/*
 	 * Given a VA, find the PA.
 	 * This is probably not the right interface,
 	 * but will do as an experiment. Usual
 	 * question, should va be void* or uintptr?
 	 */
-	l = mmuwalk(UINT2PTR(machp()->MMU.pml4->va), va, 0, &pte, nil);
-	DBG("physaddr: va %#p l %d\n", va, l);
+	print("machp() %p \n", machp());
+	print("mahcp()->MMU.root %p\n", machp()->MMU.root);
+	print("... va  %p\n", machp()->MMU.root->va);
+	l = mmuwalk(UINT2PTR(machp()->MMU.root->va), va, 0, &pte, nil);
+	print("pte is %p *pte is 0x%llx\n", pte, *pte);
+	print("physaddr: va %#p l %d\n", va, l);
 	if(l < 0)
 		return ~0;
 
+	ppn = (*pte & ~0x3ff) << 2;
+	print("PPN from PTE is %llx\n", ppn);
 	mask = PGLSZ(l)-1;
-	pa = (*pte & ~mask) + (va & mask);
+	pa = (ppn & ~mask) + (va & mask);
+	print("physaddr: mask is %llx, ~mask %llx, ppn & ~mask %llx, \n", mask, ~mask, ppn & ~mask);
 
-	DBG("physaddr: l %d va %#p pa %#llx\n", l, va, pa);
+	print("physaddr: RESULT: l %d va %#p pa %#llx\n", l, va, pa);
 
 	return pa;
 }
 
-Page mach0pml4;
-
+/* to accomodate the weirdness of the rv64 modes, we're going to leave it as a 4
+ * level PT, and fake up the PML4 with one entry when it's 3 levels. Later, we want
+ * to be smarter, but a lot of our code is pretty wired to assume 4 level PT and I'm
+ * not wanting to just rip it all out. */
 void
 mmuinit(void)
 {
-	panic("mmuinit");
-#if 0
 	uint8_t *p;
-	Page *page;
-	uint64_t o, pa, r, sz;
+	uint64_t o, pa, sz, n;
 
-	archmmu();
-	DBG("mach%d: %#p pml4 %#p npgsz %d\n", machp()->machno, machp(), machp()->MMU.pml4, sys->npgsz);
+	n = archmmu();
+	print("%d page sizes\n", n);
+	print("mach%d: %#p root %#p npgsz %d\n", machp()->machno, machp(), machp()->MMU.root, sys->npgsz);
 
 	if(machp()->machno != 0){
 		/* NIX: KLUDGE: Has to go when each mach is using
@@ -853,30 +720,48 @@ mmuinit(void)
 		 */
 		p = UINT2PTR(machp()->stack);
 		p += MACHSTKSZ;
-
-		memmove(p, UINT2PTR(mach0pml4.va), PTSZ);
-		machp()->MMU.pml4 = &machp()->MMU.pml4kludge;
-		machp()->MMU.pml4->va = PTR2UINT(p);
-		machp()->MMU.pml4->pa = PADDR(p);
-		machp()->MMU.pml4->daddr = mach0pml4.daddr;	/* # of user mappings in pml4 */
-
-		r = rdmsr(Efer);
-		r |= Nxe;
-		wrmsr(Efer, r);
-		rootput(machp()->MMU.pml4->pa);
-		DBG("m %#p pml4 %#p\n", machp(), machp()->MMU.pml4);
+		panic("not yet");
+#if 0
+		memmove(p, UINT2PTR(mach0root.va), PTSZ);
+		machp()->MMU.root = &machp()->MMU.root;
+		machp()->MMU.root->va = PTR2UINT(p);
+		machp()->MMU.root->pa = PADDR(p);
+		machp()->MMU.root->daddr = mach0root.daddr;	/* # of user mappings in root */
+
+		rootput(machp()->MMU.root->pa);
+		print("m %#p root %#p\n", machp(), machp()->MMU.root);
+#endif
 		return;
 	}
 
-	page = &mach0pml4;
-	page->pa = read_csr(sptbr);
-	page->va = PTR2UINT(KADDR(page->pa));
+	machp()->MMU.root = &sys->root;
 
-	machp()->MMU.pml4 = page;
+	uintptr_t PhysicalRoot = read_csr(sptbr)<<12;
+	PTE *root = KADDR(PhysicalRoot);
+	print("Physical root is 0x%llx and root 0x %p\n", PhysicalRoot, root);
+	PTE *KzeroPTE;
+	/* As it happens, as this point, we don't know the number of page table levels.
+	 * But a walk to "level 4" will work even if it's only 3, and we can use that
+	 * information to know what to do. Further, KSEG0 is the last 2M so this will
+	 * get us the last PTE on either an L3 or L2 pte page */
+	int l;
+	if((l = mmuwalk(root, KSEG0, 2, &KzeroPTE, nil)) < 0) {
+		panic("Can't walk to PtePML2");
+	}
+	print("KzeroPTE is 0x%llx\n", KzeroPTE);
+	int PTLevels = (*KzeroPTE>>9)&3;
+	switch(PTLevels) {
+	default:
+		panic("unsupported number of page table levels: %d", PTLevels);
+		break;
+	case 0:
+		machp()->MMU.root->pa = PhysicalRoot;
+		print("root is 0x%x\n", machp()->MMU.root->pa);
+		machp()->MMU.root->va = (uintptr_t) KADDR(machp()->MMU.root->pa);
+		break;
+	}
 
-	r = rdmsr(Efer);
-	r |= Nxe;
-	wrmsr(Efer, r);
+	print("mach%d: %#p root %#p npgsz %d\n", machp()->machno, machp(), machp()->MMU.root, sys->npgsz);
 
 	/*
 	 * Set up the various kernel memory allocator limits:
@@ -893,33 +778,37 @@ mmuinit(void)
 	 * This is set up here so meminit can map appropriately.
 	 */
 	o = sys->pmstart;
+print("sys->pmstart is %p\n", o);
 	sz = ROUNDUP(o, 4*MiB) - o;
+print("Size is 0x%x\n", sz);
 	pa = asmalloc(0, sz, 1, 0);
 	if(pa != o)
 		panic("mmuinit: pa %#llx memstart %#llx\n", pa, o);
 	sys->pmstart += sz;
 
 	sys->vmstart = KSEG0;
+print("Going to set vmunused to %p + 0x%x\n", sys->vmstart, ROUNDUP(o, 4*KiB));
+	/* more issues with arithmetic since physmem is at 80000000 */
+	o &= 0x7fffffff;
 	sys->vmunused = sys->vmstart + ROUNDUP(o, 4*KiB);
-	sys->vmunmapped = sys->vmstart + o + sz;
 	sys->vmend = sys->vmstart + TMFM;
 
+	// on amd64, this was set to just the end of the kernel, because
+	// only that much was mapped, and also vmap required a lot of
+	// free *address space* (not memory, *address space*) for the
+	// vmap functions. vmap was a hack we intended to remove.
+	// It's still there. But we can get rid of it on riscv.
+	// There's lots more to do but at least vmap is gone,
+	// as is the PDMAP hack, which was also supposed to
+	// be temporary.
+	// TODO: We get much further now but still
+	// die in meminit(). When that's fixed remove
+	// this TODO.
+	sys->vmunmapped = sys->vmend;
+
 	print("mmuinit: vmstart %#p vmunused %#p vmunmapped %#p vmend %#p\n",
 		sys->vmstart, sys->vmunused, sys->vmunmapped, sys->vmend);
-
-	/*
-	 * Set up the map for PD entry access by inserting
-	 * the relevant PDP entry into the PD. It's equivalent
-	 * to PADDR(sys->pd)|PteRW|PteP.
-	 *
-	 */
-	sys->pd[PDX(PDMAP)] = sys->pdp[PDPX(PDMAP)] & ~(PteD|PteA);
-	print("sys->pd %#p %#p\n", sys->pd[PDX(PDMAP)], sys->pdp[PDPX(PDMAP)]);
-	assert((pdeget(PDMAP) & ~(PteD|PteA)) == (PADDR(sys->pd)|PteRW|PteP));
-
-
 	dumpmmuwalk(KZERO);
 
 	mmuphysaddr(PTR2UINT(end));
-#endif
 }

+ 3 - 0
sys/src/9/riscv/physalloc.c

@@ -22,6 +22,8 @@
 #define ISPOWEROF2(x)	(((x) != 0) && !((x) & ((x)-1)))
 #define UNO		((uintmem)1)
 
+#undef DBG
+#define DBG print
 enum {
 	BKmin		= 21,			/* Minimum lg2 */
 	BKmax		= 30,			/* Maximum lg2 */
@@ -371,6 +373,7 @@ physalloc(uint64_t size, int *colorp, void *tag)
 					*colorp = i;
 					return m;
 				}
+print("physalloc: return %p\n", m);
 	return m;
 }
 

+ 3 - 56
sys/src/9/riscv/qmalloc.c

@@ -265,65 +265,12 @@ qmallocalign(usize nbytes, uintptr_t align, int32_t offset, usize span)
 	return p+1;
 }
 
+/* Force it to allocate on 64 byte boundaries. I want to guarantee this happens as
+ * I don't want to take alignment traps. */
 static void*
 qmalloc(usize nbytes)
 {
-	Qlist *qlist;
-	Header *p, *q;
-	uint nunits, n;
-
-///* FIXME: (ignore for now)
-	if(nbytes == 0)
-		return nil;
-//*/
-
-	qstats[QSmalloc]++;
-	nunits = NUNITS(nbytes);
-	if(nunits <= NQUICK){
-		qlist = &QLIST[nunits];
-		QLOCK(&qlist->lk);
-		if((p = qlist->first) != nil){
-			qlist->first = p->s.next;
-			qlist->nalloc++;
-			QUNLOCK(&qlist->lk);
-			p->s.next = &checkval;
-			return p+1;
-		}
-		QUNLOCK(&qlist->lk);
-	}
-
-	MLOCK;
-	if(nunits > tailsize) {
-		/* hard way */
-		if((q = rover) != nil){
-			do {
-				p = q->s.next;
-				if(p->s.size >= nunits) {
-					if(p->s.size > nunits) {
-						p->s.size -= nunits;
-						p += p->s.size;
-						p->s.size = nunits;
-					} else
-						q->s.next = p->s.next;
-					p->s.next = &checkval;
-					rover = q;
-					qstats[QSmallocrover]++;
-					MUNLOCK;
-					return p+1;
-				}
-			} while((q = p) != rover);
-		}
-		if((n = morecore(nunits)) == 0){
-			MUNLOCK;
-			return nil;
-		}
-		tailsize += n;
-	}
-	qstats[QSmalloctail]++;
-	tailalloc(p, nunits);
-	MUNLOCK;
-
-	return p+1;
+	return qmallocalign(nbytes, 64, 0, 0);
 }
 
 static void

+ 1 - 1
sys/src/9/riscv/spike_util.h

@@ -65,7 +65,7 @@ uintptr_t mcall_query_memory(uintptr_t id, memory_block_info *p);
 uintptr_t mcall_hart_id(void);
 uintptr_t htif_interrupt(uintptr_t mcause, uintptr_t* regs);
 uintptr_t mcall_console_putchar(uint8_t ch);
-void testPrint(void);
+void putchar(void);
 uintptr_t mcall_dev_req(sbi_device_message *m);
 uintptr_t mcall_dev_resp(void);
 uintptr_t mcall_set_timer(unsigned long long when);

+ 38 - 0
sys/src/9/riscv/spl.c

@@ -0,0 +1,38 @@
+#include <u.h>
+#include <libc.h>
+#include <ureg.h>
+#include "encoding.h"
+
+
+/* these are declared in this file as we do not want them externally visible.
+ * inline assembly is not allowed in harvey.
+ */
+
+int64_t _splhi(void);
+int64_t _spllo(void);
+
+// splhi and spllo return 1 if we were at splhi. This is used in splx, below.
+int splhi(void)
+{
+	uint64_t cur;
+	cur = read_csr(sstatus);
+	_splhi();
+	return !(cur & 2);
+}
+
+int spllo(void)
+{
+	uint64_t cur;
+	cur = read_csr(sstatus);
+	_spllo();
+	return !(cur & 2);
+}
+
+void splx(int s)
+{
+	if (s)
+		_splhi();
+	else
+		_spllo();
+}
+

+ 27 - 17
sys/src/9/riscv/syscall.c

@@ -225,7 +225,7 @@ noerrorsleft(void)
 	}
 }
 
-int printallsyscalls;
+int printallsyscalls = 0;
 
 void
 syscall(unsigned int scallnr, Ureg *ureg)
@@ -233,6 +233,8 @@ syscall(unsigned int scallnr, Ureg *ureg)
 	// can only handle 6 args right now.
 	uintptr_t a0, a1, a2, a3;
 	uintptr_t a4, a5;
+	if (0 && printallsyscalls)
+		dumpgpr(ureg);
 
 	a0 = ureg->a0;
 	a1 = ureg->a1;
@@ -241,7 +243,7 @@ syscall(unsigned int scallnr, Ureg *ureg)
 	a4 = ureg->a4;
 	a5 = ureg->a5;
 	Proc *up = externup();
-	if (0) iprint("Syscall %d, %lx, %lx, %lx %lx %lx %lx\n", scallnr, a0, a1, a2, a3, a4, a5);
+	if (1) iprint("Syscall %d, %lx, %lx, %lx %lx %lx %lx\n", scallnr, a0, a1, a2, a3, a4, a5);
 	char *e;
 	uintptr_t	sp;
 	int s;
@@ -249,9 +251,8 @@ syscall(unsigned int scallnr, Ureg *ureg)
 	Ar0 ar0;
 	static Ar0 zar0;
 
-	panic("test userureg");
-	//if(!userureg(ureg))
-		//panic("syscall: cs %#llx\n", ureg->cs);
+	if(!userureg(ureg))
+		panic("syscall: userureg is false; ip %#llx\n", ureg->ip);
 
 	cycles(&up->kentry);
 
@@ -262,13 +263,14 @@ syscall(unsigned int scallnr, Ureg *ureg)
 	up->pc = ureg->ip;
 	up->dbgreg = ureg;
 	sp = ureg->sp;
+	//print("ureg -> sp says %p\n", ureg->sp);
 	startns = stopns = 0;
-	if (0) hi("so far syscall!\n");
+	if (0) print("so far syscall!\n");
 	if (up->pid == 0 || printallsyscalls) {
 		syscallfmt('E', scallnr, nil, startns, stopns, a0, a1, a2, a3, a4, a5);
 		if(up->syscalltrace) {
 			print("E %s\n", up->syscalltrace);
-			free(up->syscalltrace);
+			//free(up->syscalltrace);
 			up->syscalltrace = nil;
 		}
 	}
@@ -292,7 +294,7 @@ syscall(unsigned int scallnr, Ureg *ureg)
 		up->syscalltrace = nil;
 		startns = todget(nil);
 	}
-	if (0) hi("more syscall!\n");
+	if (0) print("more syscall!\n");
 	up->scallnr = scallnr;
 	if(scallnr == RFORK)