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 guarded_storage_release(struct task_struct
*tsk
)
17 kfree(tsk
->thread
.gs_cb
);
18 kfree(tsk
->thread
.gs_bc_cb
);
21 static int gs_enable(void)
25 if (!current
->thread
.gs_cb
) {
26 gs_cb
= kzalloc(sizeof(*gs_cb
), GFP_KERNEL
);
33 current
->thread
.gs_cb
= gs_cb
;
39 static int gs_disable(void)
41 if (current
->thread
.gs_cb
) {
43 kfree(current
->thread
.gs_cb
);
44 current
->thread
.gs_cb
= NULL
;
45 __ctl_clear_bit(2, 4);
51 static int gs_set_bc_cb(struct gs_cb __user
*u_gs_cb
)
55 gs_cb
= current
->thread
.gs_bc_cb
;
57 gs_cb
= kzalloc(sizeof(*gs_cb
), GFP_KERNEL
);
60 current
->thread
.gs_bc_cb
= gs_cb
;
62 if (copy_from_user(gs_cb
, u_gs_cb
, sizeof(*gs_cb
)))
67 static int gs_clear_bc_cb(void)
71 gs_cb
= current
->thread
.gs_bc_cb
;
72 current
->thread
.gs_bc_cb
= NULL
;
77 void gs_load_bc_cb(struct pt_regs
*regs
)
82 clear_thread_flag(TIF_GUARDED_STORAGE
);
83 gs_cb
= current
->thread
.gs_bc_cb
;
85 kfree(current
->thread
.gs_cb
);
86 current
->thread
.gs_bc_cb
= NULL
;
89 current
->thread
.gs_cb
= gs_cb
;
94 static int gs_broadcast(void)
96 struct task_struct
*sibling
;
98 read_lock(&tasklist_lock
);
99 for_each_thread(current
, sibling
) {
100 if (!sibling
->thread
.gs_bc_cb
)
102 if (test_and_set_tsk_thread_flag(sibling
, TIF_GUARDED_STORAGE
))
103 kick_process(sibling
);
105 read_unlock(&tasklist_lock
);
109 SYSCALL_DEFINE2(s390_guarded_storage
, int, command
,
110 struct gs_cb __user
*, gs_cb
)
120 return gs_set_bc_cb(gs_cb
);
122 return gs_clear_bc_cb();
124 return gs_broadcast();