FILE
guarded_storage.c
File preview with syntax highlighting.
linux-6.19.14/arch/s390/kernel/guarded_storage.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright IBM Corp. 2016 4 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 5 */ 6 7#include <linux/cpufeature.h> 8#include <linux/kernel.h> 9#include <linux/syscalls.h> 10#include <linux/signal.h> 11#include <linux/mm.h> 12#include <linux/slab.h> 13#include <asm/guarded_storage.h> 14#include "entry.h" 15 16void guarded_storage_release(struct task_struct *tsk) 17{ 18 kfree(tsk->thread.gs_cb); 19 kfree(tsk->thread.gs_bc_cb); 20} 21 22static int gs_enable(void) 23{ 24 struct gs_cb *gs_cb; 25 26 if (!current->thread.gs_cb) { 27 gs_cb = kzalloc(sizeof(*gs_cb), GFP_KERNEL); 28 if (!gs_cb) 29 return -ENOMEM; 30 gs_cb->gsd = 25; 31 preempt_disable(); 32 local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); 33 load_gs_cb(gs_cb); 34 current->thread.gs_cb = gs_cb; 35 preempt_enable(); 36 } 37 return 0; 38} 39 40static int gs_disable(void) 41{ 42 if (current->thread.gs_cb) { 43 preempt_disable(); 44 kfree(current->thread.gs_cb); 45 current->thread.gs_cb = NULL; 46 local_ctl_clear_bit(2, CR2_GUARDED_STORAGE_BIT); 47 preempt_enable(); 48 } 49 return 0; 50} 51 52static int gs_set_bc_cb(struct gs_cb __user *u_gs_cb) 53{ 54 struct gs_cb *gs_cb; 55 56 gs_cb = current->thread.gs_bc_cb; 57 if (!gs_cb) { 58 gs_cb = kzalloc(sizeof(*gs_cb), GFP_KERNEL); 59 if (!gs_cb) 60 return -ENOMEM; 61 current->thread.gs_bc_cb = gs_cb; 62 } 63 if (copy_from_user(gs_cb, u_gs_cb, sizeof(*gs_cb))) 64 return -EFAULT; 65 return 0; 66} 67 68static int gs_clear_bc_cb(void) 69{ 70 struct gs_cb *gs_cb; 71 72 gs_cb = current->thread.gs_bc_cb; 73 current->thread.gs_bc_cb = NULL; 74 kfree(gs_cb); 75 return 0; 76} 77 78void gs_load_bc_cb(struct pt_regs *regs) 79{ 80 struct gs_cb *gs_cb; 81 82 preempt_disable(); 83 clear_thread_flag(TIF_GUARDED_STORAGE); 84 gs_cb = current->thread.gs_bc_cb; 85 if (gs_cb) { 86 kfree(current->thread.gs_cb); 87 current->thread.gs_bc_cb = NULL; 88 local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); 89 load_gs_cb(gs_cb); 90 current->thread.gs_cb = gs_cb; 91 } 92 preempt_enable(); 93} 94 95static int gs_broadcast(void) 96{ 97 struct task_struct *sibling; 98 99 read_lock(&tasklist_lock); 100 for_each_thread(current, sibling) { 101 if (!sibling->thread.gs_bc_cb) 102 continue; 103 if (test_and_set_tsk_thread_flag(sibling, TIF_GUARDED_STORAGE)) 104 kick_process(sibling); 105 } 106 read_unlock(&tasklist_lock); 107 return 0; 108} 109 110SYSCALL_DEFINE2(s390_guarded_storage, int, command, 111 struct gs_cb __user *, gs_cb) 112{ 113 if (!cpu_has_gs()) 114 return -EOPNOTSUPP; 115 switch (command) { 116 case GS_ENABLE: 117 return gs_enable(); 118 case GS_DISABLE: 119 return gs_disable(); 120 case GS_SET_BC_CB: 121 return gs_set_bc_cb(gs_cb); 122 case GS_CLEAR_BC_CB: 123 return gs_clear_bc_cb(); 124 case GS_BROADCAST: 125 return gs_broadcast(); 126 default: 127 return -EINVAL; 128 } 129}
~/
Read-only file preview.