From: Liao Chang <liaochang1@huawei.com> hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/release-management/issues/ID5CMS -------------------------------- Add xcall_prog_register()/unregister() interface for user module to register xcall syscall. Signed-off-by: Liao Chang <liaochang1@huawei.com> Signed-off-by: Zheng Xinyu <zhengxinyu6@huawei.com> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> --- arch/arm64/kernel/xcall/core.c | 59 ++++++++++++++++++++++++++++++---- include/linux/xcall.h | 12 +++++++ 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kernel/xcall/core.c b/arch/arm64/kernel/xcall/core.c index 5d0a401335c4..ccfc8df323aa 100644 --- a/arch/arm64/kernel/xcall/core.c +++ b/arch/arm64/kernel/xcall/core.c @@ -24,17 +24,23 @@ static struct xcall_prog *get_xcall_prog(const char *module) { struct xcall_prog *p; - spin_lock(&prog_list_lock); list_for_each_entry(p, &progs_list, list) { - if (!strcmp(module, p->name)) { - spin_unlock(&prog_list_lock); + if (!strcmp(module, p->name)) return p; - } } - spin_unlock(&prog_list_lock); return NULL; } +static struct xcall_prog *get_xcall_prog_locked(const char *module) +{ + struct xcall_prog *ret; + + spin_lock(&prog_list_lock); + ret = get_xcall_prog(module); + spin_unlock(&prog_list_lock); + + return ret; +} static struct xcall *get_xcall(struct xcall *xcall) { @@ -104,7 +110,7 @@ static void delete_xcall(struct xcall *xcall) /* Init xcall with a given inode */ static int init_xcall(struct xcall *xcall, struct xcall_comm *comm) { - struct xcall_prog *program = get_xcall_prog(comm->module); + struct xcall_prog *program = get_xcall_prog_locked(comm->module); if (!program || !try_module_get(program->owner)) return -EINVAL; @@ -161,3 +167,44 @@ int xcall_detach(struct xcall_comm *comm) delete_xcall(xcall); return 0; } + +static int check_prog(struct xcall_prog *prog) +{ + struct xcall_prog_object *obj = prog->objs; + + prog->nr_scno = 0; + while (prog->nr_scno < MAX_NR_SCNO && obj->func) { + if (obj->scno >= __NR_syscalls) + return -EINVAL; + + prog->nr_scno++; + obj++; + } + + pr_info("Successly registered syscall number: %d\n", prog->nr_scno); + return 0; +} + +int xcall_prog_register(struct xcall_prog *prog) +{ + if (check_prog(prog)) + return -EINVAL; + + spin_lock(&prog_list_lock); + if (get_xcall_prog(prog->name)) { + spin_unlock(&prog_list_lock); + return -EBUSY; + } + list_add(&prog->list, &progs_list); + spin_unlock(&prog_list_lock); + return 0; +} +EXPORT_SYMBOL(xcall_prog_register); + +void xcall_prog_unregister(struct xcall_prog *prog) +{ + spin_lock(&prog_list_lock); + list_del(&prog->list); + spin_unlock(&prog_list_lock); +} +EXPORT_SYMBOL(xcall_prog_unregister); diff --git a/include/linux/xcall.h b/include/linux/xcall.h index 6b67253a3623..b7110d02c6bd 100644 --- a/include/linux/xcall.h +++ b/include/linux/xcall.h @@ -24,4 +24,16 @@ struct xcall_prog { struct xcall_prog_object objs[MAX_NR_SCNO]; unsigned int nr_scno; }; + +#ifdef CONFIG_DYNAMIC_XCALL +extern int xcall_prog_register(struct xcall_prog *prog); +extern void xcall_prog_unregister(struct xcall_prog *prog); +#else /* !CONFIG_DYNAMIC_XCALL */ +static inline int xcall_prog_register(struct xcall_prog *prog) +{ + return -EINVAL; +} +static inline void xcall_prog_unregister(struct xcall_prog *prog) {} +#endif /* CONFIG_DYNAMIC_XCALL */ + #endif /* _LINUX_XCALL_H */ -- 2.34.1