File Index
Files and directories
Sign in
FILE

guarded_storage.c

File preview with syntax highlighting.

linux-6.19.14/arch/s390/kernel/guarded_storage.c 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.