Module Name:    src
Committed By:   palle
Date:           Sun Dec  8 14:41:28 UTC 2013

Modified Files:
        src/sys/arch/sparc/stand/ofwboot: Makefile loadfile_machdep.c version
        src/sys/arch/sparc64/include: pte.h
        src/sys/arch/sparc64/sparc64: hvcall.S

Log Message:
Add support for running ofwboot on sun4v. Please note that the kernel on sun4v 
will be loaded properly but when the kernel takes over it will crash 
immediately since the kernel is not sun4v ready yet


To generate a diff of this commit:
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/sparc/stand/ofwboot/Makefile
cvs rdiff -u -r1.10 -r1.11 \
    src/sys/arch/sparc/stand/ofwboot/loadfile_machdep.c
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/sparc/stand/ofwboot/version
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/sparc64/include/pte.h
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/sparc64/sparc64/hvcall.S

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sparc/stand/ofwboot/Makefile
diff -u src/sys/arch/sparc/stand/ofwboot/Makefile:1.30 src/sys/arch/sparc/stand/ofwboot/Makefile:1.31
--- src/sys/arch/sparc/stand/ofwboot/Makefile:1.30	Wed Aug 21 06:41:52 2013
+++ src/sys/arch/sparc/stand/ofwboot/Makefile	Sun Dec  8 14:41:28 2013
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.30 2013/08/21 06:41:52 matt Exp $
+#	$NetBSD: Makefile,v 1.31 2013/12/08 14:41:28 palle Exp $
 
 CURDIR=	${.CURDIR}
 S=	${CURDIR}/../../../..
@@ -13,6 +13,9 @@ KLINK_MACHINE=	sparc64
 PROG?=		ofwboot
 SRCS=		srt0.s Locore.c boot.c ofdev.c alloc.c net.c netif_of.c vers.c
 SRCS+=		bootinfo.c loadfile_machdep.c promlib.c prf.c isfloppy.c
+.if ${MACHINE_ARCH} == "sparc64"
+SRCS+=		hvcall.S
+.endif
 .PATH:		${S}/arch/sparc64/sparc64 ${S}/arch/sparc/stand/common
 
 # XXX SHOULD NOT NEED TO DEFINE THESE!
@@ -25,6 +28,9 @@ COPTS+=		-ffreestanding
 CWARNFLAGS+=	-Wno-main
 CFLAGS+=	${COPTS} ${CEXTRAFLAGS}
 CPPFLAGS+=	-D_STANDALONE -DSUN4U
+.if ${MACHINE_ARCH} == "sparc64"
+CPPFLAGS+=	-DSUN4V
+.endif
 CPPFLAGS+=	-DBOOT_ELF32 -DBOOT_ELF64 -DBOOT_AOUT
 CPPFLAGS+=	-DNETBOOT
 CPPFLAGS+=	-DSUPPORT_DHCP
@@ -120,5 +126,9 @@ NORMAL_S=	${CC} ${AFLAGS} ${CPPFLAGS} -c
 srt0.o: srt0.s
 	${NORMAL_S}
 
+hvcall.o: hvcall.S
+	${NORMAL_S}
+
+
 # Explicit dependency for this.
 boot.o: boot.c

