17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
525cf1a3jl * Common Development and Distribution License (the "License").
625cf1a3jl * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
222dd3029jimand * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
247c478bdstevel@tonic-gate */
252a1fd0fPeter Tribble/*
262a1fd0fPeter Tribble * Copyright 2019 Peter Tribble.
272a1fd0fPeter Tribble */
287c478bdstevel@tonic-gate
297c478bdstevel@tonic-gate#ifndef	_SYS_MACHTHREAD_H
307c478bdstevel@tonic-gate#define	_SYS_MACHTHREAD_H
317c478bdstevel@tonic-gate
327c478bdstevel@tonic-gate#include <sys/asi.h>
337c478bdstevel@tonic-gate#include <sys/sun4asi.h>
347c478bdstevel@tonic-gate#include <sys/machasi.h>
357c478bdstevel@tonic-gate#include <sys/bitmap.h>
3625cf1a3jl#include <sys/opl_olympus_regs.h>
377c478bdstevel@tonic-gate
387c478bdstevel@tonic-gate#ifdef	__cplusplus
397c478bdstevel@tonic-gateextern "C" {
407c478bdstevel@tonic-gate#endif
417c478bdstevel@tonic-gate
427c478bdstevel@tonic-gate#ifdef	_ASM
437c478bdstevel@tonic-gate
447c478bdstevel@tonic-gate#define	THREAD_REG	%g7		/* pointer to current thread data */
457c478bdstevel@tonic-gate
467c478bdstevel@tonic-gate/*
477c478bdstevel@tonic-gate * Get the processor implementation from the version register.
487c478bdstevel@tonic-gate */
497c478bdstevel@tonic-gate#define	GET_CPU_IMPL(out)		\
507c478bdstevel@tonic-gate	rdpr	%ver,	out;		\
517c478bdstevel@tonic-gate	srlx	out, 32, out;		\
527c478bdstevel@tonic-gate	sll	out, 16, out;		\
537c478bdstevel@tonic-gate	srl	out, 16, out;
547c478bdstevel@tonic-gate
552a1fd0fPeter Tribble#ifdef _OPL
5625cf1a3jl/*
5725cf1a3jl * For OPL platform, we get CPU_INDEX from ASI_EIDR.
5825cf1a3jl */
5925cf1a3jl#define	CPU_INDEX(r, scr)		\
6025cf1a3jl	ldxa	[%g0]ASI_EIDR, r;	\
6125cf1a3jl	and	r, 0xfff, r
6225cf1a3jl
6325cf1a3jl
642a1fd0fPeter Tribble#else /* _OPL */
657c478bdstevel@tonic-gate
667c478bdstevel@tonic-gate/*
677c478bdstevel@tonic-gate * UPA supports up to 32 devices while Safari supports up to
687c478bdstevel@tonic-gate * 1024 devices (utilizing the SSM protocol). Based upon the
697c478bdstevel@tonic-gate * value of NCPU, a 5- or 10-bit mask will be needed for
707c478bdstevel@tonic-gate * extracting the cpu id.
717c478bdstevel@tonic-gate */
727c478bdstevel@tonic-gate#if NCPU > 32
737c478bdstevel@tonic-gate#define	CPU_MASK	0x3ff
747c478bdstevel@tonic-gate#else
757c478bdstevel@tonic-gate#define	CPU_MASK	0x1f
767c478bdstevel@tonic-gate#endif	/* NCPU > 32 */
777c478bdstevel@tonic-gate
787c478bdstevel@tonic-gate/*
797c478bdstevel@tonic-gate * CPU_INDEX(r, scr)
807c478bdstevel@tonic-gate * Returns cpu id in r.
817c478bdstevel@tonic-gate * For UPA based systems, the cpu id corresponds to the mid field in
827c478bdstevel@tonic-gate * the UPA config register. For Safari based machines, the cpu id
837c478bdstevel@tonic-gate * corresponds to the aid field in the Safari config register.
847c478bdstevel@tonic-gate *
857c478bdstevel@tonic-gate * XXX - scr reg is not used here.
867c478bdstevel@tonic-gate */
877c478bdstevel@tonic-gate#define	CPU_INDEX(r, scr)		\
887c478bdstevel@tonic-gate	ldxa	[%g0]ASI_UPA_CONFIG, r;	\
897c478bdstevel@tonic-gate	srlx	r, 17, r;		\
907c478bdstevel@tonic-gate	and	r, CPU_MASK, r
917c478bdstevel@tonic-gate
922a1fd0fPeter Tribble#endif	/* _OPL */
937c478bdstevel@tonic-gate
947c478bdstevel@tonic-gate/*
957c478bdstevel@tonic-gate * Given a cpu id extract the appropriate word
967c478bdstevel@tonic-gate * in the cpuset mask for this cpu id.
977c478bdstevel@tonic-gate */
987c478bdstevel@tonic-gate#if CPUSET_SIZE > CLONGSIZE
997c478bdstevel@tonic-gate#define	CPU_INDEXTOSET(base, index, scr)	\
1007c478bdstevel@tonic-gate	srl	index, BT_ULSHIFT, scr;		\
1017c478bdstevel@tonic-gate	and	index, BT_ULMASK, index;	\
1027c478bdstevel@tonic-gate	sll	scr, CLONGSHIFT, scr;		\
1037c478bdstevel@tonic-gate	add	base, scr, base
1047c478bdstevel@tonic-gate#else
1057c478bdstevel@tonic-gate#define	CPU_INDEXTOSET(base, index, scr)
1067c478bdstevel@tonic-gate#endif	/* CPUSET_SIZE */
1077c478bdstevel@tonic-gate
1087c478bdstevel@tonic-gate
1097c478bdstevel@tonic-gate/*
1107c478bdstevel@tonic-gate * Assembly macro to find address of the current CPU.
1117c478bdstevel@tonic-gate * Used when coming in from a user trap - cannot use THREAD_REG.
1127c478bdstevel@tonic-gate * Args are destination register and one scratch register.
1137c478bdstevel@tonic-gate */
1147c478bdstevel@tonic-gate#define	CPU_ADDR(reg, scr) 		\
1157c478bdstevel@tonic-gate	.global	cpu;			\
1167c478bdstevel@tonic-gate	CPU_INDEX(scr, reg);		\
1177c478bdstevel@tonic-gate	sll	scr, CPTRSHIFT, scr;	\
1187c478bdstevel@tonic-gate	set	cpu, reg;		\
1197c478bdstevel@tonic-gate	ldn	[reg + scr], reg
1207c478bdstevel@tonic-gate
1217c478bdstevel@tonic-gate#define	CINT64SHIFT	3
1227c478bdstevel@tonic-gate
1237c478bdstevel@tonic-gate/*
1247c478bdstevel@tonic-gate * Assembly macro to find the physical address of the current CPU.
1257c478bdstevel@tonic-gate * All memory references using VA must be limited to nucleus
1267c478bdstevel@tonic-gate * memory to avoid any MMU side effect.
1277c478bdstevel@tonic-gate */
1287c478bdstevel@tonic-gate#define	CPU_PADDR(reg, scr)				\
1297c478bdstevel@tonic-gate	.global cpu_pa;					\
1307c478bdstevel@tonic-gate	CPU_INDEX(scr, reg);				\
1317c478bdstevel@tonic-gate	sll	scr, CINT64SHIFT, scr;			\
1327c478bdstevel@tonic-gate	set	cpu_pa, reg;				\
1337c478bdstevel@tonic-gate	ldx	[reg + scr], reg
1347c478bdstevel@tonic-gate
1357c478bdstevel@tonic-gate#endif	/* _ASM */
1367c478bdstevel@tonic-gate
1378f230a5bs/*
1388f230a5bs * If a high level trap handler decides to call sys_trap() to execute some
1398f230a5bs * base level code, context and other registers must be set to proper
1408f230a5bs * values to run kernel. This is true for most part of the kernel, except
1418f230a5bs * for user_rtt, a substantial part of which is executed with registers
1428f230a5bs * ready to run user code. The following macro may be used to detect this
1438f230a5bs * condition and handle it. Please note that, in general, we can't restart
1448f230a5bs * arbitrary piece of code running at tl > 0; user_rtt is a special case
1458f230a5bs * that can be handled.
1468f230a5bs *
1478f230a5bs * Entry condition:
1488f230a5bs *
1498f230a5bs * %tl = 2
1508f230a5bs * pstate.ag = 1
1518f230a5bs *
1528f230a5bs * Register usage:
1538f230a5bs *
1548f230a5bs * scr1, scr2 - destroyed
1558f230a5bs * normal %g5 and %g6 - destroyed
1568f230a5bs *
1578f230a5bs */
1588f230a5bs/* BEGIN CSTYLED */
1598f230a5bs#define	RESET_USER_RTT_REGS(scr1, scr2, label)				\
1608f230a5bs	/*								\
1618f230a5bs	 * do nothing if %tl != 2. this an attempt to stop this		\
1628f230a5bs	 * piece of code from executing more than once before going	\
1638f230a5bs	 * back to TL=0. more specifically, the changes we are doing	\
1648f230a5bs	 * to %wstate, %canrestore and %otherwin can't be done more	\
1658f230a5bs	 * than once before going to TL=0. note that it is okay to	\
1668f230a5bs	 * execute this more than once if we restart at user_rtt and	\
1678f230a5bs	 * come back from there.					\
1688f230a5bs	 */								\
1698f230a5bs	rdpr	%tl, scr1;						\
1708f230a5bs	cmp	scr1, 2;						\
1718f230a5bs	bne,a,pn %xcc, label;						\
1728f230a5bs	nop;								\
1738f230a5bs	/*								\
1748f230a5bs	 * read tstate[2].%tpc. do nothing if it is not			\
1758f230a5bs	 * between rtt_ctx_start and rtt_ctx_end.			\
1768f230a5bs	 */								\
1778f230a5bs	rdpr	%tpc, scr1;						\
1788f230a5bs	set	rtt_ctx_end, scr2;					\
1798f230a5bs	cmp	scr1, scr2;						\
1808f230a5bs	bgu,a,pt %xcc, label;						\
1818f230a5bs	nop;								\
1828f230a5bs	set	rtt_ctx_start, scr2;					\
1838f230a5bs	cmp	scr1, scr2;						\
1848f230a5bs	blu,a,pt %xcc, label;						\
1858f230a5bs	nop;								\
1868f230a5bs	/*								\
1878f230a5bs	 * pickup tstate[2].cwp						\
1888f230a5bs	 */								\
1898f230a5bs	rdpr	%tstate, scr1;						\
1908f230a5bs	and	scr1, TSTATE_CWP, scr1;					\
1918f230a5bs	/*								\
1928f230a5bs	 * set tstate[1].cwp to tstate[2].cwp. fudge			\
1938f230a5bs	 * tstate[1].tpc and tstate[1].tnpc to restart			\
1948f230a5bs	 * user_rtt.							\
1958f230a5bs	 */								\
1968f230a5bs	wrpr	%g0, 1, %tl;						\
1978f230a5bs	set	TSTATE_KERN | TSTATE_IE, scr2;				\
1988f230a5bs	or	scr1, scr2, scr2;					\
1998f230a5bs	wrpr    %g0, scr2, %tstate;					\
2008f230a5bs	set	user_rtt, scr1;						\
2018f230a5bs	wrpr	%g0, scr1, %tpc;					\
2028f230a5bs	add	scr1, 4, scr1;						\
2038f230a5bs	wrpr	%g0, scr1, %tnpc;					\
2048f230a5bs	/*								\
2058f230a5bs	 * restore %tl							\
2068f230a5bs	 */								\
2078f230a5bs	wrpr	%g0, 2, %tl;						\
2088f230a5bs	/*								\
2098f230a5bs	 * set %wstate							\
2108f230a5bs	 */								\
2118f230a5bs	rdpr	%wstate, scr1;						\
2128f230a5bs	sllx	scr1, WSTATE_SHIFT, scr1;				\
2138f230a5bs	wrpr    scr1, WSTATE_K64, %wstate;				\
2148f230a5bs	/*								\
2158f230a5bs	 * setup window registers					\
2168f230a5bs	 * %cleanwin <-- nwin - 1					\
2178f230a5bs	 * %otherwin <-- %canrestore					\
2188f230a5bs	 * %canrestore <-- 0						\
2198f230a5bs	 */								\
2208f230a5bs	sethi   %hi(nwin_minus_one), scr1;				\
2218f230a5bs	ld	[scr1 + %lo(nwin_minus_one)], scr1;			\
2228f230a5bs	wrpr    %g0, scr1, %cleanwin;					\
2238f230a5bs	rdpr	%canrestore, scr1;					\
2248f230a5bs	wrpr	%g0, scr1, %otherwin;					\
2258f230a5bs	wrpr	%g0, 0, %canrestore;					\
2268f230a5bs	/*								\
2278f230a5bs	 * set THREAD_REG, as we have restored user			\
2288f230a5bs	 * registers in user_rtt. we trash %g5 and %g6			\
2298f230a5bs	 * in the process.						\
2308f230a5bs	 */								\
2318f230a5bs	rdpr    %pstate, scr1;						\
2328f230a5bs	wrpr	scr1, PSTATE_AG, %pstate;				\
2338f230a5bs	/*								\
2348f230a5bs	 * using normal globals now					\
2358f230a5bs	 */								\
2368f230a5bs	CPU_ADDR(%g5, %g6);						\
2378f230a5bs	ldn	[%g5 + CPU_THREAD], %g6;				\
2388f230a5bs	mov	%g6, THREAD_REG;					\
2398f230a5bs	rdpr	%pstate, %g5;						\
2408f230a5bs	wrpr	%g5, PSTATE_AG, %pstate;				\
2418f230a5bs	/*								\
2428f230a5bs	 * back to alternate globals.					\
2438f230a5bs	 * set PCONTEXT to run kernel.					\
244febcc4ajimand	 * A demap of I/DTLB is required if the nucleus bits differ	\
245febcc4ajimand	 * from kcontextreg.						\
2468f230a5bs	 */								\
2478f230a5bs	mov	MMU_PCONTEXT, scr1;					\
2488f230a5bs	sethi	%hi(kcontextreg), scr2;					\
2498f230a5bs	ldx     [scr2 + %lo(kcontextreg)], scr2;			\
2502dd3029jimand	ldxa	[scr1]ASI_MMU_CTX, scr1;				\
2512dd3029jimand	xor	scr2, scr1, scr1;					\
2522dd3029jimand	srlx	scr1, CTXREG_NEXT_SHIFT, scr1;				\
253febcc4ajimand	/*								\
254febcc4ajimand	 * If N_pgsz0/1 changed, need to demap.				\
255febcc4ajimand	 */								\
2562dd3029jimand	brz	scr1, label/**/_0;					\
2572dd3029jimand	nop;								\
2582dd3029jimand	mov	DEMAP_ALL_TYPE, scr1;					\
2592dd3029jimand	stxa	%g0, [scr1]ASI_DTLB_DEMAP;				\
2602dd3029jimand	stxa	%g0, [scr1]ASI_ITLB_DEMAP;				\
2612dd3029jimandlabel/**/_0:								\
2622dd3029jimand	mov	MMU_PCONTEXT, scr1;					\
2638f230a5bs	stxa    scr2, [scr1]ASI_MMU_CTX;				\
2642dd3029jimand	sethi   %hi(FLUSH_ADDR), scr1;					\
2652dd3029jimand	flush	scr1
2668f230a5bs
2678f230a5bs/* END CSTYLED */
2688f230a5bs
2697c478bdstevel@tonic-gate#ifdef	__cplusplus
2707c478bdstevel@tonic-gate}
2717c478bdstevel@tonic-gate#endif
2727c478bdstevel@tonic-gate
2737c478bdstevel@tonic-gate#endif	/* _SYS_MACHTHREAD_H */
274