18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright IBM Corp. 1999, 2009
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef __ASM_SWITCH_TO_H
98c2ecf20Sopenharmony_ci#define __ASM_SWITCH_TO_H
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/thread_info.h>
128c2ecf20Sopenharmony_ci#include <asm/fpu/api.h>
138c2ecf20Sopenharmony_ci#include <asm/ptrace.h>
148c2ecf20Sopenharmony_ci#include <asm/guarded_storage.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ciextern struct task_struct *__switch_to(void *, void *);
178c2ecf20Sopenharmony_ciextern void update_cr_regs(struct task_struct *task);
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic inline void save_access_regs(unsigned int *acrs)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	typedef struct { int _[NUM_ACRS]; } acrstype;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	asm volatile("stam 0,15,%0" : "=Q" (*(acrstype *)acrs));
248c2ecf20Sopenharmony_ci}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic inline void restore_access_regs(unsigned int *acrs)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	typedef struct { int _[NUM_ACRS]; } acrstype;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	asm volatile("lam 0,15,%0" : : "Q" (*(acrstype *)acrs));
318c2ecf20Sopenharmony_ci}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define switch_to(prev, next, last) do {				\
348c2ecf20Sopenharmony_ci	/* save_fpu_regs() sets the CIF_FPU flag, which enforces	\
358c2ecf20Sopenharmony_ci	 * a restore of the floating point / vector registers as	\
368c2ecf20Sopenharmony_ci	 * soon as the next task returns to user space			\
378c2ecf20Sopenharmony_ci	 */								\
388c2ecf20Sopenharmony_ci	save_fpu_regs();						\
398c2ecf20Sopenharmony_ci	save_access_regs(&prev->thread.acrs[0]);			\
408c2ecf20Sopenharmony_ci	save_ri_cb(prev->thread.ri_cb);					\
418c2ecf20Sopenharmony_ci	save_gs_cb(prev->thread.gs_cb);					\
428c2ecf20Sopenharmony_ci	update_cr_regs(next);						\
438c2ecf20Sopenharmony_ci	restore_access_regs(&next->thread.acrs[0]);			\
448c2ecf20Sopenharmony_ci	restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb);		\
458c2ecf20Sopenharmony_ci	restore_gs_cb(next->thread.gs_cb);				\
468c2ecf20Sopenharmony_ci	prev = __switch_to(prev, next);					\
478c2ecf20Sopenharmony_ci} while (0)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#endif /* __ASM_SWITCH_TO_H */
50