0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/syscalls.h>
0009 #include <linux/signal.h>
0010 #include <linux/mm.h>
0011 #include <linux/slab.h>
0012 #include <asm/guarded_storage.h>
0013 #include "entry.h"
0014
0015 void guarded_storage_release(struct task_struct *tsk)
0016 {
0017 kfree(tsk->thread.gs_cb);
0018 kfree(tsk->thread.gs_bc_cb);
0019 }
0020
0021 static int gs_enable(void)
0022 {
0023 struct gs_cb *gs_cb;
0024
0025 if (!current->thread.gs_cb) {
0026 gs_cb = kzalloc(sizeof(*gs_cb), GFP_KERNEL);
0027 if (!gs_cb)
0028 return -ENOMEM;
0029 gs_cb->gsd = 25;
0030 preempt_disable();
0031 __ctl_set_bit(2, 4);
0032 load_gs_cb(gs_cb);
0033 current->thread.gs_cb = gs_cb;
0034 preempt_enable();
0035 }
0036 return 0;
0037 }
0038
0039 static int gs_disable(void)
0040 {
0041 if (current->thread.gs_cb) {
0042 preempt_disable();
0043 kfree(current->thread.gs_cb);
0044 current->thread.gs_cb = NULL;
0045 __ctl_clear_bit(2, 4);
0046 preempt_enable();
0047 }
0048 return 0;
0049 }
0050
0051 static int gs_set_bc_cb(struct gs_cb __user *u_gs_cb)
0052 {
0053 struct gs_cb *gs_cb;
0054
0055 gs_cb = current->thread.gs_bc_cb;
0056 if (!gs_cb) {
0057 gs_cb = kzalloc(sizeof(*gs_cb), GFP_KERNEL);
0058 if (!gs_cb)
0059 return -ENOMEM;
0060 current->thread.gs_bc_cb = gs_cb;
0061 }
0062 if (copy_from_user(gs_cb, u_gs_cb, sizeof(*gs_cb)))
0063 return -EFAULT;
0064 return 0;
0065 }
0066
0067 static int gs_clear_bc_cb(void)
0068 {
0069 struct gs_cb *gs_cb;
0070
0071 gs_cb = current->thread.gs_bc_cb;
0072 current->thread.gs_bc_cb = NULL;
0073 kfree(gs_cb);
0074 return 0;
0075 }
0076
0077 void gs_load_bc_cb(struct pt_regs *regs)
0078 {
0079 struct gs_cb *gs_cb;
0080
0081 preempt_disable();
0082 clear_thread_flag(TIF_GUARDED_STORAGE);
0083 gs_cb = current->thread.gs_bc_cb;
0084 if (gs_cb) {
0085 kfree(current->thread.gs_cb);
0086 current->thread.gs_bc_cb = NULL;
0087 __ctl_set_bit(2, 4);
0088 load_gs_cb(gs_cb);
0089 current->thread.gs_cb = gs_cb;
0090 }
0091 preempt_enable();
0092 }
0093
0094 static int gs_broadcast(void)
0095 {
0096 struct task_struct *sibling;
0097
0098 read_lock(&tasklist_lock);
0099 for_each_thread(current, sibling) {
0100 if (!sibling->thread.gs_bc_cb)
0101 continue;
0102 if (test_and_set_tsk_thread_flag(sibling, TIF_GUARDED_STORAGE))
0103 kick_process(sibling);
0104 }
0105 read_unlock(&tasklist_lock);
0106 return 0;
0107 }
0108
0109 SYSCALL_DEFINE2(s390_guarded_storage, int, command,
0110 struct gs_cb __user *, gs_cb)
0111 {
0112 if (!MACHINE_HAS_GS)
0113 return -EOPNOTSUPP;
0114 switch (command) {
0115 case GS_ENABLE:
0116 return gs_enable();
0117 case GS_DISABLE:
0118 return gs_disable();
0119 case GS_SET_BC_CB:
0120 return gs_set_bc_cb(gs_cb);
0121 case GS_CLEAR_BC_CB:
0122 return gs_clear_bc_cb();
0123 case GS_BROADCAST:
0124 return gs_broadcast();
0125 default:
0126 return -EINVAL;
0127 }
0128 }