root/arch/s390/kernel/guarded_storage.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. guarded_storage_release
  2. gs_enable
  3. gs_disable
  4. gs_set_bc_cb
  5. gs_clear_bc_cb
  6. gs_load_bc_cb
  7. gs_broadcast
  8. SYSCALL_DEFINE2

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

/* [<][>][^][v][top][bottom][index][help] */