
From: Yipeng Zou <zouyipeng@huawei.com> hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/release-management/issues/IC9Q31 -------------------------------- Introduce xcall_select to mark a special syscall. Mark by: echo @$syscall_nr > /proc/$PID/xcall Make sure it has been enabled in xcall before mark. If a system call number is marked, it means there are custom operations for xcall, otherwise it enters normal system call process. Signed-off-by: Yipeng Zou <zouyipeng@huawei.com> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> --- arch/arm64/kernel/asm-offsets.c | 2 +- arch/arm64/kernel/entry.S | 2 +- fs/proc/base.c | 74 +++++++++++++++++++++++++-------- include/linux/sched.h | 2 +- include/linux/xcall.h | 12 ++++++ kernel/fork.c | 21 ++++++---- 6 files changed, 85 insertions(+), 28 deletions(-) create mode 100644 include/linux/xcall.h diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 7c6ad4b1667b..54a21afd4181 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -27,7 +27,7 @@ int main(void) { #ifdef CONFIG_FAST_SYSCALL - DEFINE(TSK_XCALL, offsetof(struct task_struct, xcall_enable)); + DEFINE(TSK_XCALL, offsetof(struct task_struct, xinfo)); #endif DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); BLANK(); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 5ed8b8e8e58e..aa3eac1eb96e 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -707,7 +707,7 @@ SYM_CODE_END(el1_irq) .endm .macro check_xcall_enable - /* x21 = task_struct->xcall_enable */ + /* x21 = task_struct->xinfo->xcall_enable */ ldr_this_cpu x20, __entry_task, x21 ldr x21, [x20, #TSK_XCALL] /* x20 = sc_no / 8 */ diff --git a/fs/proc/base.c b/fs/proc/base.c index 3206960c4bd7..027d47bbdd7f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3590,13 +3590,16 @@ static const struct file_operations proc_pid_sg_level_operations = { #endif #ifdef CONFIG_FAST_SYSCALL +#include <linux/xcall.h> + bool fast_syscall_enabled(void); static int xcall_show(struct seq_file *m, void *v) { struct inode *inode = m->private; struct task_struct *p; - unsigned int rs, re; + unsigned int rs, re, sc_no; + struct xcall_info *xinfo; if (!fast_syscall_enabled()) return -EACCES; @@ -3605,19 +3608,29 @@ static int xcall_show(struct seq_file *m, void *v) if (!p) return -ESRCH; - if (!p->xcall_enable) + if (!p->xinfo) goto out; - seq_printf(m, "Enabled Total[%d/%d]:", bitmap_weight(p->xcall_enable, __NR_syscalls), + xinfo = p->xinfo; + seq_printf(m, "Enabled Total[%d/%d]:", bitmap_weight(xinfo->xcall_enable, __NR_syscalls), __NR_syscalls); - for (rs = 0, bitmap_next_set_region(p->xcall_enable, &rs, &re, __NR_syscalls); + for (rs = 0, bitmap_next_set_region(xinfo->xcall_enable, &rs, &re, __NR_syscalls); rs < re; rs = re + 1, - bitmap_next_set_region(p->xcall_enable, &rs, &re, __NR_syscalls)) { + bitmap_next_set_region(xinfo->xcall_enable, &rs, &re, __NR_syscalls)) { rs == (re - 1) ? seq_printf(m, "%d,", rs) : seq_printf(m, "%d-%d,", rs, re - 1); } - seq_puts(m, "\n"); + seq_puts(m, "\nAvailable:\n"); + + for (sc_no = 0; sc_no < __NR_syscalls; sc_no++) { + if (test_bit(sc_no, xinfo->xcall_select)) { + seq_printf(m, "NR_syscall: %3d: enabled: %d ", + sc_no, test_bit(sc_no, xinfo->xcall_enable)); + seq_printf(m, "xcall_select: %d\n", + test_bit(sc_no, xinfo->xcall_select)); + } + } out: put_task_struct(p); @@ -3629,15 +3642,36 @@ static int xcall_open(struct inode *inode, struct file *filp) return single_open(filp, xcall_show, inode); } -static int xcall_enable_one(struct task_struct *p, unsigned int sc_no) +static int xcall_enable_one(struct xcall_info *xinfo, unsigned int sc_no) { - bitmap_set(p->xcall_enable, sc_no, 1); + if (test_bit(sc_no, xinfo->xcall_select)) + return -EINVAL; + + bitmap_set(xinfo->xcall_enable, sc_no, 1); return 0; } -static int xcall_disable_one(struct task_struct *p, unsigned int sc_no) +static int xcall_disable_one(struct xcall_info *xinfo, unsigned int sc_no) { - bitmap_clear(p->xcall_enable, sc_no, 1); + if (test_bit(sc_no, xinfo->xcall_select)) + return -EINVAL; + + bitmap_clear(xinfo->xcall_enable, sc_no, 1); + return 0; +} + +static int xcall_select_table(struct xcall_info *xinfo, unsigned int sc_no) +{ + if (!test_bit(sc_no, xinfo->xcall_enable)) { + pr_err("Please enable NR_syscall: %d to xcall first.\n", sc_no); + return -EINVAL; + } + + if (test_bit(sc_no, xinfo->xcall_select)) + return -EINVAL; + + bitmap_set(xinfo->xcall_select, sc_no, 1); + return 0; } @@ -3650,7 +3684,8 @@ static ssize_t xcall_write(struct file *file, const char __user *buf, const size_t maxlen = sizeof(buffer) - 1; unsigned int sc_no = __NR_syscalls; int ret = 0; - int is_clear = 0; + int is_clear = 0, is_switch = 0; + struct xcall_info *xinfo; if (!fast_syscall_enabled()) return -EACCES; @@ -3660,13 +3695,16 @@ static ssize_t xcall_write(struct file *file, const char __user *buf, return -EFAULT; p = get_proc_task(inode); - if (!p || !p->xcall_enable) + if (!p || !p->xinfo) return -ESRCH; + xinfo = p->xinfo; if (buffer[0] == '!') is_clear = 1; + else if ((buffer[0] == '@')) + is_switch = 1; - if (kstrtouint(buffer + is_clear, 10, &sc_no)) { + if (kstrtouint(buffer + is_clear + is_switch, 10, &sc_no)) { ret = -EINVAL; goto out; } @@ -3676,10 +3714,12 @@ static ssize_t xcall_write(struct file *file, const char __user *buf, goto out; } - if (!is_clear && !test_bit(sc_no, p->xcall_enable)) - ret = xcall_enable_one(p, sc_no); - else if (is_clear && test_bit(sc_no, p->xcall_enable)) - ret = xcall_disable_one(p, sc_no); + if (is_switch && test_bit(sc_no, xinfo->xcall_enable)) + ret = xcall_select_table(xinfo, sc_no); + else if (!is_switch && !is_clear && !test_bit(sc_no, xinfo->xcall_enable)) + ret = xcall_enable_one(xinfo, sc_no); + else if (!is_switch && is_clear && test_bit(sc_no, xinfo->xcall_enable)) + ret = xcall_disable_one(xinfo, sc_no); else ret = -EINVAL; diff --git a/include/linux/sched.h b/include/linux/sched.h index 18361e35a377..fd975183ec26 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1478,7 +1478,7 @@ struct task_struct { KABI_RESERVE(14) #endif #if defined(CONFIG_FAST_SYSCALL) - KABI_USE(15, unsigned long *xcall_enable) + KABI_USE(15, struct xcall_info *xinfo) #else KABI_RESERVE(15) #endif diff --git a/include/linux/xcall.h b/include/linux/xcall.h new file mode 100644 index 000000000000..b0de488a4fff --- /dev/null +++ b/include/linux/xcall.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_XCALL_H +#define _LINUX_XCALL_H + +#include <linux/sysctl.h> + +struct xcall_info { + /* Must be first! */ + DECLARE_BITMAP(xcall_enable, __NR_syscalls); + DECLARE_BITMAP(xcall_select, __NR_syscalls); +}; +#endif diff --git a/kernel/fork.c b/kernel/fork.c index bd7afeb364ab..5338d21b185e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -102,6 +102,9 @@ #include <linux/sched/grid_qos.h> #endif #include <linux/share_pool.h> +#ifdef CONFIG_FAST_SYSCALL +#include <linux/xcall.h> +#endif #include <asm/pgalloc.h> #include <linux/uaccess.h> #include <asm/mmu_context.h> @@ -481,8 +484,7 @@ void free_task(struct task_struct *tsk) sched_relationship_free(tsk); #ifdef CONFIG_FAST_SYSCALL - if (tsk->xcall_enable) - bitmap_free(tsk->xcall_enable); + kfree(tsk->xinfo); #endif free_task_struct(tsk); @@ -1015,7 +1017,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) #endif #ifdef CONFIG_FAST_SYSCALL - tsk->xcall_enable = NULL; + tsk->xinfo = NULL; #endif return tsk; @@ -2097,12 +2099,15 @@ static __latent_entropy struct task_struct *copy_process( rt_mutex_init_task(p); #ifdef CONFIG_FAST_SYSCALL - p->xcall_enable = bitmap_zalloc(__NR_syscalls, GFP_KERNEL); - if (!p->xcall_enable) + p->xinfo = kzalloc(sizeof(struct xcall_info), GFP_KERNEL); + if (!p->xinfo) goto bad_fork_free; - - if (current->xcall_enable) - bitmap_copy(p->xcall_enable, current->xcall_enable, __NR_syscalls); + if (current->xinfo) { + bitmap_copy(p->xinfo->xcall_enable, current->xinfo->xcall_enable, + __NR_syscalls); + bitmap_copy(p->xinfo->xcall_select, current->xinfo->xcall_select, + __NR_syscalls); + } #endif #ifdef CONFIG_QOS_SCHED_DYNAMIC_AFFINITY -- 2.34.1