Index: src/sys/arch/sparc/stand/ofwboot/loadfile_machdep.c
diff -u src/sys/arch/sparc/stand/ofwboot/loadfile_machdep.c:1.10 src/sys/arch/sparc/stand/ofwboot/loadfile_machdep.c:1.11
--- src/sys/arch/sparc/stand/ofwboot/loadfile_machdep.c:1.10	Sat May 21 16:32:00 2011
+++ src/sys/arch/sparc/stand/ofwboot/loadfile_machdep.c	Sun Dec  8 14:41:28 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: loadfile_machdep.c,v 1.10 2011/05/21 16:32:00 nakayama Exp $	*/
+/*	$NetBSD: loadfile_machdep.c,v 1.11 2013/12/08 14:41:28 palle Exp $	*/
 
 /*-
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -37,6 +37,7 @@
 #include <machine/ctlreg.h>
 #include <machine/vmparam.h>
 #include <machine/promlib.h>
+#include <machine/hypervisor.h>
 
 #include "boot.h"
 #include "openfirm.h"
@@ -58,8 +59,19 @@ extern vaddr_t	itlb_va_to_pa(vaddr_t);
 extern vaddr_t	dtlb_va_to_pa(vaddr_t);
 
 static void	tlb_init(void);
-
+static void	tlb_init_sun4u(void);
+#ifdef SUN4V
+static void	tlb_init_sun4v(void);
+#endif
+void	sparc64_finalize_tlb_sun4u(u_long);
+#ifdef SUN4V
+void	sparc64_finalize_tlb_sun4v(u_long);
+#endif
 static int	mmu_mapin(vaddr_t, vsize_t);
+static int	mmu_mapin_sun4u(vaddr_t, vsize_t);
+#ifdef SUN4V
+static int	mmu_mapin_sun4v(vaddr_t, vsize_t);
+#endif
 static ssize_t	mmu_read(int, void *, size_t);
 static void*	mmu_memcpy(void *, const void *, size_t);
 static void*	mmu_memset(void *, int, size_t);
@@ -106,6 +118,9 @@ static struct memsw {
 
 static struct memsw *memsw = &memswa[0];
 
+#ifdef SUN4V
+static int sun4v = 0;
+#endif
 
 /*
  * Check if a memory region is already mapped. Return length and virtual
@@ -158,16 +173,52 @@ kvamap_enter(uint64_t va, uint64_t len)
 static void
 tlb_init(void)
 {
-	phandle_t child;
 	phandle_t root;
+#ifdef SUN4V	
 	char buf[128];
-	u_int bootcpu;
-	u_int cpu;
+#endif	
 
 	if (dtlb_store != NULL) {
 		return;
 	}
 
+	if ( (root = prom_findroot()) == -1) {
+		panic("tlb_init: prom_findroot()");
+	}
+#ifdef SUN4V		
+	if (_prom_getprop(root, "compatible", buf, sizeof(buf)) > 0 &&
+		    strcmp(buf, "sun4v") == 0) {
+		tlb_init_sun4v();
+		sun4v = 1;
+	}
+	else {
+#endif
+		tlb_init_sun4u();
+#ifdef SUN4V		
+	}
+#endif
+
+	dtlb_store = alloc(dtlb_slot_max * sizeof(*dtlb_store));
+	itlb_store = alloc(itlb_slot_max * sizeof(*itlb_store));
+	if (dtlb_store == NULL || itlb_store == NULL) {
+		panic("tlb_init: malloc");
+	}
+
+	dtlb_slot = itlb_slot = 0;
+}
+
+/*
+ * Initialize TLB as required by MMU mapping functions - sun4u.
+ */
+static void
+tlb_init_sun4u(void)
+{
+	phandle_t child;
+	phandle_t root;
+	char buf[128];
+	u_int bootcpu;
+	u_int cpu;
+
 	bootcpu = get_cpuid();
 
 	if ( (root = prom_findroot()) == -1) {
@@ -196,14 +247,35 @@ tlb_init(void)
 	    _prom_getprop(child, "#itlb-entries", &itlb_slot_max,
 	    sizeof(itlb_slot_max)) == -1)
 		panic("tlb_init: prom_getprop");
-	dtlb_store = alloc(dtlb_slot_max * sizeof(*dtlb_store));
-	itlb_store = alloc(itlb_slot_max * sizeof(*itlb_store));
-	if (dtlb_store == NULL || itlb_store == NULL) {
-		panic("tlb_init: malloc");
-	}
+}
 
-	dtlb_slot = itlb_slot = 0;
+#ifdef SUN4V
+/*
+ * Initialize TLB as required by MMU mapping functions - sun4v.
+ */
+static void
+tlb_init_sun4v(void)
+{
+	psize_t len;
+	paddr_t pa;
+	int64_t hv_rc;
+
+	hv_mach_desc((paddr_t)NULL, &len); /* Trick to get actual length */
+	if ( !len ) {
+		panic("init_tlb: hv_mach_desc() failed");
+	}
+	pa = OF_alloc_phys(len, 16);
+	if ( pa == -1 ) {
+		panic("OF_alloc_phys() failed");
+	}
+	hv_rc = hv_mach_desc(pa, &len);
+	if (hv_rc != H_EOK) {
+		panic("hv_mach_desc() failed");
+	}
+	/* XXX dig out TLB node info - 64 is ok for loading the kernel */
+	dtlb_slot_max = itlb_slot_max = 64;
 }
