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