blob: c61b2cc1a8a86a9508fe093a607d106ff0118be3 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
David Howellsa0616cd2012-03-28 18:30:02 +01002/*
3 * Copyright IBM Corp. 1999, 2009
4 *
5 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
6 */
7
8#ifndef __ASM_SWITCH_TO_H
9#define __ASM_SWITCH_TO_H
10
11#include <linux/thread_info.h>
Hendrik Bruecknerb0753902015-10-06 12:25:59 +020012#include <asm/fpu/api.h>
Heiko Carstensbee5c282013-08-20 10:24:12 +020013#include <asm/ptrace.h>
Martin Schwidefsky916cda12016-01-26 14:10:34 +010014#include <asm/guarded_storage.h>
David Howellsa0616cd2012-03-28 18:30:02 +010015
16extern struct task_struct *__switch_to(void *, void *);
Michael Mueller64597f92013-07-02 22:58:26 +020017extern void update_cr_regs(struct task_struct *task);
David Howellsa0616cd2012-03-28 18:30:02 +010018
David Howellsa0616cd2012-03-28 18:30:02 +010019static inline void save_access_regs(unsigned int *acrs)
20{
Heiko Carstensbee5c282013-08-20 10:24:12 +020021 typedef struct { int _[NUM_ACRS]; } acrstype;
22
23 asm volatile("stam 0,15,%0" : "=Q" (*(acrstype *)acrs));
David Howellsa0616cd2012-03-28 18:30:02 +010024}
25
26static inline void restore_access_regs(unsigned int *acrs)
27{
Heiko Carstensbee5c282013-08-20 10:24:12 +020028 typedef struct { int _[NUM_ACRS]; } acrstype;
29
30 asm volatile("lam 0,15,%0" : : "Q" (*(acrstype *)acrs));
David Howellsa0616cd2012-03-28 18:30:02 +010031}
32
Heiko Carstensfbbd7f12017-11-20 12:38:44 +010033#define switch_to(prev, next, last) do { \
34 /* save_fpu_regs() sets the CIF_FPU flag, which enforces \
35 * a restore of the floating point / vector registers as \
36 * soon as the next task returns to user space \
37 */ \
38 save_fpu_regs(); \
39 save_access_regs(&prev->thread.acrs[0]); \
40 save_ri_cb(prev->thread.ri_cb); \
41 save_gs_cb(prev->thread.gs_cb); \
Heiko Carstensa1c5bef2017-11-09 12:29:34 +010042 update_cr_regs(next); \
Heiko Carstensfbbd7f12017-11-20 12:38:44 +010043 restore_access_regs(&next->thread.acrs[0]); \
44 restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \
45 restore_gs_cb(next->thread.gs_cb); \
46 prev = __switch_to(prev, next); \
David Howellsa0616cd2012-03-28 18:30:02 +010047} while (0)
48
David Howellsa0616cd2012-03-28 18:30:02 +010049#endif /* __ASM_SWITCH_TO_H */