+#endif
 
 /*
  * Map requested memory region with permanent 4MB pages.
@@ -211,14 +283,29 @@ tlb_init(void)
 static int
 mmu_mapin(vaddr_t rva, vsize_t len)
 {
-	uint64_t data;
-	paddr_t pa;
-	vaddr_t va, mva;
-
 	len  = roundup2(len + (rva & PAGE_MASK_4M), PAGE_SIZE_4M);
 	rva &= ~PAGE_MASK_4M;
 
 	tlb_init();
+
+#if SUN4V	
+	if ( sun4v )
+		return mmu_mapin_sun4v(rva, len);
+	else
+#endif		
+		return mmu_mapin_sun4u(rva, len);
+}
+
+/*
+ * Map requested memory region with permanent 4MB pages - sun4u.
+ */
+static int
+mmu_mapin_sun4u(vaddr_t rva, vsize_t len)
+{
+	uint64_t data;
+	paddr_t pa;
+	vaddr_t va, mva;
+
 	for (pa = (paddr_t)-1; len > 0; rva = va) {
 		if ( (len = kvamap_extract(rva, len, &va)) == 0) {
 			/* The rest is already mapped */
@@ -286,6 +373,86 @@ mmu_mapin(vaddr_t rva, vsize_t len)
 	return (0);
 }
 
+#ifdef SUN4V
+/*
+ * Map requested memory region with permanent 4MB pages - sun4v.
+ */
+static int
+mmu_mapin_sun4v(vaddr_t rva, vsize_t len)
+{
+	uint64_t data;
+	paddr_t pa;
+	vaddr_t va, mva;
+	int64_t hv_rc;
+
+	for (pa = (paddr_t)-1; len > 0; rva = va) {
+		if ( (len = kvamap_extract(rva, len, &va)) == 0) {
+			/* The rest is already mapped */
+			break;
+		}
+
+		/* Allocate a physical page, claim the virtual area */
+		if (pa == (paddr_t)-1) {
+			pa = OF_alloc_phys(PAGE_SIZE_4M, PAGE_SIZE_4M);
+			if (pa == (paddr_t)-1)
+				panic("out of memory");
+			mva = OF_claim_virt(va, PAGE_SIZE_4M);
+			if (mva != va) {
+				panic("can't claim virtual page "
+				    "(wanted %#lx, got %#lx)",
+				    va, mva);
+			}
+		}
+
+		/*
+		 * Actually, we can only allocate two pages less at
+		 * most (depending on the kernel TSB size).
+		 */
+		if (dtlb_slot >= dtlb_slot_max)
+			panic("mmu_mapin: out of dtlb_slots");
+		if (itlb_slot >= itlb_slot_max)
+			panic("mmu_mapin: out of itlb_slots");
+		
+		DPRINTF(("mmu_mapin: 0x%lx:0x%x.0x%x\n", va,
+		    hi(pa), lo(pa)));
+
+		data = SUN4V_TSB_DATA(
+			0,		/* global */
+			PGSZ_4M,	/* 4mb page */
+			pa,		/* phys.address */
+			1,		/* privileged */
+			1,		/* write */
+			1,		/* cache */
+			1,		/* alias */
+			1,		/* valid */
+			0		/* endianness */
+			);
+		data |= SUN4V_TLB_CV; /* virt.cache */
+		
+		dtlb_store[dtlb_slot].te_pa = pa;
+		dtlb_store[dtlb_slot].te_va = va;
+		dtlb_slot++;
+		hv_rc = hv_mmu_map_perm_addr(va, data, MAP_DTLB);
+		if ( hv_rc != H_EOK ) {
+			panic("hv_mmu_map_perm_addr() failed - rc = %ld", hv_rc);
+		}
+
+		kvamap_enter(va, PAGE_SIZE_4M);
+
+		pa = (paddr_t)-1;
+
+		len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len;
+		va += PAGE_SIZE_4M;
+	}
+
+	if (pa != (paddr_t)-1) {
+		OF_free_phys(pa, PAGE_SIZE_4M);
+	}
+
+	return (0);
+}
+#endif
+
 static ssize_t
 mmu_read(int f, void *addr, size_t size)
 {
@@ -434,6 +601,21 @@ sparc64_memset(void *dst, int c, size_t 
 void
 sparc64_finalize_tlb(u_long data_va)
 {
+#ifdef SUN4V
+	if ( sun4v )
+		sparc64_finalize_tlb_sun4v(data_va);
+	else
+#endif	
+		sparc64_finalize_tlb_sun4u(data_va);
+}
+
+/*
+ * Remove write permissions from text mappings in the dTLB - sun4u.
+ * Add entries in the iTLB.
+ */
+void
+sparc64_finalize_tlb_sun4u(u_long data_va)
+{
 	int i;
 	int64_t data;
 	bool writable_text = false;
@@ -471,8 +653,76 @@ sparc64_finalize_tlb(u_long data_va)
 	}
 	if (writable_text)
 		printf("WARNING: kernel text mapped writable!\n");
+
 }
 
+#ifdef SUN4V
+/*
+ * Remove write permissions from text mappings in the dTLB - sun4v.
+ * Add entries in the iTLB.
+ */
+void
+sparc64_finalize_tlb_sun4v(u_long data_va)
+{
+	int i;
+	int64_t data;
+	bool writable_text = false;
+	int64_t hv_rc;
+
+	for (i = 0; i < dtlb_slot; i++) {
+		if (dtlb_store[i].te_va >= data_va) {
+			/*
+			 * If (for whatever reason) the start of the
+			 * writable section is right at the start of
+			 * the kernel, we need to map it into the ITLB
+			 * nevertheless (and don't make it readonly).
+			 */
+			if (i == 0 && dtlb_store[i].te_va == data_va)
+				writable_text = true;
+			else
+				continue;
+		}
+
+		data = SUN4V_TSB_DATA(
+			0,		/* global */
+			PGSZ_4M,	/* 4mb page */
+			dtlb_store[i].te_pa,	/* phys.address */
+			1,		/* privileged */
+			0,		/* write */
+			1,		/* cache */
+			1,		/* alias */
+			1,		/* valid */
+			0		/* endianness */
+			);
+		data |= SUN4V_TLB_L | SUN4V_TLB_CV; /* locked, virt.cache */
+		if (!writable_text) {
+			hv_rc = hv_mmu_unmap_perm_addr(dtlb_store[i].te_va,
+			                               MAP_DTLB);
+			if ( hv_rc != H_EOK ) {
+				panic("hv_mmu_unmap_perm_addr() failed - "
+				      "rc = %ld", hv_rc);
+			}
+			hv_rc = hv_mmu_map_perm_addr(dtlb_store[i].te_va, data,
+			                             MAP_DTLB);
+			if ( hv_rc != H_EOK ) {
+				panic("hv_mmu_map_perm_addr() failed - "
+				      "rc = %ld", hv_rc);
+			}
+		}
+		
+		itlb_store[itlb_slot] = dtlb_store[i];
+		itlb_slot++;
+		hv_rc = hv_mmu_map_perm_addr(dtlb_store[i].te_va, data,
+		                             MAP_ITLB);
+		if ( hv_rc != H_EOK ) {
+			panic("hv_mmu_map_perm_addr() failed - rc = %ld", hv_rc);
+		}
+	}
+	if (writable_text)
+		printf("WARNING: kernel text mapped writable!\n");
+}
+#endif
+
 /*
  * Record kernel mappings in bootinfo structure.
  */

Index: src/sys/arch/sparc/stand/ofwboot/version
diff -u src/sys/arch/sparc/stand/ofwboot/version:1.19 src/sys/arch/sparc/stand/ofwboot/version:1.20
--- src/sys/arch/sparc/stand/ofwboot/version:1.19	Fri Apr  2 18:41:52 2010
+++ src/sys/arch/sparc/stand/ofwboot/version	Sun Dec  8 14:41:28 2013
@@ -1,4 +1,4 @@
-$NetBSD: version,v 1.19 2010/04/02 18:41:52 martin Exp $
+$NetBSD: version,v 1.20 2013/12/08 14:41:28 palle Exp $
 
 NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE.  The format of this
 file is important - make sure the entries are appended on end, last item
@@ -20,3 +20,4 @@ is taken as the current.
 1.14:	Make 3 attempts at BOOTP/DHCP for to allow for bridges and clear prior data read
 1.15:	Properly close the firmware handle before starting the kernel
 1.16:	Add support to boot with root on cd9660
+1.17:	Add support for sun4v architecture

Index: src/sys/arch/sparc64/include/pte.h
diff -u src/sys/arch/sparc64/include/pte.h:1.22 src/sys/arch/sparc64/include/pte.h:1.23
--- src/sys/arch/sparc64/include/pte.h:1.22	Fri Jan 15 15:02:48 2010
+++ src/sys/arch/sparc64/include/pte.h	Sun Dec  8 14:41:28 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: pte.h,v 1.22 2010/01/15 15:02:48 nakayama Exp $ */
+/*	$NetBSD: pte.h,v 1.23 2013/12/08 14:41:28 palle Exp $ */
 
 /*
  * Copyright (c) 1996-1999 Eduardo Horvath
@@ -222,11 +222,52 @@ typedef struct sun4u_tte pte_t;
         "b\6L\0"        "b\5CP\0"       "b\4CV\0" \
         "b\3E\0"        "b\2P\0"        "b\1W\0"        "b\0G\0"
 
+#define SUN4V_PGSZ_SHIFT	0
+#define	SUN4V_TLB_SZ(s)		(((uint64_t)(s))<<SUN4V_PGSZ_SHIFT)
+
+/* TLB data masks */
+#define SUN4V_TLB_V		0x8000000000000000LL
+#define SUN4V_TLB_8K		SUN4V_TLB_SZ(PGSZ_8K)
+#define SUN4V_TLB_64K		SUN4V_TLB_SZ(PGSZ_64K)
+#define SUN4V_TLB_512K		SUN4V_TLB_SZ(PGSZ_512K)
+#define SUN4V_TLB_4M		SUN4V_TLB_SZ(PGSZ_4M)
+#define SUN4V_TLB_SZ_MASK	0x000000000000000fLL
+#define SUN4V_TLB_NFO		0x4000000000000000LL
+#define SUN4V_TLB_IE		0x0000000000001000LL
+#define SUN4V_TLB_SOFT2_MASK	0x3f00000000000000LL
+#define SUN4V_TLB_PA_MASK	0x00ffffffffffe000LL
+#define SUN4V_TLB_SOFT_MASK	0x0000000000000030LL
+/* S/W bits */
+#define SUN4V_TLB_ACCESS	0x0000000000000010LL
+#define SUN4V_TLB_MODIFY	0x0000000000000020LL
+#define SUN4V_TLB_REAL_W	0x2000000000000000LL
+#define SUN4V_TLB_TSB_LOCK	0x1000000000000000UL
+#define SUN4V_TLB_L             SUN4V_TLB_TSB_LOCK     
+#define SUN4V_TLB_EXEC		SUN4V_TLB_X
+#define SUN4V_TLB_EXEC_ONLY	0x0200000000000000LL
+/* H/W bits */
+#define SUN4V_TLB_CACHE_MASK	0x0000000000000600LL
+#define SUN4V_TLB_CP		0x0000000000000400LL
+#define SUN4V_TLB_CV		0x0000000000000200LL
+#define SUN4V_TLB_E		0x0000000000000800LL
+#define SUN4V_TLB_P		0x0000000000000100LL
+#define SUN4V_TLB_X		0x0000000000000080LL
+#define SUN4V_TLB_W		0x0000000000000040LL
+#define SUN4V_TLB_G		0x0000000000000000LL
+
 #define TSB_DATA(g,sz,pa,priv,write,cache,aliased,valid,ie) \
 (((valid)?TLB_V:0LL)|TLB_SZ(sz)|(((uint64_t)(pa))&TLB_PA_MASK)|\
 ((cache)?((aliased)?TLB_CP:TLB_CACHE_MASK):TLB_E)|\
 ((priv)?TLB_P:0LL)|((write)?TLB_W:0LL)|((g)?TLB_G:0LL)|((ie)?TLB_IE:0LL))
 
+#define SUN4V_TSB_DATA(g,sz,pa,priv,write,cache,aliased,valid,ie) \
+(((valid)?SUN4V_TLB_V:0LL)|SUN4V_TLB_SZ(sz)|\
+(((u_int64_t)(pa))&SUN4V_TLB_PA_MASK)|\
+((cache)?((aliased)?SUN4V_TLB_CP:SUN4V_TLB_CACHE_MASK):SUN4V_TLB_E)|\
+((priv)?SUN4V_TLB_P:0LL)|((write)?SUN4V_TLB_W:0LL)|((g)?SUN4V_TLB_G:0LL)|\
+((ie)?SUN4V_TLB_IE:0LL))
+
+
 #define MMU_CACHE_VIRT	0x3
 #define MMU_CACHE_PHYS	0x2
 #define MMU_CACHE_NONE	0x0

Index: src/sys/arch/sparc64/sparc64/hvcall.S
diff -u src/sys/arch/sparc64/sparc64/hvcall.S:1.2 src/sys/arch/sparc64/sparc64/hvcall.S:1.3
--- src/sys/arch/sparc64/sparc64/hvcall.S:1.2	Sat Dec  7 16:54:43 2013
+++ src/sys/arch/sparc64/sparc64/hvcall.S	Sun Dec  8 14:41:28 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: hvcall.S,v 1.2 2013/12/07 16:54:43 palle Exp $ */
+/*	$NetBSD: hvcall.S,v 1.3 2013/12/08 14:41:28 palle Exp $ */
 /*	$OpenBSD: hvcall.S,v 1.10 2011/06/25 20:45:00 kettenis Exp $	*/
 
 /*
@@ -17,10 +17,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#if 0
-FIXME not necessary on NetBSD? fails building if present...	
-#include "assym.h"
-#endif	
 #include <machine/asm.h>
 
 #define FAST_TRAP	0x80

Reply via email to