Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Add support for running ofwboot on sun4v. Please no...



details:   https://anonhg.NetBSD.org/src/rev/9a61361837fa
branches:  trunk
changeset: 325142:9a61361837fa
user:      palle <palle%NetBSD.org@localhost>
date:      Sun Dec 08 14:41:28 2013 +0000

description:
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

diffstat:

 sys/arch/sparc/stand/ofwboot/Makefile           |   12 +-
 sys/arch/sparc/stand/ofwboot/loadfile_machdep.c |  282 ++++++++++++++++++++++-
 sys/arch/sparc/stand/ofwboot/version            |    3 +-
 sys/arch/sparc64/include/pte.h                  |   43 +++-
 sys/arch/sparc64/sparc64/hvcall.S               |    6 +-
 5 files changed, 322 insertions(+), 24 deletions(-)

diffs (truncated from 502 to 300 lines):

diff -r a7b78ef2da84 -r 9a61361837fa sys/arch/sparc/stand/ofwboot/Makefile
--- a/sys/arch/sparc/stand/ofwboot/Makefile     Sun Dec 08 14:37:01 2013 +0000
+++ b/sys/arch/sparc/stand/ofwboot/Makefile     Sun Dec 08 14:41:28 2013 +0000
@@ -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 @@
 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 @@
 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 @@
 srt0.o: srt0.s
        ${NORMAL_S}
 
+hvcall.o: hvcall.S
+       ${NORMAL_S}
+
+
 # Explicit dependency for this.
 boot.o: boot.c
diff -r a7b78ef2da84 -r 9a61361837fa sys/arch/sparc/stand/ofwboot/loadfile_machdep.c
--- a/sys/arch/sparc/stand/ofwboot/loadfile_machdep.c   Sun Dec 08 14:37:01 2013 +0000
+++ b/sys/arch/sparc/stand/ofwboot/loadfile_machdep.c   Sun Dec 08 14:41:28 2013 +0000
@@ -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 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 *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 @@
 static void
 tlb_init(void)
 {
+       phandle_t root;
+#ifdef SUN4V   
+       char buf[128];
+#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;
 
-       if (dtlb_store != NULL) {
-               return;
-       }
-
        bootcpu = get_cpuid();
 
        if ( (root = prom_findroot()) == -1) {
@@ -196,14 +247,35 @@
            _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");
+}
+
+#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");
        }
-
-       dtlb_slot = itlb_slot = 0;
+       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 @@
 static int
 mmu_mapin(vaddr_t rva, vsize_t len)
 {
+       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;
 
-       len  = roundup2(len + (rva & PAGE_MASK_4M), PAGE_SIZE_4M);
-       rva &= ~PAGE_MASK_4M;
-
-       tlb_init();
        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 @@
        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);
+       }
+



Home | Main Index | Thread Index | Old Index