18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2020 Loongson Technology Corporation Limited 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#ifndef _ASM_PROCESSOR_H 68c2ecf20Sopenharmony_ci#define _ASM_PROCESSOR_H 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/atomic.h> 98c2ecf20Sopenharmony_ci#include <linux/cpumask.h> 108c2ecf20Sopenharmony_ci#include <linux/sizes.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/cpu.h> 138c2ecf20Sopenharmony_ci#include <asm/cpu-info.h> 148c2ecf20Sopenharmony_ci#include <asm/loongarchregs.h> 158c2ecf20Sopenharmony_ci#include <asm/vdso/processor.h> 168c2ecf20Sopenharmony_ci#include <uapi/asm/ptrace.h> 178c2ecf20Sopenharmony_ci#include <uapi/asm/sigcontext.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#ifdef CONFIG_32BIT 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define TASK_SIZE 0x80000000UL 228c2ecf20Sopenharmony_ci#define TASK_SIZE_MIN TASK_SIZE 238c2ecf20Sopenharmony_ci#define STACK_TOP_MAX TASK_SIZE 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define TASK_IS_32BIT_ADDR 1 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#endif 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define TASK_SIZE32 0x100000000UL 328c2ecf20Sopenharmony_ci#define TASK_SIZE64 (0x1UL << ((cpu_vabits > VA_BITS) ? VA_BITS : cpu_vabits)) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64) 358c2ecf20Sopenharmony_ci#define TASK_SIZE_MIN TASK_SIZE32 368c2ecf20Sopenharmony_ci#define STACK_TOP_MAX TASK_SIZE64 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define TASK_SIZE_OF(tsk) \ 398c2ecf20Sopenharmony_ci (test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define TASK_IS_32BIT_ADDR test_thread_flag(TIF_32BIT_ADDR) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#endif 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define VDSO_RANDOMIZE_SIZE (TASK_IS_32BIT_ADDR ? SZ_1M : SZ_64M) 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ciunsigned long stack_top(void); 488c2ecf20Sopenharmony_ci#define STACK_TOP stack_top() 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * This decides where the kernel will search for a free chunk of vm 528c2ecf20Sopenharmony_ci * space during mmap's. 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_ci#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define FPU_REG_WIDTH 256 578c2ecf20Sopenharmony_ci#define FPU_ALIGN __attribute__((aligned(32))) 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ciunion fpureg { 608c2ecf20Sopenharmony_ci __u32 val32[FPU_REG_WIDTH / 32]; 618c2ecf20Sopenharmony_ci __u64 val64[FPU_REG_WIDTH / 64]; 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define FPR_IDX(width, idx) (idx) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define BUILD_FPR_ACCESS(width) \ 678c2ecf20Sopenharmony_cistatic inline u##width get_fpr##width(union fpureg *fpr, unsigned idx) \ 688c2ecf20Sopenharmony_ci{ \ 698c2ecf20Sopenharmony_ci return fpr->val##width[FPR_IDX(width, idx)]; \ 708c2ecf20Sopenharmony_ci} \ 718c2ecf20Sopenharmony_ci \ 728c2ecf20Sopenharmony_cistatic inline void set_fpr##width(union fpureg *fpr, unsigned idx, \ 738c2ecf20Sopenharmony_ci u##width val) \ 748c2ecf20Sopenharmony_ci{ \ 758c2ecf20Sopenharmony_ci fpr->val##width[FPR_IDX(width, idx)] = val; \ 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ciBUILD_FPR_ACCESS(32) 798c2ecf20Sopenharmony_ciBUILD_FPR_ACCESS(64) 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistruct loongarch_fpu { 828c2ecf20Sopenharmony_ci unsigned int fcsr; 838c2ecf20Sopenharmony_ci uint64_t fcc; /* 8x8 */ 848c2ecf20Sopenharmony_ci uint64_t ftop; 858c2ecf20Sopenharmony_ci union fpureg fpr[NUM_FPU_REGS]; 868c2ecf20Sopenharmony_ci}; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistruct loongarch_lbt { 898c2ecf20Sopenharmony_ci /* Scratch registers */ 908c2ecf20Sopenharmony_ci unsigned long scr0; 918c2ecf20Sopenharmony_ci unsigned long scr1; 928c2ecf20Sopenharmony_ci unsigned long scr2; 938c2ecf20Sopenharmony_ci unsigned long scr3; 948c2ecf20Sopenharmony_ci /* Eflags register */ 958c2ecf20Sopenharmony_ci unsigned long eflags; 968c2ecf20Sopenharmony_ci}; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#define INIT_CPUMASK { \ 998c2ecf20Sopenharmony_ci {0,} \ 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistruct loongarch_watch_reg_state { 1038c2ecf20Sopenharmony_ci unsigned long addr[NUM_WATCH_REGS]; 1048c2ecf20Sopenharmony_ci unsigned long mask[NUM_WATCH_REGS]; 1058c2ecf20Sopenharmony_ci unsigned char irw[NUM_WATCH_REGS]; 1068c2ecf20Sopenharmony_ci unsigned char irwstat[NUM_WATCH_REGS]; 1078c2ecf20Sopenharmony_ci unsigned char irwmask[NUM_WATCH_REGS]; 1088c2ecf20Sopenharmony_ci}; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci#define ARCH_MIN_TASKALIGN 32 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistruct loongarch_vdso_info; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/* 1158c2ecf20Sopenharmony_ci * If you change thread_struct remember to change the #defines below too! 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_cistruct thread_struct { 1188c2ecf20Sopenharmony_ci /* Main processor registers. */ 1198c2ecf20Sopenharmony_ci unsigned long reg01, reg03, reg22; /* ra sp fp */ 1208c2ecf20Sopenharmony_ci unsigned long reg23, reg24, reg25, reg26; /* s0-s3 */ 1218c2ecf20Sopenharmony_ci unsigned long reg27, reg28, reg29, reg30, reg31; /* s4-s8 */ 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* __schedule() return address / call frame address */ 1248c2ecf20Sopenharmony_ci unsigned long sched_ra; 1258c2ecf20Sopenharmony_ci unsigned long sched_cfa; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* CSR registers */ 1288c2ecf20Sopenharmony_ci unsigned long csr_prmd; 1298c2ecf20Sopenharmony_ci unsigned long csr_crmd; 1308c2ecf20Sopenharmony_ci unsigned long csr_euen; 1318c2ecf20Sopenharmony_ci unsigned long csr_ecfg; 1328c2ecf20Sopenharmony_ci unsigned long csr_badvaddr; /* Last user fault */ 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci /* Used by ptrace single_step */ 1358c2ecf20Sopenharmony_ci unsigned long single_step; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* Watch register state, if available. */ 1388c2ecf20Sopenharmony_ci struct loongarch_watch_reg_state watch; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* Other stuff associated with the thread. */ 1418c2ecf20Sopenharmony_ci unsigned long trap_nr; 1428c2ecf20Sopenharmony_ci unsigned long error_code; 1438c2ecf20Sopenharmony_ci struct loongarch_lbt lbt; 1448c2ecf20Sopenharmony_ci struct loongarch_vdso_info *vdso; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* 1478c2ecf20Sopenharmony_ci * FPU & vector registers, must be at last because 1488c2ecf20Sopenharmony_ci * they are conditionally copied at fork(). 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_ci struct loongarch_fpu fpu FPU_ALIGN; 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci#define thread_saved_ra(tsk) (tsk->thread.sched_ra) 1548c2ecf20Sopenharmony_ci#define thread_saved_fp(tsk) (tsk->thread.sched_cfa) 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#define INIT_THREAD { \ 1578c2ecf20Sopenharmony_ci /* \ 1588c2ecf20Sopenharmony_ci * Main processor registers \ 1598c2ecf20Sopenharmony_ci */ \ 1608c2ecf20Sopenharmony_ci .reg01 = 0, \ 1618c2ecf20Sopenharmony_ci .reg03 = 0, \ 1628c2ecf20Sopenharmony_ci .reg22 = 0, \ 1638c2ecf20Sopenharmony_ci .reg23 = 0, \ 1648c2ecf20Sopenharmony_ci .reg24 = 0, \ 1658c2ecf20Sopenharmony_ci .reg25 = 0, \ 1668c2ecf20Sopenharmony_ci .reg26 = 0, \ 1678c2ecf20Sopenharmony_ci .reg27 = 0, \ 1688c2ecf20Sopenharmony_ci .reg28 = 0, \ 1698c2ecf20Sopenharmony_ci .reg29 = 0, \ 1708c2ecf20Sopenharmony_ci .reg30 = 0, \ 1718c2ecf20Sopenharmony_ci .reg31 = 0, \ 1728c2ecf20Sopenharmony_ci .sched_ra = 0, \ 1738c2ecf20Sopenharmony_ci .sched_cfa = 0, \ 1748c2ecf20Sopenharmony_ci .csr_crmd = 0, \ 1758c2ecf20Sopenharmony_ci .csr_prmd = 0, \ 1768c2ecf20Sopenharmony_ci .csr_euen = 0, \ 1778c2ecf20Sopenharmony_ci .csr_ecfg = 0, \ 1788c2ecf20Sopenharmony_ci .csr_badvaddr = 0, \ 1798c2ecf20Sopenharmony_ci /* \ 1808c2ecf20Sopenharmony_ci * Saved watch register stuff \ 1818c2ecf20Sopenharmony_ci */ \ 1828c2ecf20Sopenharmony_ci .watch = {{0,},}, \ 1838c2ecf20Sopenharmony_ci /* \ 1848c2ecf20Sopenharmony_ci * Other stuff associated with the process \ 1858c2ecf20Sopenharmony_ci */ \ 1868c2ecf20Sopenharmony_ci .trap_nr = 0, \ 1878c2ecf20Sopenharmony_ci .error_code = 0, \ 1888c2ecf20Sopenharmony_ci /* \ 1898c2ecf20Sopenharmony_ci * FPU & vector registers \ 1908c2ecf20Sopenharmony_ci */ \ 1918c2ecf20Sopenharmony_ci .fpu = { \ 1928c2ecf20Sopenharmony_ci .fcsr = 0, \ 1938c2ecf20Sopenharmony_ci .fcc = 0, \ 1948c2ecf20Sopenharmony_ci .fpr = {{{0,},},}, \ 1958c2ecf20Sopenharmony_ci }, \ 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistruct task_struct; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci/* Free all resources held by a thread. */ 2018c2ecf20Sopenharmony_ci#define release_thread(thread) do { } while(0) 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cienum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT, 2048c2ecf20Sopenharmony_ci IDLE_POLL}; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ciextern unsigned long boot_option_idle_override; 2078c2ecf20Sopenharmony_ci/* 2088c2ecf20Sopenharmony_ci * Do necessary setup to start up a newly executed thread. 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_ciextern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic inline void flush_thread(void) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ciunsigned long get_wchan(struct task_struct *p); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \ 2198c2ecf20Sopenharmony_ci THREAD_SIZE - sizeof(struct pt_regs)) 2208c2ecf20Sopenharmony_ci#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk)) 2218c2ecf20Sopenharmony_ci#define KSTK_EIP(tsk) (task_pt_regs(tsk)->csr_era) 2228c2ecf20Sopenharmony_ci#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[3]) 2238c2ecf20Sopenharmony_ci#define KSTK_EUEN(tsk) (task_pt_regs(tsk)->csr_euen) 2248c2ecf20Sopenharmony_ci#define KSTK_ECFG(tsk) (task_pt_regs(tsk)->csr_ecfg) 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci#define return_address() ({__asm__ __volatile__("":::"$1");__builtin_return_address(0);}) 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_HAS_PREFETCH 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci#define ARCH_HAS_PREFETCH 2318c2ecf20Sopenharmony_ci#define prefetch(x) __builtin_prefetch((x), 0, 1) 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci#define ARCH_HAS_PREFETCHW 2348c2ecf20Sopenharmony_ci#define prefetchw(x) __builtin_prefetch((x), 1, 1) 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci#endif 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci#endif /* _ASM_PROCESSOR_H */ 239