summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2008-03-23 23:46:22 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2008-03-23 23:46:22 +0000
commit378058c8842e5f428f7d7ce81f0c12190675d45f (patch)
tree813d74f8f7524bad8192cea560fb9fc5d5aa6ffd /sys/arch
parent28243bf4755af75f511078d6ff390ccb86d6fffb (diff)
Add code to initialize CPUs on sun4v.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sparc64/include/cpu.h14
-rw-r--r--sys/arch/sparc64/sparc64/cpu.c97
-rw-r--r--sys/arch/sparc64/sparc64/pmap.c101
3 files changed, 184 insertions, 28 deletions
diff --git a/sys/arch/sparc64/include/cpu.h b/sys/arch/sparc64/include/cpu.h
index 46e45da2b06..a80575ebd1b 100644
--- a/sys/arch/sparc64/include/cpu.h
+++ b/sys/arch/sparc64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.57 2008/03/17 23:10:21 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.58 2008/03/23 23:46:21 kettenis Exp $ */
/* $NetBSD: cpu.h,v 1.28 2001/06/14 22:56:58 thorpej Exp $ */
/*
@@ -133,6 +133,18 @@ struct cpu_info {
void (*ci_spinup)(void); /* spinup routine */
void *ci_initstack;
paddr_t ci_paddr; /* Phys addr of this structure. */
+
+#ifdef SUN4V
+ struct rwindow64 ci_rw;
+ u_int64_t ci_rwsp;
+
+ paddr_t ci_mmfsa;
+ paddr_t ci_cpumq;
+ paddr_t ci_devmq;
+
+ paddr_t ci_cpuset;
+ paddr_t ci_mondo;
+#endif
};
#define CPUF_RUNNING 0x0001 /* CPU is running */
diff --git a/sys/arch/sparc64/sparc64/cpu.c b/sys/arch/sparc64/sparc64/cpu.c
index 545b146b1bf..7331682c048 100644
--- a/sys/arch/sparc64/sparc64/cpu.c
+++ b/sys/arch/sparc64/sparc64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.35 2008/03/16 22:22:15 kettenis Exp $ */
+/* $OpenBSD: cpu.c,v 1.36 2008/03/23 23:46:21 kettenis Exp $ */
/* $NetBSD: cpu.c,v 1.13 2001/05/26 21:27:15 chs Exp $ */
/*
@@ -62,6 +62,7 @@
#include <machine/cpu.h>
#include <machine/reg.h>
#include <machine/trap.h>
+#include <machine/hypervisor.h>
#include <machine/openfirm.h>
#include <machine/pmap.h>
#include <machine/sparc64.h>
@@ -78,29 +79,28 @@ struct cacheinfo cacheinfo = {
/* Linked list of all CPUs in system. */
struct cpu_info *cpus = NULL;
-struct cpu_info *alloc_cpuinfo(int);
+struct cpu_info *alloc_cpuinfo(struct mainbus_attach_args *);
/* The following are used externally (sysctl_hw). */
char machine[] = MACHINE; /* from <machine/param.h> */
char cpu_model[100];
-void cpu_hatch(void);
-
/* The CPU configuration driver. */
-static void cpu_attach(struct device *, struct device *, void *);
-int cpu_match(struct device *, void *, void *);
+int cpu_match(struct device *, void *, void *);
+void cpu_attach(struct device *, struct device *, void *);
struct cfattach cpu_ca = {
sizeof(struct device), cpu_match, cpu_attach
};
-extern struct cfdriver cpu_cd;
+void cpu_init(struct cpu_info *ci);
+void cpu_hatch(void);
#define IU_IMPL(v) ((((u_int64_t)(v))&VER_IMPL) >> VER_IMPL_SHIFT)
#define IU_VERS(v) ((((u_int64_t)(v))&VER_MASK) >> VER_MASK_SHIFT)
struct cpu_info *
-alloc_cpuinfo(int node)
+alloc_cpuinfo(struct mainbus_attach_args *ma)
{
paddr_t pa0, pa;
vaddr_t va, va0;
@@ -109,9 +109,11 @@ alloc_cpuinfo(int node)
struct cpu_info *cpi, *ci;
extern paddr_t cpu0paddr;
- portid = getpropint(node, "portid", -1);
+ portid = getpropint(ma->ma_node, "portid", -1);
if (portid == -1)
- portid = getpropint(node, "upa-portid", -1);
+ portid = getpropint(ma->ma_node, "upa-portid", -1);
+ if (portid == -1 && ma->ma_nreg > 0)
+ portid = (ma->ma_reg[0].ur_paddr >> 32) & 0x0fffffff;
if (portid == -1)
panic("alloc_cpuinfo: portid");
@@ -153,10 +155,13 @@ alloc_cpuinfo(int node)
cpi->ci_spinup = NULL;
#endif
- cpi->ci_initstack = (void *)EINTSTACK;
+ cpi->ci_initstack = cpi;
cpi->ci_paddr = pa0;
+#ifdef SUN4V
+ cpi->ci_mmfsa = pa0;
+#endif
cpi->ci_self = cpi;
- cpi->ci_node = node;
+ cpi->ci_node = ma->ma_node;
sched_init_cpu(cpi);
@@ -195,6 +200,8 @@ cpu_match(parent, vcf, aux)
portid = getpropint(ma->ma_node, "portid", -1);
if (portid == -1)
portid = getpropint(ma->ma_node, "cpuid", -1);
+ if (portid == -1 && ma->ma_nreg > 0)
+ portid = (ma->ma_reg[0].ur_paddr >> 32) & 0xff;
if (portid == -1)
return (0);
@@ -210,7 +217,7 @@ cpu_match(parent, vcf, aux)
* Discover interesting goop about the virtual address cache
* (slightly funny place to do it, but this is where it is to be found).
*/
-static void
+void
cpu_attach(parent, dev, aux)
struct device *parent;
struct device *dev;
@@ -223,10 +230,11 @@ cpu_attach(parent, dev, aux)
struct cpu_info *ci;
const char *sep;
register int i, l;
- u_int64_t ver;
+ u_int64_t ver = 0;
extern u_int64_t cpu_clockrate[];
- ver = getver();
+ if (CPU_ISSUN4U)
+ ver = getver();
impl = IU_IMPL(ver);
vers = IU_VERS(ver);
@@ -236,7 +244,7 @@ cpu_attach(parent, dev, aux)
/*
* Allocate cpu_info structure if needed.
*/
- ci = alloc_cpuinfo(node);
+ ci = alloc_cpuinfo(ma);
clk = getpropint(node, "clock-frequency", 0);
if (clk == 0) {
@@ -253,6 +261,9 @@ cpu_attach(parent, dev, aux)
ma->ma_name, vers >> 4, vers & 0xf, clockfreq(clk));
printf(": %s\n", cpu_model);
+ if (ci->ci_upaid == cpu_myid())
+ cpu_init(ci);
+
cacheinfo.c_physical = 1; /* Dunno... */
cacheinfo.c_split = 1;
l = getpropint(node, "icache-line-size", 0);
@@ -370,6 +381,15 @@ cpu_myid(void)
{
char buf[32];
+#ifdef SUN4V
+ if (CPU_ISSUN4V) {
+ uint64_t myid;
+
+ hv_cpu_myid(&myid);
+ return myid;
+ }
+#endif
+
if (OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0 &&
strcmp(buf, "SUNW,Ultra-Enterprise-10000") == 0)
return lduwa(0x1fff40000d0UL, ASI_PHYS_NON_CACHED);
@@ -377,6 +397,42 @@ cpu_myid(void)
return CPU_UPAID;
}
+void
+cpu_init(struct cpu_info *ci)
+{
+#ifdef SUN4V
+ paddr_t pa = ci->ci_paddr;
+ int err;
+
+ if (CPU_ISSUN4U)
+ return;
+
+#define MONDO_QUEUE_SIZE 32
+#define QUEUE_ENTRY_SIZE 64
+
+ pa += CPUINFO_VA - INTSTACK;
+ pa += PAGE_SIZE;
+
+ ci->ci_cpumq = pa;
+ err = hv_cpu_qconf(CPU_MONDO_QUEUE, ci->ci_cpumq, MONDO_QUEUE_SIZE);
+ if (err != H_EOK)
+ panic("Unable to set cpu mondo queue: %d", err);
+ pa += MONDO_QUEUE_SIZE * QUEUE_ENTRY_SIZE;
+
+ ci->ci_devmq = pa;
+ err = hv_cpu_qconf(DEVICE_MONDO_QUEUE, ci->ci_devmq, MONDO_QUEUE_SIZE);
+ if (err != H_EOK)
+ panic("Unable to set device mondo queue: %d", err);
+ pa += MONDO_QUEUE_SIZE * QUEUE_ENTRY_SIZE;
+
+ ci->ci_mondo = pa;
+ pa += 64;
+
+ ci->ci_cpuset = pa;
+ pa += 64;
+#endif
+}
+
struct cfdriver cpu_cd = {
NULL, "cpu", DV_DULL
};
@@ -405,7 +461,7 @@ cpu_boot_secondary_processors(void)
continue;
cpuid = getpropint(ci->ci_node, "cpuid", -1);
- if (cpuid == -1) {
+ if (CPU_ISSUN4U && cpuid == -1) {
prom_start_cpu(ci->ci_node,
(void *)cpu_mp_startup, ci->ci_paddr);
} else {
@@ -425,13 +481,16 @@ cpu_boot_secondary_processors(void)
void
cpu_hatch(void)
{
+ struct cpu_info *ci = curcpu();
int s;
- curcpu()->ci_flags |= CPUF_RUNNING;
+ cpu_init(ci);
+
+ ci->ci_flags |= CPUF_RUNNING;
sparc_membar(Sync);
s = splhigh();
- microuptime(&curcpu()->ci_schedstate.spc_runtime);
+ microuptime(&ci->ci_schedstate.spc_runtime);
splx(s);
tick_start();
diff --git a/sys/arch/sparc64/sparc64/pmap.c b/sys/arch/sparc64/sparc64/pmap.c
index a45bd55dd2b..fa3dfa9dab1 100644
--- a/sys/arch/sparc64/sparc64/pmap.c
+++ b/sys/arch/sparc64/sparc64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.54 2008/03/22 16:01:32 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.55 2008/03/23 23:46:21 kettenis Exp $ */
/* $NetBSD: pmap.c,v 1.107 2001/08/31 16:47:41 eeh Exp $ */
#undef NO_VCACHE /* Don't forget the locked TLB in dostart */
/*
@@ -43,6 +43,7 @@
#include <machine/pcb.h>
#include <machine/sparc64.h>
#include <machine/ctlreg.h>
+#include <machine/hypervisor.h>
#include <machine/openfirm.h>
#include <machine/kcore.h>
@@ -235,6 +236,10 @@ int tsbsize; /* tsbents = 512 * 2^^tsbsize */
*/
#define TSB_TAG_INVALID (~0LL)
+#ifdef SUN4V
+struct tsb_desc *tsb_desc;
+#endif
+
struct pmap kernel_pmap_;
extern int physmem;
@@ -1044,6 +1049,19 @@ remap_data:
BDPRINTF(PDB_BOOT1, ("TSB allocated at %p size %08x\r\n", (void *)tsb_dmmu,
(int)TSBSIZE));
+#ifdef SUN4V
+ if (CPU_ISSUN4V) {
+ valloc(tsb_desc, struct tsb_desc, sizeof(struct tsb_desc));
+ bzero(tsb_desc, sizeof(struct tsb_desc));
+ tsb_desc->td_idxpgsz = 0;
+ tsb_desc->td_assoc = 1;
+ tsb_desc->td_size = TSBENTS;
+ tsb_desc->td_ctxidx = -1;
+ tsb_desc->td_pgsz = 0xf;
+ tsb_desc->td_pa = (paddr_t)tsb_dmmu + kdatap - kdata;
+ }
+#endif
+
first_phys_addr = mem->start;
BDPRINTF(PDB_BOOT1, ("firstaddr after pmap=%08lx\r\n",
(u_long)firstaddr));
@@ -1385,6 +1403,9 @@ remap_data:
cpus->ci_spinup = main; /* Call main when we're running. */
cpus->ci_initstack = (void *)u0[1];
cpus->ci_paddr = cpu0paddr;
+#ifdef SUN4V
+ cpus->ci_mmfsa = cpu0paddr;
+#endif
proc0paddr = cpus->ci_cpcb;
cpu0paddr += 64 * KB;
@@ -1407,11 +1428,23 @@ remap_data:
pmap_bootstrap_cpu(cpus->ci_paddr);
}
-extern void sun4u_set_tsbs(void);
+void sun4u_bootstrap_cpu(paddr_t);
+void sun4v_bootstrap_cpu(paddr_t);
void
pmap_bootstrap_cpu(paddr_t intstack)
{
+ if (CPU_ISSUN4V)
+ sun4v_bootstrap_cpu(intstack);
+ else
+ sun4u_bootstrap_cpu(intstack);
+}
+
+extern void sun4u_set_tsbs(void);
+
+void
+sun4u_bootstrap_cpu(paddr_t intstack)
+{
u_int64_t data;
paddr_t pa;
vaddr_t va;
@@ -1426,16 +1459,16 @@ pmap_bootstrap_cpu(paddr_t intstack)
index = 15; /* XXX */
for (va = ktext, pa = ktextp; va < ektext; va += 4*MEG, pa += 4*MEG) {
- data = TSB_DATA(0, PGSZ_4M, pa, 1, 0, 1, FORCE_ALIAS, 1, 0);
- data |= TLB_L;
+ data = SUN4U_TSB_DATA(0, PGSZ_4M, pa, 1, 0, 1, FORCE_ALIAS, 1, 0);
+ data |= SUN4U_TLB_L;
prom_itlb_load(index, data, va);
prom_dtlb_load(index, data, va);
index--;
}
for (va = kdata, pa = kdatap; va < ekdata; va += 4*MEG, pa += 4*MEG) {
- data = TSB_DATA(0, PGSZ_4M, pa, 1, 1, 1, FORCE_ALIAS, 1, 0);
- data |= TLB_L;
+ data = SUN4U_TSB_DATA(0, PGSZ_4M, pa, 1, 1, 1, FORCE_ALIAS, 1, 0);
+ data |= SUN4U_TLB_L;
prom_dtlb_load(index, data, va);
index--;
}
@@ -1444,13 +1477,65 @@ pmap_bootstrap_cpu(paddr_t intstack)
* Establish the 64KB locked mapping for the interrupt stack.
*/
- data = TSB_DATA(0, PGSZ_64K, intstack, 1, 1, 1, FORCE_ALIAS, 1, 0);
- data |= TLB_L;
+ data = SUN4U_TSB_DATA(0, PGSZ_64K, intstack, 1, 1, 1, FORCE_ALIAS, 1, 0);
+ data |= SUN4U_TLB_L;
prom_dtlb_load(index, data, INTSTACK);
sun4u_set_tsbs();
}
+void
+sun4v_bootstrap_cpu(paddr_t intstack)
+{
+#ifdef SUN4V
+ u_int64_t data;
+ paddr_t pa;
+ vaddr_t va;
+ int err;
+
+ /*
+ * Establish the 4MB locked mappings for kernel data and text.
+ *
+ * The text segment needs to be mapped into the DTLB too,
+ * because of .rodata.
+ */
+
+ for (va = ktext, pa = ktextp; va < ektext; va += 4*MEG, pa += 4*MEG) {
+ data = SUN4V_TSB_DATA(0, PGSZ_4M, pa, 1, 0, 1, 0, 1, 0);
+ data |= SUN4V_TLB_X;
+ err = hv_mmu_map_perm_addr(va, data, MAP_ITLB|MAP_DTLB);
+ if (err != H_EOK)
+ prom_printf("err: %d\r\n", err);
+ }
+
+ for (va = kdata, pa = kdatap; va < ekdata; va += 4*MEG, pa += 4*MEG) {
+ data = SUN4V_TSB_DATA(0, PGSZ_4M, pa, 1, 1, 1, 0, 1, 0);
+ err = hv_mmu_map_perm_addr(va, data, MAP_DTLB);
+ if (err != H_EOK)
+ prom_printf("err: %d\r\n", err);
+ }
+
+#ifndef MULTIPROCESSOR
+ /*
+ * Establish the 64KB locked mapping for the interrupt stack.
+ */
+ data = SUN4V_TSB_DATA(0, PGSZ_64K, intstack, 1, 1, 1, 0, 1, 0);
+ err = hv_mmu_map_perm_addr(INTSTACK, data, MAP_DTLB);
+ if (err != H_EOK)
+ prom_printf("err: %d\r\n", err);
+#endif
+
+ stxa(0, ASI_SCRATCHPAD, intstack + (CPUINFO_VA - INTSTACK));
+
+ err = hv_mmu_tsb_ctx0(1, (paddr_t)tsb_desc + kdatap - kdata);
+ if (err != H_EOK)
+ prom_printf("err: %d\r\n", err);
+ err = hv_mmu_tsb_ctxnon0(1, (paddr_t)tsb_desc + kdatap - kdata);
+ if (err != H_EOK)
+ prom_printf("err: %d\r\n", err);
+#endif
+}
+
/*
* Initialize anything else for pmap handling.
* Called during vm_init().