18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _SPARC_TRAP_BLOCK_H
38c2ecf20Sopenharmony_ci#define _SPARC_TRAP_BLOCK_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/threads.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <asm/hypervisor.h>
88c2ecf20Sopenharmony_ci#include <asm/asi.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/* Trap handling code needs to get at a few critical values upon
138c2ecf20Sopenharmony_ci * trap entry and to process TSB misses.  These cannot be in the
148c2ecf20Sopenharmony_ci * per_cpu() area as we really need to lock them into the TLB and
158c2ecf20Sopenharmony_ci * thus make them part of the main kernel image.  As a result we
168c2ecf20Sopenharmony_ci * try to make this as small as possible.
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * This is padded out and aligned to 64-bytes to avoid false sharing
198c2ecf20Sopenharmony_ci * on SMP.
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* If you modify the size of this structure, please update
238c2ecf20Sopenharmony_ci * TRAP_BLOCK_SZ_SHIFT below.
248c2ecf20Sopenharmony_ci */
258c2ecf20Sopenharmony_cistruct thread_info;
268c2ecf20Sopenharmony_cistruct trap_per_cpu {
278c2ecf20Sopenharmony_ci/* D-cache line 1: Basic thread information, cpu and device mondo queues */
288c2ecf20Sopenharmony_ci	struct thread_info	*thread;
298c2ecf20Sopenharmony_ci	unsigned long		pgd_paddr;
308c2ecf20Sopenharmony_ci	unsigned long		cpu_mondo_pa;
318c2ecf20Sopenharmony_ci	unsigned long		dev_mondo_pa;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
348c2ecf20Sopenharmony_ci	unsigned long		resum_mondo_pa;
358c2ecf20Sopenharmony_ci	unsigned long		resum_kernel_buf_pa;
368c2ecf20Sopenharmony_ci	unsigned long		nonresum_mondo_pa;
378c2ecf20Sopenharmony_ci	unsigned long		nonresum_kernel_buf_pa;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
408c2ecf20Sopenharmony_ci	struct hv_fault_status	fault_info;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list.  */
438c2ecf20Sopenharmony_ci	unsigned long		cpu_mondo_block_pa;
448c2ecf20Sopenharmony_ci	unsigned long		cpu_list_pa;
458c2ecf20Sopenharmony_ci	unsigned long		tsb_huge;
468c2ecf20Sopenharmony_ci	unsigned long		tsb_huge_temp;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size.  */
498c2ecf20Sopenharmony_ci	unsigned long		irq_worklist_pa;
508c2ecf20Sopenharmony_ci	unsigned int		cpu_mondo_qmask;
518c2ecf20Sopenharmony_ci	unsigned int		dev_mondo_qmask;
528c2ecf20Sopenharmony_ci	unsigned int		resum_qmask;
538c2ecf20Sopenharmony_ci	unsigned int		nonresum_qmask;
548c2ecf20Sopenharmony_ci	unsigned long		__per_cpu_base;
558c2ecf20Sopenharmony_ci} __attribute__((aligned(64)));
568c2ecf20Sopenharmony_ciextern struct trap_per_cpu trap_block[NR_CPUS];
578c2ecf20Sopenharmony_civoid init_cur_cpu_trap(struct thread_info *);
588c2ecf20Sopenharmony_civoid setup_tba(void);
598c2ecf20Sopenharmony_ciextern int ncpus_probed;
608c2ecf20Sopenharmony_ciextern u64 cpu_mondo_counter[NR_CPUS];
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ciunsigned long real_hard_smp_processor_id(void);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistruct cpuid_patch_entry {
658c2ecf20Sopenharmony_ci	unsigned int	addr;
668c2ecf20Sopenharmony_ci	unsigned int	cheetah_safari[4];
678c2ecf20Sopenharmony_ci	unsigned int	cheetah_jbus[4];
688c2ecf20Sopenharmony_ci	unsigned int	starfire[4];
698c2ecf20Sopenharmony_ci	unsigned int	sun4v[4];
708c2ecf20Sopenharmony_ci};
718c2ecf20Sopenharmony_ciextern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistruct sun4v_1insn_patch_entry {
748c2ecf20Sopenharmony_ci	unsigned int	addr;
758c2ecf20Sopenharmony_ci	unsigned int	insn;
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ciextern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
788c2ecf20Sopenharmony_ci	__sun4v_1insn_patch_end;
798c2ecf20Sopenharmony_ciextern struct sun4v_1insn_patch_entry __fast_win_ctrl_1insn_patch,
808c2ecf20Sopenharmony_ci	__fast_win_ctrl_1insn_patch_end;
818c2ecf20Sopenharmony_ciextern struct sun4v_1insn_patch_entry __sun_m7_1insn_patch,
828c2ecf20Sopenharmony_ci	__sun_m7_1insn_patch_end;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistruct sun4v_2insn_patch_entry {
858c2ecf20Sopenharmony_ci	unsigned int	addr;
868c2ecf20Sopenharmony_ci	unsigned int	insns[2];
878c2ecf20Sopenharmony_ci};
888c2ecf20Sopenharmony_ciextern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
898c2ecf20Sopenharmony_ci	__sun4v_2insn_patch_end;
908c2ecf20Sopenharmony_ciextern struct sun4v_2insn_patch_entry __sun_m7_2insn_patch,
918c2ecf20Sopenharmony_ci	__sun_m7_2insn_patch_end;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#endif /* !(__ASSEMBLY__) */
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_THREAD		0x00
978c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_PGD_PADDR		0x08
988c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_CPU_MONDO_PA	0x10
998c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_DEV_MONDO_PA	0x18
1008c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_RESUM_MONDO_PA	0x20
1018c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_RESUM_KBUF_PA	0x28
1028c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_NONRESUM_MONDO_PA	0x30
1038c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_NONRESUM_KBUF_PA	0x38
1048c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_FAULT_INFO		0x40
1058c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA	0xc0
1068c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_CPU_LIST_PA	0xc8
1078c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_TSB_HUGE		0xd0
1088c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_TSB_HUGE_TEMP	0xd8
1098c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_IRQ_WORKLIST_PA	0xe0
1108c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_CPU_MONDO_QMASK	0xe8
1118c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_DEV_MONDO_QMASK	0xec
1128c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_RESUM_QMASK	0xf0
1138c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_NONRESUM_QMASK	0xf4
1148c2ecf20Sopenharmony_ci#define TRAP_PER_CPU_PER_CPU_BASE	0xf8
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci#define TRAP_BLOCK_SZ_SHIFT		8
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci#include <asm/scratchpad.h>
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci#define __GET_CPUID(REG)				\
1218c2ecf20Sopenharmony_ci	/* Spitfire implementation (default). */	\
1228c2ecf20Sopenharmony_ci661:	ldxa		[%g0] ASI_UPA_CONFIG, REG;	\
1238c2ecf20Sopenharmony_ci	srlx		REG, 17, REG;			\
1248c2ecf20Sopenharmony_ci	 and		REG, 0x1f, REG;			\
1258c2ecf20Sopenharmony_ci	nop;						\
1268c2ecf20Sopenharmony_ci	.section	.cpuid_patch, "ax";		\
1278c2ecf20Sopenharmony_ci	/* Instruction location. */			\
1288c2ecf20Sopenharmony_ci	.word		661b;				\
1298c2ecf20Sopenharmony_ci	/* Cheetah Safari implementation. */		\
1308c2ecf20Sopenharmony_ci	ldxa		[%g0] ASI_SAFARI_CONFIG, REG;	\
1318c2ecf20Sopenharmony_ci	srlx		REG, 17, REG;			\
1328c2ecf20Sopenharmony_ci	and		REG, 0x3ff, REG;		\
1338c2ecf20Sopenharmony_ci	nop;						\
1348c2ecf20Sopenharmony_ci	/* Cheetah JBUS implementation. */		\
1358c2ecf20Sopenharmony_ci	ldxa		[%g0] ASI_JBUS_CONFIG, REG;	\
1368c2ecf20Sopenharmony_ci	srlx		REG, 17, REG;			\
1378c2ecf20Sopenharmony_ci	and		REG, 0x1f, REG;			\
1388c2ecf20Sopenharmony_ci	nop;						\
1398c2ecf20Sopenharmony_ci	/* Starfire implementation. */			\
1408c2ecf20Sopenharmony_ci	sethi		%hi(0x1fff40000d0 >> 9), REG;	\
1418c2ecf20Sopenharmony_ci	sllx		REG, 9, REG;			\
1428c2ecf20Sopenharmony_ci	or		REG, 0xd0, REG;			\
1438c2ecf20Sopenharmony_ci	lduwa		[REG] ASI_PHYS_BYPASS_EC_E, REG;\
1448c2ecf20Sopenharmony_ci	/* sun4v implementation. */			\
1458c2ecf20Sopenharmony_ci	mov		SCRATCHPAD_CPUID, REG;		\
1468c2ecf20Sopenharmony_ci	ldxa		[REG] ASI_SCRATCHPAD, REG;	\
1478c2ecf20Sopenharmony_ci	nop;						\
1488c2ecf20Sopenharmony_ci	nop;						\
1498c2ecf20Sopenharmony_ci	.previous;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
1548c2ecf20Sopenharmony_ci	__GET_CPUID(TMP)			\
1558c2ecf20Sopenharmony_ci	sethi	%hi(trap_block), DEST;		\
1568c2ecf20Sopenharmony_ci	sllx	TMP, TRAP_BLOCK_SZ_SHIFT, TMP;	\
1578c2ecf20Sopenharmony_ci	or	DEST, %lo(trap_block), DEST;	\
1588c2ecf20Sopenharmony_ci	add	DEST, TMP, DEST;		\
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci/* Clobbers TMP, current address space PGD phys address into DEST.  */
1618c2ecf20Sopenharmony_ci#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
1628c2ecf20Sopenharmony_ci	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
1638c2ecf20Sopenharmony_ci	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
1668c2ecf20Sopenharmony_ci#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
1678c2ecf20Sopenharmony_ci	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
1688c2ecf20Sopenharmony_ci	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci/* Clobbers TMP, loads DEST with current thread info pointer.  */
1718c2ecf20Sopenharmony_ci#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
1728c2ecf20Sopenharmony_ci	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
1738c2ecf20Sopenharmony_ci	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci/* Given the current thread info pointer in THR, load the per-cpu
1768c2ecf20Sopenharmony_ci * area base of the current processor into DEST.  REG1, REG2, and REG3 are
1778c2ecf20Sopenharmony_ci * clobbered.
1788c2ecf20Sopenharmony_ci *
1798c2ecf20Sopenharmony_ci * You absolutely cannot use DEST as a temporary in this code.  The
1808c2ecf20Sopenharmony_ci * reason is that traps can happen during execution, and return from
1818c2ecf20Sopenharmony_ci * trap will load the fully resolved DEST per-cpu base.  This can corrupt
1828c2ecf20Sopenharmony_ci * the calculations done by the macro mid-stream.
1838c2ecf20Sopenharmony_ci */
1848c2ecf20Sopenharmony_ci#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)	\
1858c2ecf20Sopenharmony_ci	lduh	[THR + TI_CPU], REG1;			\
1868c2ecf20Sopenharmony_ci	sethi	%hi(trap_block), REG2;			\
1878c2ecf20Sopenharmony_ci	sllx	REG1, TRAP_BLOCK_SZ_SHIFT, REG1;	\
1888c2ecf20Sopenharmony_ci	or	REG2, %lo(trap_block), REG2;		\
1898c2ecf20Sopenharmony_ci	add	REG2, REG1, REG2;			\
1908c2ecf20Sopenharmony_ci	ldx	[REG2 + TRAP_PER_CPU_PER_CPU_BASE], DEST;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci#else
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
1958c2ecf20Sopenharmony_ci	sethi	%hi(trap_block), DEST;		\
1968c2ecf20Sopenharmony_ci	or	DEST, %lo(trap_block), DEST;	\
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci/* Uniprocessor versions, we know the cpuid is zero.  */
1998c2ecf20Sopenharmony_ci#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
2008c2ecf20Sopenharmony_ci	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
2018c2ecf20Sopenharmony_ci	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
2048c2ecf20Sopenharmony_ci#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
2058c2ecf20Sopenharmony_ci	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
2068c2ecf20Sopenharmony_ci	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
2098c2ecf20Sopenharmony_ci	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
2108c2ecf20Sopenharmony_ci	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci/* No per-cpu areas on uniprocessor, so no need to load DEST.  */
2138c2ecf20Sopenharmony_ci#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci#endif /* !(CONFIG_SMP) */
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci#endif /* _SPARC_TRAP_BLOCK_H */
218