From a36159eec6ca17402b0e146b86efaf76568dc353 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 20 Sep 2024 01:41:23 +0000 Subject: [PATCH] 重命名 AX88772C_eeprom/asix.c 为 asix_mac.c --- kernel/arch/riscv/kernel/signal.c | 165 +++++++++++++++++++++++++++++++++--------------------- 1 files changed, 100 insertions(+), 65 deletions(-) diff --git a/kernel/arch/riscv/kernel/signal.c b/kernel/arch/riscv/kernel/signal.c index 718d0c9..dd63407 100644 --- a/kernel/arch/riscv/kernel/signal.c +++ b/kernel/arch/riscv/kernel/signal.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. * Chen Liqin <liqin.chen@sunplusct.com> * Lennox Wu <lennox.wu@sunplusct.com> * Copyright (C) 2012 Regents of the University of California - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., */ #include <linux/signal.h> @@ -29,53 +16,83 @@ #include <asm/vdso.h> #include <asm/switch_to.h> #include <asm/csr.h> +#include <asm/cacheflush.h> + +extern u32 __user_rt_sigreturn[2]; #define DEBUG_SIG 0 struct rt_sigframe { struct siginfo info; struct ucontext uc; +#ifndef CONFIG_MMU + u32 sigreturn_code[2]; +#endif }; -static long restore_d_state(struct pt_regs *regs, - struct __riscv_d_ext_state __user *state) +#ifdef CONFIG_FPU +static long restore_fp_state(struct pt_regs *regs, + union __riscv_fp_state __user *sc_fpregs) { long err; - err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state)); - if (likely(!err)) - fstate_restore(current, regs); - return err; -} - -static long save_d_state(struct pt_regs *regs, - struct __riscv_d_ext_state __user *state) -{ - fstate_save(current, regs); - return __copy_to_user(state, ¤t->thread.fstate, sizeof(*state)); -} - -static long restore_sigcontext(struct pt_regs *regs, - struct sigcontext __user *sc) -{ - long err; + struct __riscv_d_ext_state __user *state = &sc_fpregs->d; size_t i; - /* sc_regs is structured the same as the start of pt_regs */ - err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs)); + + err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state)); if (unlikely(err)) return err; - /* Restore the floating-point state. */ - err = restore_d_state(regs, &sc->sc_fpregs.d); - if (unlikely(err)) - return err; + + fstate_restore(current, regs); + /* We support no other extension state at this time. */ - for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) { + for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) { u32 value; - err = __get_user(value, &sc->sc_fpregs.q.reserved[i]); + + err = __get_user(value, &sc_fpregs->q.reserved[i]); if (unlikely(err)) break; if (value != 0) return -EINVAL; } + + return err; +} + +static long save_fp_state(struct pt_regs *regs, + union __riscv_fp_state __user *sc_fpregs) +{ + long err; + struct __riscv_d_ext_state __user *state = &sc_fpregs->d; + size_t i; + + fstate_save(current, regs); + err = __copy_to_user(state, ¤t->thread.fstate, sizeof(*state)); + if (unlikely(err)) + return err; + + /* We support no other extension state at this time. */ + for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) { + err = __put_user(0, &sc_fpregs->q.reserved[i]); + if (unlikely(err)) + break; + } + + return err; +} +#else +#define save_fp_state(task, regs) (0) +#define restore_fp_state(task, regs) (0) +#endif + +static long restore_sigcontext(struct pt_regs *regs, + struct sigcontext __user *sc) +{ + long err; + /* sc_regs is structured the same as the start of pt_regs */ + err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs)); + /* Restore the floating-point state. */ + if (has_fpu) + err |= restore_fp_state(regs, &sc->sc_fpregs); return err; } @@ -91,7 +108,7 @@ frame = (struct rt_sigframe __user *)regs->sp; - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + if (!access_ok(frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) @@ -105,6 +122,8 @@ if (restore_altstack(&frame->uc.uc_stack)) goto badframe; + regs->cause = -1UL; + return regs->a0; badframe: @@ -113,9 +132,9 @@ pr_info_ratelimited( "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n", task->comm, task_pid_nr(task), __func__, - frame, (void *)regs->sepc, (void *)regs->sp); + frame, (void *)regs->epc, (void *)regs->sp); } - force_sig(SIGSEGV, task); + force_sig(SIGSEGV); return 0; } @@ -124,14 +143,11 @@ { struct sigcontext __user *sc = &frame->uc.uc_mcontext; long err; - size_t i; /* sc_regs is structured the same as the start of pt_regs */ err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs)); /* Save the floating-point state. */ - err |= save_d_state(regs, &sc->sc_fpregs.d); - /* We support no other extension state at this time. */ - for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) - err |= __put_user(0, &sc->sc_fpregs.q.reserved[i]); + if (has_fpu) + err |= save_fp_state(regs, &sc->sc_fpregs); return err; } @@ -158,15 +174,15 @@ return (void __user *)sp; } - static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; long err = 0; + unsigned long __maybe_unused addr; frame = get_sigframe(ksig, regs, sizeof(*frame)); - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + if (!access_ok(frame, sizeof(*frame))) return -EFAULT; err |= copy_siginfo_to_user(&frame->info, &ksig->info); @@ -181,8 +197,24 @@ return -EFAULT; /* Set up to return from userspace. */ +#ifdef CONFIG_MMU regs->ra = (unsigned long)VDSO_SYMBOL( current->mm->context.vdso, rt_sigreturn); +#else + /* + * For the nommu case we don't have a VDSO. Instead we push two + * instructions to call the rt_sigreturn syscall onto the user stack. + */ + if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn, + sizeof(frame->sigreturn_code))) + return -EFAULT; + + addr = (unsigned long)&frame->sigreturn_code; + /* Make sure the two instructions are pushed to icache. */ + flush_icache_range(addr, addr + sizeof(frame->sigreturn_code)); + + regs->ra = addr; +#endif /* CONFIG_MMU */ /* * Set up registers for signal handler. @@ -191,7 +223,7 @@ * We always pass siginfo and mcontext, regardless of SA_SIGINFO, * since some things rely on this (e.g. glibc's debug/segfault.c). */ - regs->sepc = (unsigned long)ksig->ka.sa.sa_handler; + regs->epc = (unsigned long)ksig->ka.sa.sa_handler; regs->sp = (unsigned long)frame; regs->a0 = ksig->sig; /* a0: signal number */ regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */ @@ -200,7 +232,7 @@ #if DEBUG_SIG pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n", current->comm, task_pid_nr(current), ksig->sig, - (void *)regs->sepc, (void *)regs->ra, frame); + (void *)regs->epc, (void *)regs->ra, frame); #endif return 0; @@ -212,7 +244,9 @@ int ret; /* Are we from a system call? */ - if (regs->scause == EXC_SYSCALL) { + if (regs->cause == EXC_SYSCALL) { + /* Avoid additional syscall restarting via ret_from_exception */ + regs->cause = -1UL; /* If so, check system call restarting.. */ switch (regs->a0) { case -ERESTART_RESTARTBLOCK: @@ -225,10 +259,10 @@ regs->a0 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: regs->a0 = regs->orig_a0; - regs->sepc -= 0x4; + regs->epc -= 0x4; break; } } @@ -250,19 +284,22 @@ } /* Did we come from a system call? */ - if (regs->scause == EXC_SYSCALL) { + if (regs->cause == EXC_SYSCALL) { + /* Avoid additional syscall restarting via ret_from_exception */ + regs->cause = -1UL; + /* Restart the system call - no handlers present */ switch (regs->a0) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->a0 = regs->orig_a0; - regs->sepc -= 0x4; + regs->epc -= 0x4; break; case -ERESTART_RESTARTBLOCK: regs->a0 = regs->orig_a0; regs->a7 = __NR_restart_syscall; - regs->sepc -= 0x4; + regs->epc -= 0x4; break; } } @@ -278,15 +315,13 @@ * notification of userspace execution resumption * - triggered by the _TIF_WORK_MASK flags */ -asmlinkage void do_notify_resume(struct pt_regs *regs, - unsigned long thread_info_flags) +asmlinkage __visible void do_notify_resume(struct pt_regs *regs, + unsigned long thread_info_flags) { /* Handle pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) do_signal(regs); - if (thread_info_flags & _TIF_NOTIFY_RESUME) { - clear_thread_flag(TIF_NOTIFY_RESUME); + if (thread_info_flags & _TIF_NOTIFY_RESUME) tracehook_notify_resume(regs); - } } -- Gitblit v1.6.2