162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#ifndef _ASM_PROCESSOR_H 662306a36Sopenharmony_ci#define _ASM_PROCESSOR_H 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/atomic.h> 962306a36Sopenharmony_ci#include <linux/cpumask.h> 1062306a36Sopenharmony_ci#include <linux/sizes.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <asm/cpu.h> 1362306a36Sopenharmony_ci#include <asm/cpu-info.h> 1462306a36Sopenharmony_ci#include <asm/hw_breakpoint.h> 1562306a36Sopenharmony_ci#include <asm/loongarch.h> 1662306a36Sopenharmony_ci#include <asm/vdso/processor.h> 1762306a36Sopenharmony_ci#include <uapi/asm/ptrace.h> 1862306a36Sopenharmony_ci#include <uapi/asm/sigcontext.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#ifdef CONFIG_32BIT 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define TASK_SIZE 0x80000000UL 2362306a36Sopenharmony_ci#define TASK_SIZE_MIN TASK_SIZE 2462306a36Sopenharmony_ci#define STACK_TOP_MAX TASK_SIZE 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define TASK_IS_32BIT_ADDR 1 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#endif 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#ifdef CONFIG_64BIT 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define TASK_SIZE32 0x100000000UL 3362306a36Sopenharmony_ci#define TASK_SIZE64 (0x1UL << ((cpu_vabits > VA_BITS) ? VA_BITS : cpu_vabits)) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64) 3662306a36Sopenharmony_ci#define TASK_SIZE_MIN TASK_SIZE32 3762306a36Sopenharmony_ci#define STACK_TOP_MAX TASK_SIZE64 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define TASK_SIZE_OF(tsk) \ 4062306a36Sopenharmony_ci (test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define TASK_IS_32BIT_ADDR test_thread_flag(TIF_32BIT_ADDR) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#endif 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define VDSO_RANDOMIZE_SIZE (TASK_IS_32BIT_ADDR ? SZ_1M : SZ_64M) 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciunsigned long stack_top(void); 4962306a36Sopenharmony_ci#define STACK_TOP stack_top() 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* 5262306a36Sopenharmony_ci * This decides where the kernel will search for a free chunk of vm 5362306a36Sopenharmony_ci * space during mmap's. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define FPU_REG_WIDTH 256 5862306a36Sopenharmony_ci#define FPU_ALIGN __attribute__((aligned(32))) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciunion fpureg { 6162306a36Sopenharmony_ci __u32 val32[FPU_REG_WIDTH / 32]; 6262306a36Sopenharmony_ci __u64 val64[FPU_REG_WIDTH / 64]; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define FPR_IDX(width, idx) (idx) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define BUILD_FPR_ACCESS(width) \ 6862306a36Sopenharmony_cistatic inline u##width get_fpr##width(union fpureg *fpr, unsigned idx) \ 6962306a36Sopenharmony_ci{ \ 7062306a36Sopenharmony_ci return fpr->val##width[FPR_IDX(width, idx)]; \ 7162306a36Sopenharmony_ci} \ 7262306a36Sopenharmony_ci \ 7362306a36Sopenharmony_cistatic inline void set_fpr##width(union fpureg *fpr, unsigned int idx, \ 7462306a36Sopenharmony_ci u##width val) \ 7562306a36Sopenharmony_ci{ \ 7662306a36Sopenharmony_ci fpr->val##width[FPR_IDX(width, idx)] = val; \ 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciBUILD_FPR_ACCESS(32) 8062306a36Sopenharmony_ciBUILD_FPR_ACCESS(64) 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistruct loongarch_fpu { 8362306a36Sopenharmony_ci uint64_t fcc; /* 8x8 */ 8462306a36Sopenharmony_ci uint32_t fcsr; 8562306a36Sopenharmony_ci uint32_t ftop; 8662306a36Sopenharmony_ci union fpureg fpr[NUM_FPU_REGS]; 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistruct loongarch_lbt { 9062306a36Sopenharmony_ci /* Scratch registers */ 9162306a36Sopenharmony_ci unsigned long scr0; 9262306a36Sopenharmony_ci unsigned long scr1; 9362306a36Sopenharmony_ci unsigned long scr2; 9462306a36Sopenharmony_ci unsigned long scr3; 9562306a36Sopenharmony_ci /* Eflags register */ 9662306a36Sopenharmony_ci unsigned long eflags; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#define INIT_CPUMASK { \ 10062306a36Sopenharmony_ci {0,} \ 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci#define ARCH_MIN_TASKALIGN 32 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistruct loongarch_vdso_info; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci/* 10862306a36Sopenharmony_ci * If you change thread_struct remember to change the #defines below too! 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_cistruct thread_struct { 11162306a36Sopenharmony_ci /* Main processor registers. */ 11262306a36Sopenharmony_ci unsigned long reg01, reg03, reg22; /* ra sp fp */ 11362306a36Sopenharmony_ci unsigned long reg23, reg24, reg25, reg26; /* s0-s3 */ 11462306a36Sopenharmony_ci unsigned long reg27, reg28, reg29, reg30, reg31; /* s4-s8 */ 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* __schedule() return address / call frame address */ 11762306a36Sopenharmony_ci unsigned long sched_ra; 11862306a36Sopenharmony_ci unsigned long sched_cfa; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* CSR registers */ 12162306a36Sopenharmony_ci unsigned long csr_prmd; 12262306a36Sopenharmony_ci unsigned long csr_crmd; 12362306a36Sopenharmony_ci unsigned long csr_euen; 12462306a36Sopenharmony_ci unsigned long csr_ecfg; 12562306a36Sopenharmony_ci unsigned long csr_badvaddr; /* Last user fault */ 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci /* Other stuff associated with the thread. */ 12862306a36Sopenharmony_ci unsigned long trap_nr; 12962306a36Sopenharmony_ci unsigned long error_code; 13062306a36Sopenharmony_ci unsigned long single_step; /* Used by PTRACE_SINGLESTEP */ 13162306a36Sopenharmony_ci struct loongarch_vdso_info *vdso; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* 13462306a36Sopenharmony_ci * FPU & vector registers, must be at the last of inherited 13562306a36Sopenharmony_ci * context because they are conditionally copied at fork(). 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_ci struct loongarch_fpu fpu FPU_ALIGN; 13862306a36Sopenharmony_ci struct loongarch_lbt lbt; /* Also conditionally copied */ 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* Hardware breakpoints pinned to this task. */ 14162306a36Sopenharmony_ci struct perf_event *hbp_break[LOONGARCH_MAX_BRP]; 14262306a36Sopenharmony_ci struct perf_event *hbp_watch[LOONGARCH_MAX_WRP]; 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define thread_saved_ra(tsk) (tsk->thread.sched_ra) 14662306a36Sopenharmony_ci#define thread_saved_fp(tsk) (tsk->thread.sched_cfa) 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci#define INIT_THREAD { \ 14962306a36Sopenharmony_ci /* \ 15062306a36Sopenharmony_ci * Main processor registers \ 15162306a36Sopenharmony_ci */ \ 15262306a36Sopenharmony_ci .reg01 = 0, \ 15362306a36Sopenharmony_ci .reg03 = 0, \ 15462306a36Sopenharmony_ci .reg22 = 0, \ 15562306a36Sopenharmony_ci .reg23 = 0, \ 15662306a36Sopenharmony_ci .reg24 = 0, \ 15762306a36Sopenharmony_ci .reg25 = 0, \ 15862306a36Sopenharmony_ci .reg26 = 0, \ 15962306a36Sopenharmony_ci .reg27 = 0, \ 16062306a36Sopenharmony_ci .reg28 = 0, \ 16162306a36Sopenharmony_ci .reg29 = 0, \ 16262306a36Sopenharmony_ci .reg30 = 0, \ 16362306a36Sopenharmony_ci .reg31 = 0, \ 16462306a36Sopenharmony_ci .sched_ra = 0, \ 16562306a36Sopenharmony_ci .sched_cfa = 0, \ 16662306a36Sopenharmony_ci .csr_crmd = 0, \ 16762306a36Sopenharmony_ci .csr_prmd = 0, \ 16862306a36Sopenharmony_ci .csr_euen = 0, \ 16962306a36Sopenharmony_ci .csr_ecfg = 0, \ 17062306a36Sopenharmony_ci .csr_badvaddr = 0, \ 17162306a36Sopenharmony_ci /* \ 17262306a36Sopenharmony_ci * Other stuff associated with the process \ 17362306a36Sopenharmony_ci */ \ 17462306a36Sopenharmony_ci .trap_nr = 0, \ 17562306a36Sopenharmony_ci .error_code = 0, \ 17662306a36Sopenharmony_ci /* \ 17762306a36Sopenharmony_ci * FPU & vector registers \ 17862306a36Sopenharmony_ci */ \ 17962306a36Sopenharmony_ci .fpu = { \ 18062306a36Sopenharmony_ci .fcc = 0, \ 18162306a36Sopenharmony_ci .fcsr = 0, \ 18262306a36Sopenharmony_ci .ftop = 0, \ 18362306a36Sopenharmony_ci .fpr = {{{0,},},}, \ 18462306a36Sopenharmony_ci }, \ 18562306a36Sopenharmony_ci .hbp_break = {0}, \ 18662306a36Sopenharmony_ci .hbp_watch = {0}, \ 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistruct task_struct; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cienum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_HALT, IDLE_NOMWAIT, IDLE_POLL}; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ciextern unsigned long boot_option_idle_override; 19462306a36Sopenharmony_ci/* 19562306a36Sopenharmony_ci * Do necessary setup to start up a newly executed thread. 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_ciextern void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciunsigned long __get_wchan(struct task_struct *p); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \ 20262306a36Sopenharmony_ci THREAD_SIZE - sizeof(struct pt_regs)) 20362306a36Sopenharmony_ci#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk)) 20462306a36Sopenharmony_ci#define KSTK_EIP(tsk) (task_pt_regs(tsk)->csr_era) 20562306a36Sopenharmony_ci#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[3]) 20662306a36Sopenharmony_ci#define KSTK_EUEN(tsk) (task_pt_regs(tsk)->csr_euen) 20762306a36Sopenharmony_ci#define KSTK_ECFG(tsk) (task_pt_regs(tsk)->csr_ecfg) 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci#define return_address() ({__asm__ __volatile__("":::"$1"); __builtin_return_address(0);}) 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci#ifdef CONFIG_CPU_HAS_PREFETCH 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci#define ARCH_HAS_PREFETCH 21462306a36Sopenharmony_ci#define prefetch(x) __builtin_prefetch((x), 0, 1) 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci#define ARCH_HAS_PREFETCHW 21762306a36Sopenharmony_ci#define prefetchw(x) __builtin_prefetch((x), 1, 1) 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci#endif 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci#endif /* _ASM_PROCESSOR_H */ 222