162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _SPARC_TRAP_BLOCK_H 362306a36Sopenharmony_ci#define _SPARC_TRAP_BLOCK_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/threads.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <asm/hypervisor.h> 862306a36Sopenharmony_ci#include <asm/asi.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* Trap handling code needs to get at a few critical values upon 1362306a36Sopenharmony_ci * trap entry and to process TSB misses. These cannot be in the 1462306a36Sopenharmony_ci * per_cpu() area as we really need to lock them into the TLB and 1562306a36Sopenharmony_ci * thus make them part of the main kernel image. As a result we 1662306a36Sopenharmony_ci * try to make this as small as possible. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * This is padded out and aligned to 64-bytes to avoid false sharing 1962306a36Sopenharmony_ci * on SMP. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* If you modify the size of this structure, please update 2362306a36Sopenharmony_ci * TRAP_BLOCK_SZ_SHIFT below. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_cistruct thread_info; 2662306a36Sopenharmony_cistruct trap_per_cpu { 2762306a36Sopenharmony_ci/* D-cache line 1: Basic thread information, cpu and device mondo queues */ 2862306a36Sopenharmony_ci struct thread_info *thread; 2962306a36Sopenharmony_ci unsigned long pgd_paddr; 3062306a36Sopenharmony_ci unsigned long cpu_mondo_pa; 3162306a36Sopenharmony_ci unsigned long dev_mondo_pa; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */ 3462306a36Sopenharmony_ci unsigned long resum_mondo_pa; 3562306a36Sopenharmony_ci unsigned long resum_kernel_buf_pa; 3662306a36Sopenharmony_ci unsigned long nonresum_mondo_pa; 3762306a36Sopenharmony_ci unsigned long nonresum_kernel_buf_pa; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */ 4062306a36Sopenharmony_ci struct hv_fault_status fault_info; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list. */ 4362306a36Sopenharmony_ci unsigned long cpu_mondo_block_pa; 4462306a36Sopenharmony_ci unsigned long cpu_list_pa; 4562306a36Sopenharmony_ci unsigned long tsb_huge; 4662306a36Sopenharmony_ci unsigned long tsb_huge_temp; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size. */ 4962306a36Sopenharmony_ci unsigned long irq_worklist_pa; 5062306a36Sopenharmony_ci unsigned int cpu_mondo_qmask; 5162306a36Sopenharmony_ci unsigned int dev_mondo_qmask; 5262306a36Sopenharmony_ci unsigned int resum_qmask; 5362306a36Sopenharmony_ci unsigned int nonresum_qmask; 5462306a36Sopenharmony_ci unsigned long __per_cpu_base; 5562306a36Sopenharmony_ci} __attribute__((aligned(64))); 5662306a36Sopenharmony_ciextern struct trap_per_cpu trap_block[NR_CPUS]; 5762306a36Sopenharmony_civoid init_cur_cpu_trap(struct thread_info *); 5862306a36Sopenharmony_civoid setup_tba(void); 5962306a36Sopenharmony_ciextern int ncpus_probed; 6062306a36Sopenharmony_ciextern u64 cpu_mondo_counter[NR_CPUS]; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciunsigned long real_hard_smp_processor_id(void); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistruct cpuid_patch_entry { 6562306a36Sopenharmony_ci unsigned int addr; 6662306a36Sopenharmony_ci unsigned int cheetah_safari[4]; 6762306a36Sopenharmony_ci unsigned int cheetah_jbus[4]; 6862306a36Sopenharmony_ci unsigned int starfire[4]; 6962306a36Sopenharmony_ci unsigned int sun4v[4]; 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ciextern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistruct sun4v_1insn_patch_entry { 7462306a36Sopenharmony_ci unsigned int addr; 7562306a36Sopenharmony_ci unsigned int insn; 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ciextern struct sun4v_1insn_patch_entry __sun4v_1insn_patch, 7862306a36Sopenharmony_ci __sun4v_1insn_patch_end; 7962306a36Sopenharmony_ciextern struct sun4v_1insn_patch_entry __fast_win_ctrl_1insn_patch, 8062306a36Sopenharmony_ci __fast_win_ctrl_1insn_patch_end; 8162306a36Sopenharmony_ciextern struct sun4v_1insn_patch_entry __sun_m7_1insn_patch, 8262306a36Sopenharmony_ci __sun_m7_1insn_patch_end; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistruct sun4v_2insn_patch_entry { 8562306a36Sopenharmony_ci unsigned int addr; 8662306a36Sopenharmony_ci unsigned int insns[2]; 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ciextern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, 8962306a36Sopenharmony_ci __sun4v_2insn_patch_end; 9062306a36Sopenharmony_ciextern struct sun4v_2insn_patch_entry __sun_m7_2insn_patch, 9162306a36Sopenharmony_ci __sun_m7_2insn_patch_end; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#endif /* !(__ASSEMBLY__) */ 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define TRAP_PER_CPU_THREAD 0x00 9762306a36Sopenharmony_ci#define TRAP_PER_CPU_PGD_PADDR 0x08 9862306a36Sopenharmony_ci#define TRAP_PER_CPU_CPU_MONDO_PA 0x10 9962306a36Sopenharmony_ci#define TRAP_PER_CPU_DEV_MONDO_PA 0x18 10062306a36Sopenharmony_ci#define TRAP_PER_CPU_RESUM_MONDO_PA 0x20 10162306a36Sopenharmony_ci#define TRAP_PER_CPU_RESUM_KBUF_PA 0x28 10262306a36Sopenharmony_ci#define TRAP_PER_CPU_NONRESUM_MONDO_PA 0x30 10362306a36Sopenharmony_ci#define TRAP_PER_CPU_NONRESUM_KBUF_PA 0x38 10462306a36Sopenharmony_ci#define TRAP_PER_CPU_FAULT_INFO 0x40 10562306a36Sopenharmony_ci#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA 0xc0 10662306a36Sopenharmony_ci#define TRAP_PER_CPU_CPU_LIST_PA 0xc8 10762306a36Sopenharmony_ci#define TRAP_PER_CPU_TSB_HUGE 0xd0 10862306a36Sopenharmony_ci#define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8 10962306a36Sopenharmony_ci#define TRAP_PER_CPU_IRQ_WORKLIST_PA 0xe0 11062306a36Sopenharmony_ci#define TRAP_PER_CPU_CPU_MONDO_QMASK 0xe8 11162306a36Sopenharmony_ci#define TRAP_PER_CPU_DEV_MONDO_QMASK 0xec 11262306a36Sopenharmony_ci#define TRAP_PER_CPU_RESUM_QMASK 0xf0 11362306a36Sopenharmony_ci#define TRAP_PER_CPU_NONRESUM_QMASK 0xf4 11462306a36Sopenharmony_ci#define TRAP_PER_CPU_PER_CPU_BASE 0xf8 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#define TRAP_BLOCK_SZ_SHIFT 8 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci#include <asm/scratchpad.h> 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define __GET_CPUID(REG) \ 12162306a36Sopenharmony_ci /* Spitfire implementation (default). */ \ 12262306a36Sopenharmony_ci661: ldxa [%g0] ASI_UPA_CONFIG, REG; \ 12362306a36Sopenharmony_ci srlx REG, 17, REG; \ 12462306a36Sopenharmony_ci and REG, 0x1f, REG; \ 12562306a36Sopenharmony_ci nop; \ 12662306a36Sopenharmony_ci .section .cpuid_patch, "ax"; \ 12762306a36Sopenharmony_ci /* Instruction location. */ \ 12862306a36Sopenharmony_ci .word 661b; \ 12962306a36Sopenharmony_ci /* Cheetah Safari implementation. */ \ 13062306a36Sopenharmony_ci ldxa [%g0] ASI_SAFARI_CONFIG, REG; \ 13162306a36Sopenharmony_ci srlx REG, 17, REG; \ 13262306a36Sopenharmony_ci and REG, 0x3ff, REG; \ 13362306a36Sopenharmony_ci nop; \ 13462306a36Sopenharmony_ci /* Cheetah JBUS implementation. */ \ 13562306a36Sopenharmony_ci ldxa [%g0] ASI_JBUS_CONFIG, REG; \ 13662306a36Sopenharmony_ci srlx REG, 17, REG; \ 13762306a36Sopenharmony_ci and REG, 0x1f, REG; \ 13862306a36Sopenharmony_ci nop; \ 13962306a36Sopenharmony_ci /* Starfire implementation. */ \ 14062306a36Sopenharmony_ci sethi %hi(0x1fff40000d0 >> 9), REG; \ 14162306a36Sopenharmony_ci sllx REG, 9, REG; \ 14262306a36Sopenharmony_ci or REG, 0xd0, REG; \ 14362306a36Sopenharmony_ci lduwa [REG] ASI_PHYS_BYPASS_EC_E, REG;\ 14462306a36Sopenharmony_ci /* sun4v implementation. */ \ 14562306a36Sopenharmony_ci mov SCRATCHPAD_CPUID, REG; \ 14662306a36Sopenharmony_ci ldxa [REG] ASI_SCRATCHPAD, REG; \ 14762306a36Sopenharmony_ci nop; \ 14862306a36Sopenharmony_ci nop; \ 14962306a36Sopenharmony_ci .previous; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci#ifdef CONFIG_SMP 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ 15462306a36Sopenharmony_ci __GET_CPUID(TMP) \ 15562306a36Sopenharmony_ci sethi %hi(trap_block), DEST; \ 15662306a36Sopenharmony_ci sllx TMP, TRAP_BLOCK_SZ_SHIFT, TMP; \ 15762306a36Sopenharmony_ci or DEST, %lo(trap_block), DEST; \ 15862306a36Sopenharmony_ci add DEST, TMP, DEST; \ 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/* Clobbers TMP, current address space PGD phys address into DEST. */ 16162306a36Sopenharmony_ci#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \ 16262306a36Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ 16362306a36Sopenharmony_ci ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci/* Clobbers TMP, loads local processor's IRQ work area into DEST. */ 16662306a36Sopenharmony_ci#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \ 16762306a36Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ 16862306a36Sopenharmony_ci add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci/* Clobbers TMP, loads DEST with current thread info pointer. */ 17162306a36Sopenharmony_ci#define TRAP_LOAD_THREAD_REG(DEST, TMP) \ 17262306a36Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ 17362306a36Sopenharmony_ci ldx [DEST + TRAP_PER_CPU_THREAD], DEST; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* Given the current thread info pointer in THR, load the per-cpu 17662306a36Sopenharmony_ci * area base of the current processor into DEST. REG1, REG2, and REG3 are 17762306a36Sopenharmony_ci * clobbered. 17862306a36Sopenharmony_ci * 17962306a36Sopenharmony_ci * You absolutely cannot use DEST as a temporary in this code. The 18062306a36Sopenharmony_ci * reason is that traps can happen during execution, and return from 18162306a36Sopenharmony_ci * trap will load the fully resolved DEST per-cpu base. This can corrupt 18262306a36Sopenharmony_ci * the calculations done by the macro mid-stream. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_ci#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3) \ 18562306a36Sopenharmony_ci lduh [THR + TI_CPU], REG1; \ 18662306a36Sopenharmony_ci sethi %hi(trap_block), REG2; \ 18762306a36Sopenharmony_ci sllx REG1, TRAP_BLOCK_SZ_SHIFT, REG1; \ 18862306a36Sopenharmony_ci or REG2, %lo(trap_block), REG2; \ 18962306a36Sopenharmony_ci add REG2, REG1, REG2; \ 19062306a36Sopenharmony_ci ldx [REG2 + TRAP_PER_CPU_PER_CPU_BASE], DEST; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci#else 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ 19562306a36Sopenharmony_ci sethi %hi(trap_block), DEST; \ 19662306a36Sopenharmony_ci or DEST, %lo(trap_block), DEST; \ 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/* Uniprocessor versions, we know the cpuid is zero. */ 19962306a36Sopenharmony_ci#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \ 20062306a36Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ 20162306a36Sopenharmony_ci ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/* Clobbers TMP, loads local processor's IRQ work area into DEST. */ 20462306a36Sopenharmony_ci#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \ 20562306a36Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ 20662306a36Sopenharmony_ci add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#define TRAP_LOAD_THREAD_REG(DEST, TMP) \ 20962306a36Sopenharmony_ci TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ 21062306a36Sopenharmony_ci ldx [DEST + TRAP_PER_CPU_THREAD], DEST; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci/* No per-cpu areas on uniprocessor, so no need to load DEST. */ 21362306a36Sopenharmony_ci#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3) 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci#endif /* !(CONFIG_SMP) */ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci#endif /* _SPARC_TRAP_BLOCK_H */ 218