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