diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2012-08-29 20:33:17 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2012-08-29 20:33:17 +0000 |
commit | 3dedeea696f0eea7042acc587783d890538c20c5 (patch) | |
tree | 61f281656c57a76b9ad8f60c28e5107d986f5388 /sys/arch | |
parent | b5604b45f5e758b43e5114e50f575ca3de2b0168 (diff) |
The low-level guts to support MTP (Multi-Threaded Processing) on the
Fujitsu SPARC64-VI and SPARC64-VII CPUs. Since the two threads on each core
share the TLBs of the core we cannot enter different mappings for the same
virtual address. Instead we use a scratch register to store the per-cpu
pointer. This is very similar to what we do on sun4v.
For now we still only attach the first thread of each SPARC64-VI/VII core
since we currently don't handle the VMT (Vertical Multi-Threading) of the
SPARC64-VI very well.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc64/include/ctlreg.h | 4 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/autoconf.c | 19 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/locore.s | 16 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/pmap.c | 31 |
4 files changed, 66 insertions, 4 deletions
diff --git a/sys/arch/sparc64/include/ctlreg.h b/sys/arch/sparc64/include/ctlreg.h index 43652728816..a451e2ce00f 100644 --- a/sys/arch/sparc64/include/ctlreg.h +++ b/sys/arch/sparc64/include/ctlreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ctlreg.h,v 1.23 2009/11/30 22:59:29 kettenis Exp $ */ +/* $OpenBSD: ctlreg.h,v 1.24 2012/08/29 20:33:16 kettenis Exp $ */ /* $NetBSD: ctlreg.h,v 1.28 2001/08/06 23:55:34 eeh Exp $ */ /* @@ -127,6 +127,8 @@ #define ASI_AFSR 0x4c /* [4u] asynchronous fault status register */ #define ASI_AFAR 0x4d /* [4u] asynchronous fault address register */ +#define ASI_SCRATCH 0x4f /* [VI] scratch registers */ + #define ASI_ICACHE_DATA 0x66 /* [4u] diagnostic access to D-cache data RAM */ #define ASI_ICACHE_TAG 0x67 /* [4u] diagnostic access to D-cache tag RAM */ #define ASI_FLUSH_I_PAGE_PRIMARY 0x68 /* [4u] flush D-cache page using primary context */ diff --git a/sys/arch/sparc64/sparc64/autoconf.c b/sys/arch/sparc64/sparc64/autoconf.c index 733a15e4ed9..5dd2b946cde 100644 --- a/sys/arch/sparc64/sparc64/autoconf.c +++ b/sys/arch/sparc64/sparc64/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.116 2012/06/30 22:00:49 kettenis Exp $ */ +/* $OpenBSD: autoconf.c,v 1.117 2012/08/29 20:33:16 kettenis Exp $ */ /* $NetBSD: autoconf.c,v 1.51 2001/07/24 19:32:11 eeh Exp $ */ /* @@ -344,6 +344,23 @@ bootstrap(nctx) cacheinfo.c_dcache_flush_page = no_dcache_flush_page; } +#ifdef MULTIPROCESSOR + if (impl >= IMPL_OLYMPUS_C && impl <= IMPL_JUPITER) { + struct sun4u_patch { + u_int32_t addr; + u_int32_t insn; + } *p; + + extern struct sun4u_patch sun4u_mtp_patch; + extern struct sun4u_patch sun4u_mtp_patch_end; + + for (p = &sun4u_mtp_patch; p < &sun4u_mtp_patch_end; p++) { + *(u_int32_t *)(vaddr_t)p->addr = p->insn; + flush((void *)(vaddr_t)p->addr); + } + } +#endif + #ifdef SUN4V if (CPU_ISSUN4V) { u_int32_t insn; diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s index 3f401f849bb..3b10fa2c9a9 100644 --- a/sys/arch/sparc64/sparc64/locore.s +++ b/sys/arch/sparc64/sparc64/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.164 2011/10/12 18:30:09 miod Exp $ */ +/* $OpenBSD: locore.s,v 1.165 2012/08/29 20:33:16 kettenis Exp $ */ /* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */ /* @@ -106,6 +106,11 @@ _C_LABEL(sun4v_patch): .globl _C_LABEL(sun4v_mp_patch) _C_LABEL(sun4v_mp_patch): .previous + + .section .sun4u_mtp_patch, "ax" + .globl _C_LABEL(sun4u_mtp_patch) +_C_LABEL(sun4u_mtp_patch): + .previous #endif /* @@ -120,6 +125,10 @@ _C_LABEL(sun4v_mp_patch): .section .sun4v_mp_patch, "ax" ;\ .word 999b ;\ ldxa [%g0] ASI_SCRATCHPAD, ci ;\ + .previous ;\ + .section .sun4u_mtp_patch, "ax" ;\ + .word 999b ;\ + ldxa [%g0] ASI_SCRATCH, ci ;\ .previous #define GET_CPCB(pcb) \ @@ -9181,4 +9190,9 @@ _C_LABEL(sun4v_patch_end): .globl _C_LABEL(sun4v_mp_patch_end) _C_LABEL(sun4v_mp_patch_end): .previous + + .section .sun4u_mtp_patch, "ax" + .globl _C_LABEL(sun4u_mtp_patch_end) +_C_LABEL(sun4u_mtp_patch_end): + .previous #endif diff --git a/sys/arch/sparc64/sparc64/pmap.c b/sys/arch/sparc64/sparc64/pmap.c index b1e31bce64f..2d398b13e1a 100644 --- a/sys/arch/sparc64/sparc64/pmap.c +++ b/sys/arch/sparc64/sparc64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.77 2012/08/29 19:54:32 kettenis Exp $ */ +/* $OpenBSD: pmap.c,v 1.78 2012/08/29 20:33:16 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 */ /* @@ -1469,6 +1469,9 @@ sun4u_bootstrap_cpu(paddr_t intstack) paddr_t pa; vaddr_t va; int index; + int impl; + + impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT; /* * Establish the 4MB locked mappings for kernel data and text. @@ -1493,6 +1496,32 @@ sun4u_bootstrap_cpu(paddr_t intstack) index--; } +#ifdef MULTIPROCESSOR + if (impl >= IMPL_OLYMPUS_C && impl <= IMPL_JUPITER) { + /* + * On SPARC64-VI and SPARC64-VII processors, the MMU is + * shared between threads, so we can't establish a locked + * mapping for the interrupt stack since the mappings would + * conflict. Instead we stick the address in a scratch + * register, like we do for sun4v. + */ + pa = intstack + (CPUINFO_VA - INTSTACK); + pa += offsetof(struct cpu_info, ci_self); + va = ldxa(pa, ASI_PHYS_CACHED); + stxa(0x00, ASI_SCRATCH, va); + + if ((CPU_JUPITERID % 2) == 1) + index--; + + data = SUN4U_TSB_DATA(0, PGSZ_64K, intstack, 1, 1, 1, FORCE_ALIAS, 1, 0); + data |= SUN4U_TLB_L; + prom_dtlb_load(index, data, va - (CPUINFO_VA - INTSTACK)); + + sun4u_set_tsbs(); + return; + } +#endif + /* * Establish the 64KB locked mapping for the interrupt stack. */ |