diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-03-23 23:46:22 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-03-23 23:46:22 +0000 |
commit | 378058c8842e5f428f7d7ce81f0c12190675d45f (patch) | |
tree | 813d74f8f7524bad8192cea560fb9fc5d5aa6ffd /sys/arch | |
parent | 28243bf4755af75f511078d6ff390ccb86d6fffb (diff) |
Add code to initialize CPUs on sun4v.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc64/include/cpu.h | 14 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/cpu.c | 97 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/pmap.c | 101 |
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(). |