summaryrefslogtreecommitdiffstats
path: root/sys/boot/sparc64/loader/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/sparc64/loader/main.c')
-rw-r--r--sys/boot/sparc64/loader/main.c149
1 files changed, 115 insertions, 34 deletions
diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c
index 604e792..4c869da 100644
--- a/sys/boot/sparc64/loader/main.c
+++ b/sys/boot/sparc64/loader/main.c
@@ -46,16 +46,19 @@ __FBSDID("$FreeBSD$");
*/
#include <stand.h>
-#include <sys/exec.h>
#include <sys/param.h>
-#include <sys/queue.h>
+#include <sys/exec.h>
#include <sys/linker.h>
+#include <sys/queue.h>
#include <sys/types.h>
#include <vm/vm.h>
#include <machine/asi.h>
+#include <machine/cmt.h>
#include <machine/cpufunc.h>
#include <machine/elf.h>
+#include <machine/fireplane.h>
+#include <machine/jbus.h>
#include <machine/lsu.h>
#include <machine/metadata.h>
#include <machine/tte.h>
@@ -68,6 +71,12 @@ __FBSDID("$FreeBSD$");
#include "libofw.h"
#include "dev_net.h"
+#ifndef CTASSERT
+#define CTASSERT(x) _CTASSERT(x, __LINE__)
+#define _CTASSERT(x, y) __CTASSERT(x, y)
+#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1]
+#endif
+
extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
enum {
@@ -76,6 +85,9 @@ enum {
LOADSZ = 0x1000000 /* for kernel and modules */
};
+/* At least Sun Fire V1280 require page sized allocations to be claimed. */
+CTASSERT(HEAPSZ % PAGE_SIZE == 0);
+
static struct mmu_ops {
void (*tlb_init)(void);
int (*mmu_mapin)(vm_offset_t va, vm_size_t len);
@@ -84,11 +96,11 @@ static struct mmu_ops {
typedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3,
void *openfirmware);
-static inline u_long dtlb_get_data_sun4u(int slot);
-static void dtlb_enter_sun4u(u_long vpn, u_long data);
+static inline u_long dtlb_get_data_sun4u(u_int);
+static void dtlb_enter_sun4u(u_long, u_long);
static vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t);
-static inline u_long itlb_get_data_sun4u(int slot);
-static void itlb_enter_sun4u(u_long vpn, u_long data);
+static inline u_long itlb_get_data_sun4u(u_int);
+static void itlb_enter_sun4u(u_long, u_long);
static vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t);
static void itlb_relocate_locked0_sun4u(void);
extern vm_offset_t md_load(char *, vm_offset_t *);
@@ -104,6 +116,9 @@ static int __elfN(exec)(struct preloaded_file *);
static int mmu_mapin_sun4u(vm_offset_t, vm_size_t);
static int mmu_mapin_sun4v(vm_offset_t, vm_size_t);
static vm_offset_t init_heap(void);
+static phandle_t find_bsp_sun4u(phandle_t, uint32_t);
+const char *cpu_cpuid_prop_sun4u(void);
+uint32_t cpu_get_mid_sun4u(void);
static void tlb_init_sun4u(void);
static void tlb_init_sun4v(void);
@@ -120,11 +135,11 @@ static struct mmu_ops mmu_ops_sun4v = { tlb_init_sun4v, mmu_mapin_sun4v };
/* sun4u */
struct tlb_entry *dtlb_store;
struct tlb_entry *itlb_store;
-int dtlb_slot;
-int itlb_slot;
+u_int dtlb_slot;
+u_int itlb_slot;
int cpu_impl;
-static int dtlb_slot_max;
-static int itlb_slot_max;
+static u_int dtlb_slot_max;
+static u_int itlb_slot_max;
/* sun4v */
static struct tlb_entry *tlb_store;
@@ -398,7 +413,7 @@ __elfN(exec)(struct preloaded_file *fp)
}
static inline u_long
-dtlb_get_data_sun4u(int slot)
+dtlb_get_data_sun4u(u_int slot)
{
/*
@@ -410,7 +425,7 @@ dtlb_get_data_sun4u(int slot)
}
static inline u_long
-itlb_get_data_sun4u(int slot)
+itlb_get_data_sun4u(u_int slot)
{
/*
@@ -668,33 +683,98 @@ init_heap(void)
return (heapva);
}
+static phandle_t
+find_bsp_sun4u(phandle_t node, uint32_t bspid)
+{
+ char type[sizeof("cpu")];
+ phandle_t child;
+ uint32_t cpuid;
+
+ for (; node > 0; node = OF_peer(node)) {
+ child = OF_child(node);
+ if (child > 0) {
+ child = find_bsp_sun4u(child, bspid);
+ if (child > 0)
+ return (child);
+ } else {
+ if (OF_getprop(node, "device_type", type,
+ sizeof(type)) <= 0)
+ continue;
+ if (strcmp(type, "cpu") != 0)
+ continue;
+ if (OF_getprop(node, cpu_cpuid_prop_sun4u(), &cpuid,
+ sizeof(cpuid)) <= 0)
+ continue;
+ if (cpuid == bspid)
+ return (node);
+ }
+ }
+ return (0);
+}
+
+const char *
+cpu_cpuid_prop_sun4u(void)
+{
+
+ switch (cpu_impl) {
+ case CPU_IMPL_SPARC64:
+ case CPU_IMPL_ULTRASPARCI:
+ case CPU_IMPL_ULTRASPARCII:
+ case CPU_IMPL_ULTRASPARCIIi:
+ case CPU_IMPL_ULTRASPARCIIe:
+ return ("upa-portid");
+ case CPU_IMPL_ULTRASPARCIII:
+ case CPU_IMPL_ULTRASPARCIIIp:
+ case CPU_IMPL_ULTRASPARCIIIi:
+ case CPU_IMPL_ULTRASPARCIIIip:
+ return ("portid");
+ case CPU_IMPL_ULTRASPARCIV:
+ case CPU_IMPL_ULTRASPARCIVp:
+ return ("cpuid");
+ default:
+ return ("");
+ }
+}
+
+uint32_t
+cpu_get_mid_sun4u(void)
+{
+
+ switch (cpu_impl) {
+ case CPU_IMPL_SPARC64:
+ case CPU_IMPL_ULTRASPARCI:
+ case CPU_IMPL_ULTRASPARCII:
+ case CPU_IMPL_ULTRASPARCIIi:
+ case CPU_IMPL_ULTRASPARCIIe:
+ return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)));
+ case CPU_IMPL_ULTRASPARCIII:
+ case CPU_IMPL_ULTRASPARCIIIp:
+ return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG,
+ ASI_FIREPLANE_CONFIG_REG)));
+ case CPU_IMPL_ULTRASPARCIIIi:
+ case CPU_IMPL_ULTRASPARCIIIip:
+ return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG)));
+ case CPU_IMPL_ULTRASPARCIV:
+ case CPU_IMPL_ULTRASPARCIVp:
+ return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID)));
+ default:
+ return (0);
+ }
+}
+
static void
tlb_init_sun4u(void)
{
- phandle_t child;
- char buf[128];
- u_int bootcpu;
- u_int cpu;
+ phandle_t bsp;
cpu_impl = VER_IMPL(rdpr(ver));
- bootcpu = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG));
- for (child = OF_child(root); child != 0; child = OF_peer(child)) {
- if (OF_getprop(child, "device_type", buf, sizeof(buf)) <= 0)
- continue;
- if (strcmp(buf, "cpu") != 0)
- continue;
- if (OF_getprop(child, cpu_impl < CPU_IMPL_ULTRASPARCIII ?
- "upa-portid" : "portid", &cpu, sizeof(cpu)) <= 0)
- continue;
- if (cpu == bootcpu)
- break;
- }
- if (cpu != bootcpu)
+ bsp = find_bsp_sun4u(OF_child(root), cpu_get_mid_sun4u());
+ if (bsp == 0)
panic("%s: no node for bootcpu?!?!", __func__);
- if (OF_getprop(child, "#dtlb-entries", &dtlb_slot_max,
+ if (OF_getprop(bsp, "#dtlb-entries", &dtlb_slot_max,
sizeof(dtlb_slot_max)) == -1 ||
- OF_getprop(child, "#itlb-entries", &itlb_slot_max,
+ OF_getprop(bsp, "#itlb-entries", &itlb_slot_max,
sizeof(itlb_slot_max)) == -1)
panic("%s: can't get TLB slot max.", __func__);
@@ -749,14 +829,15 @@ main(int (*openfirm)(void *))
archsw.arch_autoload = sparc64_autoload;
archsw.arch_maphint = sparc64_maphint;
- init_heap();
- setheap((void *)heapva, (void *)(heapva + HEAPSZ));
-
/*
* Probe for a console.
*/
cons_probe();
+ if (init_heap() == (vm_offset_t)-1)
+ panic("%s: can't claim heap", __func__);
+ setheap((void *)heapva, (void *)(heapva + HEAPSZ));
+
if ((root = OF_peer(0)) == -1)
panic("%s: can't get root phandle", __func__);
OF_getprop(root, "compatible", compatible, sizeof(compatible));
OpenPOWER on IntegriCloud