1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright IBM Corp. 2016
4 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 #include <linux/kernel.h>
8 #include <linux/syscalls.h>
9 #include <linux/signal.h>
11 #include <linux/slab.h>
12 #include <asm/guarded_storage.h>
15 void exit_thread_gs(void)
18 kfree(current
->thread
.gs_cb
);
19 kfree(current
->thread
.gs_bc_cb
);
20 current
->thread
.gs_cb
= current
->thread
.gs_bc_cb
= NULL
;
24 static int gs_enable(void)
28 if (!current
->thread
.gs_cb
) {
29 gs_cb
= kzalloc(sizeof(*gs_cb
), GFP_KERNEL
);
36 current
->thread
.gs_cb
= gs_cb
;
42 static int gs_disable(void)
44 if (current
->thread
.gs_cb
) {
46 kfree(current
->thread
.gs_cb
);
47 current
->thread
.gs_cb
= NULL
;
48 __ctl_clear_bit(2, 4);
54 static int gs_set_bc_cb(struct gs_cb __user
*u_gs_cb
)
58 gs_cb
= current
->thread
.gs_bc_cb
;
60 gs_cb
= kzalloc(sizeof(*gs_cb
), GFP_KERNEL
);
63 current
->thread
.gs_bc_cb
= gs_cb
;
65 if (copy_from_user(gs_cb
, u_gs_cb
, sizeof(*gs_cb
)))
70 static int gs_clear_bc_cb(void)
74 gs_cb
= current
->thread
.gs_bc_cb
;
75 current
->thread
.gs_bc_cb
= NULL
;
80 void gs_load_bc_cb(struct pt_regs
*regs
)
85 clear_thread_flag(TIF_GUARDED_STORAGE
);
86 gs_cb
= current
->thread
.gs_bc_cb
;
88 kfree(current
->thread
.gs_cb
);
89 current
->thread
.gs_bc_cb
= NULL
;
92 current
->thread
.gs_cb
= gs_cb
;
97 static int gs_broadcast(void)
99 struct task_struct
*sibling
;
101 read_lock(&tasklist_lock
);
102 for_each_thread(current
, sibling
) {
103 if (!sibling
->thread
.gs_bc_cb
)
105 if (test_and_set_tsk_thread_flag(sibling
, TIF_GUARDED_STORAGE
))
106 kick_process(sibling
);
108 read_unlock(&tasklist_lock
);
112 SYSCALL_DEFINE2(s390_guarded_storage
, int, command
,
113 struct gs_cb __user
*, gs_cb
)
123 return gs_set_bc_cb(gs_cb
);
125 return gs_clear_bc_cb();
127 return gs_broadcast();