linux/arch/s390/kernel/runtime_instr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright IBM Corp. 2012
   4 * Author(s): Jan Glauber <jang@linux.vnet.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 <linux/init.h>
  13#include <linux/errno.h>
  14#include <linux/kernel_stat.h>
  15#include <linux/sched/task_stack.h>
  16
  17#include <asm/runtime_instr.h>
  18#include <asm/cpu_mf.h>
  19#include <asm/irq.h>
  20
  21#include "entry.h"
  22
  23/* empty control block to disable RI by loading it */
  24struct runtime_instr_cb runtime_instr_empty_cb;
  25
  26void runtime_instr_release(struct task_struct *tsk)
  27{
  28        kfree(tsk->thread.ri_cb);
  29}
  30
  31static void disable_runtime_instr(void)
  32{
  33        struct task_struct *task = current;
  34        struct pt_regs *regs;
  35
  36        if (!task->thread.ri_cb)
  37                return;
  38        regs = task_pt_regs(task);
  39        preempt_disable();
  40        load_runtime_instr_cb(&runtime_instr_empty_cb);
  41        kfree(task->thread.ri_cb);
  42        task->thread.ri_cb = NULL;
  43        preempt_enable();
  44
  45        /*
  46         * Make sure the RI bit is deleted from the PSW. If the user did not
  47         * switch off RI before the system call the process will get a
  48         * specification exception otherwise.
  49         */
  50        regs->psw.mask &= ~PSW_MASK_RI;
  51}
  52
  53static void init_runtime_instr_cb(struct runtime_instr_cb *cb)
  54{
  55        cb->rla = 0xfff;
  56        cb->s = 1;
  57        cb->k = 1;
  58        cb->ps = 1;
  59        cb->pc = 1;
  60        cb->key = PAGE_DEFAULT_KEY >> 4;
  61        cb->v = 1;
  62}
  63
  64/*
  65 * The signum argument is unused. In older kernels it was used to
  66 * specify a real-time signal. For backwards compatibility user space
  67 * should pass a valid real-time signal number (the signum argument
  68 * was checked in older kernels).
  69 */
  70SYSCALL_DEFINE2(s390_runtime_instr, int, command, int, signum)
  71{
  72        struct runtime_instr_cb *cb;
  73
  74        if (!test_facility(64))
  75                return -EOPNOTSUPP;
  76
  77        if (command == S390_RUNTIME_INSTR_STOP) {
  78                disable_runtime_instr();
  79                return 0;
  80        }
  81
  82        if (command != S390_RUNTIME_INSTR_START)
  83                return -EINVAL;
  84
  85        if (!current->thread.ri_cb) {
  86                cb = kzalloc(sizeof(*cb), GFP_KERNEL);
  87                if (!cb)
  88                        return -ENOMEM;
  89        } else {
  90                cb = current->thread.ri_cb;
  91                memset(cb, 0, sizeof(*cb));
  92        }
  93
  94        init_runtime_instr_cb(cb);
  95
  96        /* now load the control block to make it available */
  97        preempt_disable();
  98        current->thread.ri_cb = cb;
  99        load_runtime_instr_cb(cb);
 100        preempt_enable();
 101        return 0;
 102}
 103