Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

RISC-V: User-facing API

This patch contains code that is in some way visible to the user:
including via system calls, the VDSO, module loading and signal
handling. It also contains some generic code that is ABI visible.

Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>

+1687
+26
arch/riscv/include/asm/mmu.h
··· 1 + /* 2 + * Copyright (C) 2012 Regents of the University of California 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation, version 2. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + 15 + #ifndef _ASM_RISCV_MMU_H 16 + #define _ASM_RISCV_MMU_H 17 + 18 + #ifndef __ASSEMBLY__ 19 + 20 + typedef struct { 21 + void *vdso; 22 + } mm_context_t; 23 + 24 + #endif /* __ASSEMBLY__ */ 25 + 26 + #endif /* _ASM_RISCV_MMU_H */
+118
arch/riscv/include/asm/ptrace.h
··· 1 + /* 2 + * Copyright (C) 2012 Regents of the University of California 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation, version 2. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #ifndef _ASM_RISCV_PTRACE_H 15 + #define _ASM_RISCV_PTRACE_H 16 + 17 + #include <uapi/asm/ptrace.h> 18 + #include <asm/csr.h> 19 + 20 + #ifndef __ASSEMBLY__ 21 + 22 + struct pt_regs { 23 + unsigned long sepc; 24 + unsigned long ra; 25 + unsigned long sp; 26 + unsigned long gp; 27 + unsigned long tp; 28 + unsigned long t0; 29 + unsigned long t1; 30 + unsigned long t2; 31 + unsigned long s0; 32 + unsigned long s1; 33 + unsigned long a0; 34 + unsigned long a1; 35 + unsigned long a2; 36 + unsigned long a3; 37 + unsigned long a4; 38 + unsigned long a5; 39 + unsigned long a6; 40 + unsigned long a7; 41 + unsigned long s2; 42 + unsigned long s3; 43 + unsigned long s4; 44 + unsigned long s5; 45 + unsigned long s6; 46 + unsigned long s7; 47 + unsigned long s8; 48 + unsigned long s9; 49 + unsigned long s10; 50 + unsigned long s11; 51 + unsigned long t3; 52 + unsigned long t4; 53 + unsigned long t5; 54 + unsigned long t6; 55 + /* Supervisor CSRs */ 56 + unsigned long sstatus; 57 + unsigned long sbadaddr; 58 + unsigned long scause; 59 + /* a0 value before the syscall */ 60 + unsigned long orig_a0; 61 + }; 62 + 63 + #ifdef CONFIG_64BIT 64 + #define REG_FMT "%016lx" 65 + #else 66 + #define REG_FMT "%08lx" 67 + #endif 68 + 69 + #define user_mode(regs) (((regs)->sstatus & SR_PS) == 0) 70 + 71 + 72 + /* Helpers for working with the instruction pointer */ 73 + #define GET_IP(regs) ((regs)->sepc) 74 + #define SET_IP(regs, val) (GET_IP(regs) = (val)) 75 + 76 + static inline unsigned long instruction_pointer(struct pt_regs *regs) 77 + { 78 + return GET_IP(regs); 79 + } 80 + static inline void instruction_pointer_set(struct pt_regs *regs, 81 + unsigned long val) 82 + { 83 + SET_IP(regs, val); 84 + } 85 + 86 + #define profile_pc(regs) instruction_pointer(regs) 87 + 88 + /* Helpers for working with the user stack pointer */ 89 + #define GET_USP(regs) ((regs)->sp) 90 + #define SET_USP(regs, val) (GET_USP(regs) = (val)) 91 + 92 + static inline unsigned long user_stack_pointer(struct pt_regs *regs) 93 + { 94 + return GET_USP(regs); 95 + } 96 + static inline void user_stack_pointer_set(struct pt_regs *regs, 97 + unsigned long val) 98 + { 99 + SET_USP(regs, val); 100 + } 101 + 102 + /* Helpers for working with the frame pointer */ 103 + #define GET_FP(regs) ((regs)->s0) 104 + #define SET_FP(regs, val) (GET_FP(regs) = (val)) 105 + 106 + static inline unsigned long frame_pointer(struct pt_regs *regs) 107 + { 108 + return GET_FP(regs); 109 + } 110 + static inline void frame_pointer_set(struct pt_regs *regs, 111 + unsigned long val) 112 + { 113 + SET_FP(regs, val); 114 + } 115 + 116 + #endif /* __ASSEMBLY__ */ 117 + 118 + #endif /* _ASM_RISCV_PTRACE_H */
+102
arch/riscv/include/asm/syscall.h
··· 1 + /* 2 + * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. 3 + * Copyright 2010 Tilera Corporation. All Rights Reserved. 4 + * Copyright 2015 Regents of the University of California, Berkeley 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation, version 2. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * See asm-generic/syscall.h for descriptions of what we must do here. 16 + */ 17 + 18 + #ifndef _ASM_RISCV_SYSCALL_H 19 + #define _ASM_RISCV_SYSCALL_H 20 + 21 + #include <linux/sched.h> 22 + #include <linux/err.h> 23 + 24 + /* The array of function pointers for syscalls. */ 25 + extern void *sys_call_table[]; 26 + 27 + /* 28 + * Only the low 32 bits of orig_r0 are meaningful, so we return int. 29 + * This importantly ignores the high bits on 64-bit, so comparisons 30 + * sign-extend the low 32 bits. 31 + */ 32 + static inline int syscall_get_nr(struct task_struct *task, 33 + struct pt_regs *regs) 34 + { 35 + return regs->a7; 36 + } 37 + 38 + static inline void syscall_set_nr(struct task_struct *task, 39 + struct pt_regs *regs, 40 + int sysno) 41 + { 42 + regs->a7 = sysno; 43 + } 44 + 45 + static inline void syscall_rollback(struct task_struct *task, 46 + struct pt_regs *regs) 47 + { 48 + regs->a0 = regs->orig_a0; 49 + } 50 + 51 + static inline long syscall_get_error(struct task_struct *task, 52 + struct pt_regs *regs) 53 + { 54 + unsigned long error = regs->a0; 55 + 56 + return IS_ERR_VALUE(error) ? error : 0; 57 + } 58 + 59 + static inline long syscall_get_return_value(struct task_struct *task, 60 + struct pt_regs *regs) 61 + { 62 + return regs->a0; 63 + } 64 + 65 + static inline void syscall_set_return_value(struct task_struct *task, 66 + struct pt_regs *regs, 67 + int error, long val) 68 + { 69 + regs->a0 = (long) error ?: val; 70 + } 71 + 72 + static inline void syscall_get_arguments(struct task_struct *task, 73 + struct pt_regs *regs, 74 + unsigned int i, unsigned int n, 75 + unsigned long *args) 76 + { 77 + BUG_ON(i + n > 6); 78 + if (i == 0) { 79 + args[0] = regs->orig_a0; 80 + args++; 81 + i++; 82 + n--; 83 + } 84 + memcpy(args, &regs->a1 + i * sizeof(regs->a1), n * sizeof(args[0])); 85 + } 86 + 87 + static inline void syscall_set_arguments(struct task_struct *task, 88 + struct pt_regs *regs, 89 + unsigned int i, unsigned int n, 90 + const unsigned long *args) 91 + { 92 + BUG_ON(i + n > 6); 93 + if (i == 0) { 94 + regs->orig_a0 = args[0]; 95 + args++; 96 + i++; 97 + n--; 98 + } 99 + memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0)); 100 + } 101 + 102 + #endif /* _ASM_RISCV_SYSCALL_H */
+16
arch/riscv/include/asm/unistd.h
··· 1 + /* 2 + * Copyright (C) 2012 Regents of the University of California 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation, version 2. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #define __ARCH_HAVE_MMU 15 + #define __ARCH_WANT_SYS_CLONE 16 + #include <uapi/asm/unistd.h>
+41
arch/riscv/include/asm/vdso.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Limited 3 + * Copyright (C) 2014 Regents of the University of California 4 + * Copyright (C) 2017 SiFive 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 + */ 18 + 19 + #ifndef _ASM_RISCV_VDSO_H 20 + #define _ASM_RISCV_VDSO_H 21 + 22 + #include <linux/types.h> 23 + 24 + struct vdso_data { 25 + }; 26 + 27 + /* 28 + * The VDSO symbols are mapped into Linux so we can just use regular symbol 29 + * addressing to get their offsets in userspace. The symbols are mapped at an 30 + * offset of 0, but since the linker must support setting weak undefined 31 + * symbols to the absolute address 0 it also happens to support other low 32 + * addresses even when the code model suggests those low addresses would not 33 + * otherwise be availiable. 34 + */ 35 + #define VDSO_SYMBOL(base, name) \ 36 + ({ \ 37 + extern const char __vdso_##name[]; \ 38 + (void __user *)((unsigned long)(base) + __vdso_##name); \ 39 + }) 40 + 41 + #endif /* _ASM_RISCV_VDSO_H */
+27
arch/riscv/include/uapi/asm/Kbuild
··· 1 + # UAPI Header export list 2 + include include/uapi/asm-generic/Kbuild.asm 3 + 4 + generic-y += setup.h 5 + generic-y += unistd.h 6 + generic-y += errno.h 7 + generic-y += fcntl.h 8 + generic-y += ioctl.h 9 + generic-y += ioctls.h 10 + generic-y += ipcbuf.h 11 + generic-y += mman.h 12 + generic-y += msgbuf.h 13 + generic-y += param.h 14 + generic-y += poll.h 15 + generic-y += posix_types.h 16 + generic-y += resource.h 17 + generic-y += sembuf.h 18 + generic-y += shmbuf.h 19 + generic-y += signal.h 20 + generic-y += socket.h 21 + generic-y += sockios.h 22 + generic-y += stat.h 23 + generic-y += statfs.h 24 + generic-y += swab.h 25 + generic-y += termbits.h 26 + generic-y += termios.h 27 + generic-y += types.h
+24
arch/riscv/include/uapi/asm/auxvec.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * Copyright (C) 2015 Regents of the University of California 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License 15 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 + */ 17 + 18 + #ifndef _UAPI_ASM_RISCV_AUXVEC_H 19 + #define _UAPI_ASM_RISCV_AUXVEC_H 20 + 21 + /* vDSO location */ 22 + #define AT_SYSINFO_EHDR 33 23 + 24 + #endif /* _UAPI_ASM_RISCV_AUXVEC_H */
+25
arch/riscv/include/uapi/asm/bitsperlong.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * Copyright (C) 2015 Regents of the University of California 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License 15 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 + */ 17 + 18 + #ifndef _UAPI_ASM_RISCV_BITSPERLONG_H 19 + #define _UAPI_ASM_RISCV_BITSPERLONG_H 20 + 21 + #define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8) 22 + 23 + #include <asm-generic/bitsperlong.h> 24 + 25 + #endif /* _UAPI_ASM_RISCV_BITSPERLONG_H */
+23
arch/riscv/include/uapi/asm/byteorder.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * Copyright (C) 2015 Regents of the University of California 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License 15 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 + */ 17 + 18 + #ifndef _UAPI_ASM_RISCV_BYTEORDER_H 19 + #define _UAPI_ASM_RISCV_BYTEORDER_H 20 + 21 + #include <linux/byteorder/little_endian.h> 22 + 23 + #endif /* _UAPI_ASM_RISCV_BYTEORDER_H */
+83
arch/riscv/include/uapi/asm/elf.h
··· 1 + /* 2 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 3 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 4 + * Copyright (C) 2012 Regents of the University of California 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + */ 11 + 12 + #ifndef _UAPI_ASM_ELF_H 13 + #define _UAPI_ASM_ELF_H 14 + 15 + #include <asm/ptrace.h> 16 + 17 + /* ELF register definitions */ 18 + typedef unsigned long elf_greg_t; 19 + typedef struct user_regs_struct elf_gregset_t; 20 + #define ELF_NGREG (sizeof(elf_gregset_t) / sizeof(elf_greg_t)) 21 + 22 + typedef union __riscv_fp_state elf_fpregset_t; 23 + 24 + #define ELF_RISCV_R_SYM(r_info) ((r_info) >> 32) 25 + #define ELF_RISCV_R_TYPE(r_info) ((r_info) & 0xffffffff) 26 + 27 + /* 28 + * RISC-V relocation types 29 + */ 30 + 31 + /* Relocation types used by the dynamic linker */ 32 + #define R_RISCV_NONE 0 33 + #define R_RISCV_32 1 34 + #define R_RISCV_64 2 35 + #define R_RISCV_RELATIVE 3 36 + #define R_RISCV_COPY 4 37 + #define R_RISCV_JUMP_SLOT 5 38 + #define R_RISCV_TLS_DTPMOD32 6 39 + #define R_RISCV_TLS_DTPMOD64 7 40 + #define R_RISCV_TLS_DTPREL32 8 41 + #define R_RISCV_TLS_DTPREL64 9 42 + #define R_RISCV_TLS_TPREL32 10 43 + #define R_RISCV_TLS_TPREL64 11 44 + 45 + /* Relocation types not used by the dynamic linker */ 46 + #define R_RISCV_BRANCH 16 47 + #define R_RISCV_JAL 17 48 + #define R_RISCV_CALL 18 49 + #define R_RISCV_CALL_PLT 19 50 + #define R_RISCV_GOT_HI20 20 51 + #define R_RISCV_TLS_GOT_HI20 21 52 + #define R_RISCV_TLS_GD_HI20 22 53 + #define R_RISCV_PCREL_HI20 23 54 + #define R_RISCV_PCREL_LO12_I 24 55 + #define R_RISCV_PCREL_LO12_S 25 56 + #define R_RISCV_HI20 26 57 + #define R_RISCV_LO12_I 27 58 + #define R_RISCV_LO12_S 28 59 + #define R_RISCV_TPREL_HI20 29 60 + #define R_RISCV_TPREL_LO12_I 30 61 + #define R_RISCV_TPREL_LO12_S 31 62 + #define R_RISCV_TPREL_ADD 32 63 + #define R_RISCV_ADD8 33 64 + #define R_RISCV_ADD16 34 65 + #define R_RISCV_ADD32 35 66 + #define R_RISCV_ADD64 36 67 + #define R_RISCV_SUB8 37 68 + #define R_RISCV_SUB16 38 69 + #define R_RISCV_SUB32 39 70 + #define R_RISCV_SUB64 40 71 + #define R_RISCV_GNU_VTINHERIT 41 72 + #define R_RISCV_GNU_VTENTRY 42 73 + #define R_RISCV_ALIGN 43 74 + #define R_RISCV_RVC_BRANCH 44 75 + #define R_RISCV_RVC_JUMP 45 76 + #define R_RISCV_LUI 46 77 + #define R_RISCV_GPREL_I 47 78 + #define R_RISCV_GPREL_S 48 79 + #define R_RISCV_TPREL_I 49 80 + #define R_RISCV_TPREL_S 50 81 + #define R_RISCV_RELAX 51 82 + 83 + #endif /* _UAPI_ASM_ELF_H */
+36
arch/riscv/include/uapi/asm/hwcap.h
··· 1 + /* 2 + * Copied from arch/arm64/include/asm/hwcap.h 3 + * 4 + * Copyright (C) 2012 ARM Ltd. 5 + * Copyright (C) 2017 SiFive 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + #ifndef __UAPI_ASM_HWCAP_H 20 + #define __UAPI_ASM_HWCAP_H 21 + 22 + /* 23 + * Linux saves the floating-point registers according to the ISA Linux is 24 + * executing on, as opposed to the ISA the user program is compiled for. This 25 + * is necessary for a handful of esoteric use cases: for example, userpsace 26 + * threading libraries must be able to examine the actual machine state in 27 + * order to fully reconstruct the state of a thread. 28 + */ 29 + #define COMPAT_HWCAP_ISA_I (1 << ('I' - 'A')) 30 + #define COMPAT_HWCAP_ISA_M (1 << ('M' - 'A')) 31 + #define COMPAT_HWCAP_ISA_A (1 << ('A' - 'A')) 32 + #define COMPAT_HWCAP_ISA_F (1 << ('F' - 'A')) 33 + #define COMPAT_HWCAP_ISA_D (1 << ('D' - 'A')) 34 + #define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) 35 + 36 + #endif
+90
arch/riscv/include/uapi/asm/ptrace.h
··· 1 + /* 2 + * Copyright (C) 2012 Regents of the University of California 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation, version 2. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #ifndef _UAPI_ASM_RISCV_PTRACE_H 15 + #define _UAPI_ASM_RISCV_PTRACE_H 16 + 17 + #ifndef __ASSEMBLY__ 18 + 19 + #include <linux/types.h> 20 + 21 + /* 22 + * User-mode register state for core dumps, ptrace, sigcontext 23 + * 24 + * This decouples struct pt_regs from the userspace ABI. 25 + * struct user_regs_struct must form a prefix of struct pt_regs. 26 + */ 27 + struct user_regs_struct { 28 + unsigned long pc; 29 + unsigned long ra; 30 + unsigned long sp; 31 + unsigned long gp; 32 + unsigned long tp; 33 + unsigned long t0; 34 + unsigned long t1; 35 + unsigned long t2; 36 + unsigned long s0; 37 + unsigned long s1; 38 + unsigned long a0; 39 + unsigned long a1; 40 + unsigned long a2; 41 + unsigned long a3; 42 + unsigned long a4; 43 + unsigned long a5; 44 + unsigned long a6; 45 + unsigned long a7; 46 + unsigned long s2; 47 + unsigned long s3; 48 + unsigned long s4; 49 + unsigned long s5; 50 + unsigned long s6; 51 + unsigned long s7; 52 + unsigned long s8; 53 + unsigned long s9; 54 + unsigned long s10; 55 + unsigned long s11; 56 + unsigned long t3; 57 + unsigned long t4; 58 + unsigned long t5; 59 + unsigned long t6; 60 + }; 61 + 62 + struct __riscv_f_ext_state { 63 + __u32 f[32]; 64 + __u32 fcsr; 65 + }; 66 + 67 + struct __riscv_d_ext_state { 68 + __u64 f[32]; 69 + __u32 fcsr; 70 + }; 71 + 72 + struct __riscv_q_ext_state { 73 + __u64 f[64] __attribute__((aligned(16))); 74 + __u32 fcsr; 75 + /* 76 + * Reserved for expansion of sigcontext structure. Currently zeroed 77 + * upon signal, and must be zero upon sigreturn. 78 + */ 79 + __u32 reserved[3]; 80 + }; 81 + 82 + union __riscv_fp_state { 83 + struct __riscv_f_ext_state f; 84 + struct __riscv_d_ext_state d; 85 + struct __riscv_q_ext_state q; 86 + }; 87 + 88 + #endif /* __ASSEMBLY__ */ 89 + 90 + #endif /* _UAPI_ASM_RISCV_PTRACE_H */
+30
arch/riscv/include/uapi/asm/sigcontext.h
··· 1 + /* 2 + * Copyright (C) 2012 Regents of the University of California 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation, version 2. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #ifndef _UAPI_ASM_RISCV_SIGCONTEXT_H 15 + #define _UAPI_ASM_RISCV_SIGCONTEXT_H 16 + 17 + #include <asm/ptrace.h> 18 + 19 + /* 20 + * Signal context structure 21 + * 22 + * This contains the context saved before a signal handler is invoked; 23 + * it is restored by sys_sigreturn / sys_rt_sigreturn. 24 + */ 25 + struct sigcontext { 26 + struct user_regs_struct sc_regs; 27 + union __riscv_fp_state sc_fpregs; 28 + }; 29 + 30 + #endif /* _UAPI_ASM_RISCV_SIGCONTEXT_H */
+24
arch/riscv/include/uapi/asm/siginfo.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * Copyright (C) 2016 SiFive, Inc. 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License 15 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 + */ 17 + #ifndef __ASM_SIGINFO_H 18 + #define __ASM_SIGINFO_H 19 + 20 + #define __ARCH_SI_PREAMBLE_SIZE (__SIZEOF_POINTER__ == 4 ? 12 : 16) 21 + 22 + #include <asm-generic/siginfo.h> 23 + 24 + #endif
+45
arch/riscv/include/uapi/asm/ucontext.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * Copyright (C) 2017 SiFive, Inc. 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License 15 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 + * 17 + * This file was copied from arch/arm64/include/uapi/asm/ucontext.h 18 + */ 19 + #ifndef _UAPI__ASM_UCONTEXT_H 20 + #define _UAPI__ASM_UCONTEXT_H 21 + 22 + #include <linux/types.h> 23 + 24 + struct ucontext { 25 + unsigned long uc_flags; 26 + struct ucontext *uc_link; 27 + stack_t uc_stack; 28 + sigset_t uc_sigmask; 29 + /* There's some padding here to allow sigset_t to be expanded in the 30 + * future. Though this is unlikely, other architectures put uc_sigmask 31 + * at the end of this structure and explicitly state it can be 32 + * expanded, so we didn't want to box ourselves in here. */ 33 + __u8 __unused[1024 / 8 - sizeof(sigset_t)]; 34 + /* We can't put uc_sigmask at the end of this structure because we need 35 + * to be able to expand sigcontext in the future. For example, the 36 + * vector ISA extension will almost certainly add ISA state. We want 37 + * to ensure all user-visible ISA state can be saved and restored via a 38 + * ucontext, so we're putting this at the end in order to allow for 39 + * infinite extensibility. Since we know this will be extended and we 40 + * assume sigset_t won't be extended an extreme amount, we're 41 + * prioritizing this. */ 42 + struct sigcontext uc_mcontext; 43 + }; 44 + 45 + #endif /* _UAPI__ASM_UCONTEXT_H */
+61
arch/riscv/kernel/cpufeature.c
··· 1 + /* 2 + * Copied from arch/arm64/kernel/cpufeature.c 3 + * 4 + * Copyright (C) 2015 ARM Ltd. 5 + * Copyright (C) 2017 SiFive 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include <linux/of.h> 21 + #include <asm/processor.h> 22 + #include <asm/hwcap.h> 23 + 24 + unsigned long elf_hwcap __read_mostly; 25 + 26 + void riscv_fill_hwcap(void) 27 + { 28 + struct device_node *node; 29 + const char *isa; 30 + size_t i; 31 + static unsigned long isa2hwcap[256] = {0}; 32 + 33 + isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I; 34 + isa2hwcap['m'] = isa2hwcap['M'] = COMPAT_HWCAP_ISA_M; 35 + isa2hwcap['a'] = isa2hwcap['A'] = COMPAT_HWCAP_ISA_A; 36 + isa2hwcap['f'] = isa2hwcap['F'] = COMPAT_HWCAP_ISA_F; 37 + isa2hwcap['d'] = isa2hwcap['D'] = COMPAT_HWCAP_ISA_D; 38 + isa2hwcap['c'] = isa2hwcap['C'] = COMPAT_HWCAP_ISA_C; 39 + 40 + elf_hwcap = 0; 41 + 42 + /* 43 + * We don't support running Linux on hertergenous ISA systems. For 44 + * now, we just check the ISA of the first processor. 45 + */ 46 + node = of_find_node_by_type(NULL, "cpu"); 47 + if (!node) { 48 + pr_warning("Unable to find \"cpu\" devicetree entry"); 49 + return; 50 + } 51 + 52 + if (of_property_read_string(node, "riscv,isa", &isa)) { 53 + pr_warning("Unable to find \"riscv,isa\" devicetree entry"); 54 + return; 55 + } 56 + 57 + for (i = 0; i < strlen(isa); ++i) 58 + elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])]; 59 + 60 + pr_info("elf_hwcap is 0x%lx", elf_hwcap); 61 + }
+217
arch/riscv/kernel/module.c
··· 1 + /* 2 + * This program is free software; you can redistribute it and/or modify 3 + * it under the terms of the GNU General Public License as published by 4 + * the Free Software Foundation; either version 2 of the License, or 5 + * (at your option) any later version. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * GNU General Public License for more details. 11 + * 12 + * Copyright (C) 2017 Zihao Yu 13 + */ 14 + 15 + #include <linux/elf.h> 16 + #include <linux/err.h> 17 + #include <linux/errno.h> 18 + #include <linux/moduleloader.h> 19 + 20 + static int apply_r_riscv_64_rela(struct module *me, u32 *location, Elf_Addr v) 21 + { 22 + *(u64 *)location = v; 23 + return 0; 24 + } 25 + 26 + static int apply_r_riscv_branch_rela(struct module *me, u32 *location, 27 + Elf_Addr v) 28 + { 29 + s64 offset = (void *)v - (void *)location; 30 + u32 imm12 = (offset & 0x1000) << (31 - 12); 31 + u32 imm11 = (offset & 0x800) >> (11 - 7); 32 + u32 imm10_5 = (offset & 0x7e0) << (30 - 10); 33 + u32 imm4_1 = (offset & 0x1e) << (11 - 4); 34 + 35 + *location = (*location & 0x1fff07f) | imm12 | imm11 | imm10_5 | imm4_1; 36 + return 0; 37 + } 38 + 39 + static int apply_r_riscv_jal_rela(struct module *me, u32 *location, 40 + Elf_Addr v) 41 + { 42 + s64 offset = (void *)v - (void *)location; 43 + u32 imm20 = (offset & 0x100000) << (31 - 20); 44 + u32 imm19_12 = (offset & 0xff000); 45 + u32 imm11 = (offset & 0x800) << (20 - 11); 46 + u32 imm10_1 = (offset & 0x7fe) << (30 - 10); 47 + 48 + *location = (*location & 0xfff) | imm20 | imm19_12 | imm11 | imm10_1; 49 + return 0; 50 + } 51 + 52 + static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location, 53 + Elf_Addr v) 54 + { 55 + s64 offset = (void *)v - (void *)location; 56 + s32 hi20; 57 + 58 + if (offset != (s32)offset) { 59 + pr_err( 60 + "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", 61 + me->name, v, location); 62 + return -EINVAL; 63 + } 64 + 65 + hi20 = (offset + 0x800) & 0xfffff000; 66 + *location = (*location & 0xfff) | hi20; 67 + return 0; 68 + } 69 + 70 + static int apply_r_riscv_pcrel_lo12_i_rela(struct module *me, u32 *location, 71 + Elf_Addr v) 72 + { 73 + /* 74 + * v is the lo12 value to fill. It is calculated before calling this 75 + * handler. 76 + */ 77 + *location = (*location & 0xfffff) | ((v & 0xfff) << 20); 78 + return 0; 79 + } 80 + 81 + static int apply_r_riscv_pcrel_lo12_s_rela(struct module *me, u32 *location, 82 + Elf_Addr v) 83 + { 84 + /* 85 + * v is the lo12 value to fill. It is calculated before calling this 86 + * handler. 87 + */ 88 + u32 imm11_5 = (v & 0xfe0) << (31 - 11); 89 + u32 imm4_0 = (v & 0x1f) << (11 - 4); 90 + 91 + *location = (*location & 0x1fff07f) | imm11_5 | imm4_0; 92 + return 0; 93 + } 94 + 95 + static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location, 96 + Elf_Addr v) 97 + { 98 + s64 offset = (void *)v - (void *)location; 99 + s32 fill_v = offset; 100 + u32 hi20, lo12; 101 + 102 + if (offset != fill_v) { 103 + pr_err( 104 + "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", 105 + me->name, v, location); 106 + return -EINVAL; 107 + } 108 + 109 + hi20 = (offset + 0x800) & 0xfffff000; 110 + lo12 = (offset - hi20) & 0xfff; 111 + *location = (*location & 0xfff) | hi20; 112 + *(location + 1) = (*(location + 1) & 0xfffff) | (lo12 << 20); 113 + return 0; 114 + } 115 + 116 + static int apply_r_riscv_relax_rela(struct module *me, u32 *location, 117 + Elf_Addr v) 118 + { 119 + return 0; 120 + } 121 + 122 + static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, 123 + Elf_Addr v) = { 124 + [R_RISCV_64] = apply_r_riscv_64_rela, 125 + [R_RISCV_BRANCH] = apply_r_riscv_branch_rela, 126 + [R_RISCV_JAL] = apply_r_riscv_jal_rela, 127 + [R_RISCV_PCREL_HI20] = apply_r_riscv_pcrel_hi20_rela, 128 + [R_RISCV_PCREL_LO12_I] = apply_r_riscv_pcrel_lo12_i_rela, 129 + [R_RISCV_PCREL_LO12_S] = apply_r_riscv_pcrel_lo12_s_rela, 130 + [R_RISCV_CALL_PLT] = apply_r_riscv_call_plt_rela, 131 + [R_RISCV_RELAX] = apply_r_riscv_relax_rela, 132 + }; 133 + 134 + int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, 135 + unsigned int symindex, unsigned int relsec, 136 + struct module *me) 137 + { 138 + Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr; 139 + int (*handler)(struct module *me, u32 *location, Elf_Addr v); 140 + Elf_Sym *sym; 141 + u32 *location; 142 + unsigned int i, type; 143 + Elf_Addr v; 144 + int res; 145 + 146 + pr_debug("Applying relocate section %u to %u\n", relsec, 147 + sechdrs[relsec].sh_info); 148 + 149 + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 150 + /* This is where to make the change */ 151 + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 152 + + rel[i].r_offset; 153 + /* This is the symbol it is referring to */ 154 + sym = (Elf_Sym *)sechdrs[symindex].sh_addr 155 + + ELF_RISCV_R_SYM(rel[i].r_info); 156 + if (IS_ERR_VALUE(sym->st_value)) { 157 + /* Ignore unresolved weak symbol */ 158 + if (ELF_ST_BIND(sym->st_info) == STB_WEAK) 159 + continue; 160 + pr_warning("%s: Unknown symbol %s\n", 161 + me->name, strtab + sym->st_name); 162 + return -ENOENT; 163 + } 164 + 165 + type = ELF_RISCV_R_TYPE(rel[i].r_info); 166 + 167 + if (type < ARRAY_SIZE(reloc_handlers_rela)) 168 + handler = reloc_handlers_rela[type]; 169 + else 170 + handler = NULL; 171 + 172 + if (!handler) { 173 + pr_err("%s: Unknown relocation type %u\n", 174 + me->name, type); 175 + return -EINVAL; 176 + } 177 + 178 + v = sym->st_value + rel[i].r_addend; 179 + 180 + if (type == R_RISCV_PCREL_LO12_I || type == R_RISCV_PCREL_LO12_S) { 181 + unsigned int j; 182 + 183 + for (j = 0; j < sechdrs[relsec].sh_size / sizeof(*rel); j++) { 184 + u64 hi20_loc = 185 + sechdrs[sechdrs[relsec].sh_info].sh_addr 186 + + rel[j].r_offset; 187 + /* Find the corresponding HI20 PC-relative relocation entry */ 188 + if (hi20_loc == sym->st_value) { 189 + Elf_Sym *hi20_sym = 190 + (Elf_Sym *)sechdrs[symindex].sh_addr 191 + + ELF_RISCV_R_SYM(rel[j].r_info); 192 + u64 hi20_sym_val = 193 + hi20_sym->st_value 194 + + rel[j].r_addend; 195 + /* Calculate lo12 */ 196 + s64 offset = hi20_sym_val - hi20_loc; 197 + s32 hi20 = (offset + 0x800) & 0xfffff000; 198 + s32 lo12 = offset - hi20; 199 + v = lo12; 200 + break; 201 + } 202 + } 203 + if (j == sechdrs[relsec].sh_size / sizeof(*rel)) { 204 + pr_err( 205 + "%s: Can not find HI20 PC-relative relocation information\n", 206 + me->name); 207 + return -EINVAL; 208 + } 209 + } 210 + 211 + res = handler(me, location, v); 212 + if (res) 213 + return res; 214 + } 215 + 216 + return 0; 217 + }
+125
arch/riscv/kernel/ptrace.c
··· 1 + /* 2 + * Copyright 2010 Tilera Corporation. All Rights Reserved. 3 + * Copyright 2015 Regents of the University of California 4 + * Copyright 2017 SiFive 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation, version 2. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * Copied from arch/tile/kernel/ptrace.c 16 + */ 17 + 18 + #include <asm/ptrace.h> 19 + #include <asm/syscall.h> 20 + #include <asm/thread_info.h> 21 + #include <linux/ptrace.h> 22 + #include <linux/elf.h> 23 + #include <linux/regset.h> 24 + #include <linux/sched.h> 25 + #include <linux/sched/task_stack.h> 26 + #include <linux/tracehook.h> 27 + #include <trace/events/syscalls.h> 28 + 29 + enum riscv_regset { 30 + REGSET_X, 31 + }; 32 + 33 + static int riscv_gpr_get(struct task_struct *target, 34 + const struct user_regset *regset, 35 + unsigned int pos, unsigned int count, 36 + void *kbuf, void __user *ubuf) 37 + { 38 + struct pt_regs *regs; 39 + 40 + regs = task_pt_regs(target); 41 + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1); 42 + } 43 + 44 + static int riscv_gpr_set(struct task_struct *target, 45 + const struct user_regset *regset, 46 + unsigned int pos, unsigned int count, 47 + const void *kbuf, const void __user *ubuf) 48 + { 49 + int ret; 50 + struct pt_regs *regs; 51 + 52 + regs = task_pt_regs(target); 53 + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &regs, 0, -1); 54 + return ret; 55 + } 56 + 57 + 58 + static const struct user_regset riscv_user_regset[] = { 59 + [REGSET_X] = { 60 + .core_note_type = NT_PRSTATUS, 61 + .n = ELF_NGREG, 62 + .size = sizeof(elf_greg_t), 63 + .align = sizeof(elf_greg_t), 64 + .get = &riscv_gpr_get, 65 + .set = &riscv_gpr_set, 66 + }, 67 + }; 68 + 69 + static const struct user_regset_view riscv_user_native_view = { 70 + .name = "riscv", 71 + .e_machine = EM_RISCV, 72 + .regsets = riscv_user_regset, 73 + .n = ARRAY_SIZE(riscv_user_regset), 74 + }; 75 + 76 + const struct user_regset_view *task_user_regset_view(struct task_struct *task) 77 + { 78 + return &riscv_user_native_view; 79 + } 80 + 81 + void ptrace_disable(struct task_struct *child) 82 + { 83 + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 84 + } 85 + 86 + long arch_ptrace(struct task_struct *child, long request, 87 + unsigned long addr, unsigned long data) 88 + { 89 + long ret = -EIO; 90 + 91 + switch (request) { 92 + default: 93 + ret = ptrace_request(child, request, addr, data); 94 + break; 95 + } 96 + 97 + return ret; 98 + } 99 + 100 + /* 101 + * Allows PTRACE_SYSCALL to work. These are called from entry.S in 102 + * {handle,ret_from}_syscall. 103 + */ 104 + void do_syscall_trace_enter(struct pt_regs *regs) 105 + { 106 + if (test_thread_flag(TIF_SYSCALL_TRACE)) 107 + if (tracehook_report_syscall_entry(regs)) 108 + syscall_set_nr(current, regs, -1); 109 + 110 + #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS 111 + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 112 + trace_sys_enter(regs, syscall_get_nr(current, regs)); 113 + #endif 114 + } 115 + 116 + void do_syscall_trace_exit(struct pt_regs *regs) 117 + { 118 + if (test_thread_flag(TIF_SYSCALL_TRACE)) 119 + tracehook_report_syscall_exit(regs, 0); 120 + 121 + #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS 122 + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 123 + trace_sys_exit(regs, regs->regs[0]); 124 + #endif 125 + }
+15
arch/riscv/kernel/riscv_ksyms.c
··· 1 + /* 2 + * Copyright (C) 2017 Zihao Yu 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/export.h> 10 + #include <linux/uaccess.h> 11 + 12 + /* 13 + * Assembly functions that may be used (directly or indirectly) by modules 14 + */ 15 + EXPORT_SYMBOL(__copy_user);
+292
arch/riscv/kernel/signal.c
··· 1 + /* 2 + * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. 3 + * Chen Liqin <liqin.chen@sunplusct.com> 4 + * Lennox Wu <lennox.wu@sunplusct.com> 5 + * Copyright (C) 2012 Regents of the University of California 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License as published by 9 + * the Free Software Foundation; either version 2 of the License, or 10 + * (at your option) any later version. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + * You should have received a copy of the GNU General Public License 18 + * along with this program; if not, see the file COPYING, or write 19 + * to the Free Software Foundation, Inc., 20 + */ 21 + 22 + #include <linux/signal.h> 23 + #include <linux/uaccess.h> 24 + #include <linux/syscalls.h> 25 + #include <linux/tracehook.h> 26 + #include <linux/linkage.h> 27 + 28 + #include <asm/ucontext.h> 29 + #include <asm/vdso.h> 30 + #include <asm/switch_to.h> 31 + #include <asm/csr.h> 32 + 33 + #define DEBUG_SIG 0 34 + 35 + struct rt_sigframe { 36 + struct siginfo info; 37 + struct ucontext uc; 38 + }; 39 + 40 + static long restore_d_state(struct pt_regs *regs, 41 + struct __riscv_d_ext_state __user *state) 42 + { 43 + long err; 44 + err = __copy_from_user(&current->thread.fstate, state, sizeof(*state)); 45 + if (likely(!err)) 46 + fstate_restore(current, regs); 47 + return err; 48 + } 49 + 50 + static long save_d_state(struct pt_regs *regs, 51 + struct __riscv_d_ext_state __user *state) 52 + { 53 + fstate_save(current, regs); 54 + return __copy_to_user(state, &current->thread.fstate, sizeof(*state)); 55 + } 56 + 57 + static long restore_sigcontext(struct pt_regs *regs, 58 + struct sigcontext __user *sc) 59 + { 60 + long err; 61 + size_t i; 62 + /* sc_regs is structured the same as the start of pt_regs */ 63 + err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs)); 64 + if (unlikely(err)) 65 + return err; 66 + /* Restore the floating-point state. */ 67 + err = restore_d_state(regs, &sc->sc_fpregs.d); 68 + if (unlikely(err)) 69 + return err; 70 + /* We support no other extension state at this time. */ 71 + for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) { 72 + u32 value; 73 + err = __get_user(value, &sc->sc_fpregs.q.reserved[i]); 74 + if (unlikely(err)) 75 + break; 76 + if (value != 0) 77 + return -EINVAL; 78 + } 79 + return err; 80 + } 81 + 82 + SYSCALL_DEFINE0(rt_sigreturn) 83 + { 84 + struct pt_regs *regs = current_pt_regs(); 85 + struct rt_sigframe __user *frame; 86 + struct task_struct *task; 87 + sigset_t set; 88 + 89 + /* Always make any pending restarted system calls return -EINTR */ 90 + current->restart_block.fn = do_no_restart_syscall; 91 + 92 + frame = (struct rt_sigframe __user *)regs->sp; 93 + 94 + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 95 + goto badframe; 96 + 97 + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 98 + goto badframe; 99 + 100 + set_current_blocked(&set); 101 + 102 + if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 103 + goto badframe; 104 + 105 + if (restore_altstack(&frame->uc.uc_stack)) 106 + goto badframe; 107 + 108 + return regs->a0; 109 + 110 + badframe: 111 + task = current; 112 + if (show_unhandled_signals) { 113 + pr_info_ratelimited( 114 + "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n", 115 + task->comm, task_pid_nr(task), __func__, 116 + frame, (void *)regs->sepc, (void *)regs->sp); 117 + } 118 + force_sig(SIGSEGV, task); 119 + return 0; 120 + } 121 + 122 + static long setup_sigcontext(struct rt_sigframe __user *frame, 123 + struct pt_regs *regs) 124 + { 125 + struct sigcontext __user *sc = &frame->uc.uc_mcontext; 126 + long err; 127 + size_t i; 128 + /* sc_regs is structured the same as the start of pt_regs */ 129 + err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs)); 130 + /* Save the floating-point state. */ 131 + err |= save_d_state(regs, &sc->sc_fpregs.d); 132 + /* We support no other extension state at this time. */ 133 + for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) 134 + err |= __put_user(0, &sc->sc_fpregs.q.reserved[i]); 135 + return err; 136 + } 137 + 138 + static inline void __user *get_sigframe(struct ksignal *ksig, 139 + struct pt_regs *regs, size_t framesize) 140 + { 141 + unsigned long sp; 142 + /* Default to using normal stack */ 143 + sp = regs->sp; 144 + 145 + /* 146 + * If we are on the alternate signal stack and would overflow it, don't. 147 + * Return an always-bogus address instead so we will die with SIGSEGV. 148 + */ 149 + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) 150 + return (void __user __force *)(-1UL); 151 + 152 + /* This is the X/Open sanctioned signal stack switching. */ 153 + sp = sigsp(sp, ksig) - framesize; 154 + 155 + /* Align the stack frame. */ 156 + sp &= ~0xfUL; 157 + 158 + return (void __user *)sp; 159 + } 160 + 161 + 162 + static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, 163 + struct pt_regs *regs) 164 + { 165 + struct rt_sigframe __user *frame; 166 + long err = 0; 167 + 168 + frame = get_sigframe(ksig, regs, sizeof(*frame)); 169 + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 170 + return -EFAULT; 171 + 172 + err |= copy_siginfo_to_user(&frame->info, &ksig->info); 173 + 174 + /* Create the ucontext. */ 175 + err |= __put_user(0, &frame->uc.uc_flags); 176 + err |= __put_user(NULL, &frame->uc.uc_link); 177 + err |= __save_altstack(&frame->uc.uc_stack, regs->sp); 178 + err |= setup_sigcontext(frame, regs); 179 + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 180 + if (err) 181 + return -EFAULT; 182 + 183 + /* Set up to return from userspace. */ 184 + regs->ra = (unsigned long)VDSO_SYMBOL( 185 + current->mm->context.vdso, rt_sigreturn); 186 + 187 + /* 188 + * Set up registers for signal handler. 189 + * Registers that we don't modify keep the value they had from 190 + * user-space at the time we took the signal. 191 + * We always pass siginfo and mcontext, regardless of SA_SIGINFO, 192 + * since some things rely on this (e.g. glibc's debug/segfault.c). 193 + */ 194 + regs->sepc = (unsigned long)ksig->ka.sa.sa_handler; 195 + regs->sp = (unsigned long)frame; 196 + regs->a0 = ksig->sig; /* a0: signal number */ 197 + regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */ 198 + regs->a2 = (unsigned long)(&frame->uc); /* a2: ucontext pointer */ 199 + 200 + #if DEBUG_SIG 201 + pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n", 202 + current->comm, task_pid_nr(current), ksig->sig, 203 + (void *)regs->sepc, (void *)regs->ra, frame); 204 + #endif 205 + 206 + return 0; 207 + } 208 + 209 + static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) 210 + { 211 + sigset_t *oldset = sigmask_to_save(); 212 + int ret; 213 + 214 + /* Are we from a system call? */ 215 + if (regs->scause == EXC_SYSCALL) { 216 + /* If so, check system call restarting.. */ 217 + switch (regs->a0) { 218 + case -ERESTART_RESTARTBLOCK: 219 + case -ERESTARTNOHAND: 220 + regs->a0 = -EINTR; 221 + break; 222 + 223 + case -ERESTARTSYS: 224 + if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 225 + regs->a0 = -EINTR; 226 + break; 227 + } 228 + /* fallthrough */ 229 + case -ERESTARTNOINTR: 230 + regs->a0 = regs->orig_a0; 231 + regs->sepc -= 0x4; 232 + break; 233 + } 234 + } 235 + 236 + /* Set up the stack frame */ 237 + ret = setup_rt_frame(ksig, oldset, regs); 238 + 239 + signal_setup_done(ret, ksig, 0); 240 + } 241 + 242 + static void do_signal(struct pt_regs *regs) 243 + { 244 + struct ksignal ksig; 245 + 246 + if (get_signal(&ksig)) { 247 + /* Actually deliver the signal */ 248 + handle_signal(&ksig, regs); 249 + return; 250 + } 251 + 252 + /* Did we come from a system call? */ 253 + if (regs->scause == EXC_SYSCALL) { 254 + /* Restart the system call - no handlers present */ 255 + switch (regs->a0) { 256 + case -ERESTARTNOHAND: 257 + case -ERESTARTSYS: 258 + case -ERESTARTNOINTR: 259 + regs->a0 = regs->orig_a0; 260 + regs->sepc -= 0x4; 261 + break; 262 + case -ERESTART_RESTARTBLOCK: 263 + regs->a0 = regs->orig_a0; 264 + regs->a7 = __NR_restart_syscall; 265 + regs->sepc -= 0x4; 266 + break; 267 + } 268 + } 269 + 270 + /* 271 + * If there is no signal to deliver, we just put the saved 272 + * sigmask back. 273 + */ 274 + restore_saved_sigmask(); 275 + } 276 + 277 + /* 278 + * notification of userspace execution resumption 279 + * - triggered by the _TIF_WORK_MASK flags 280 + */ 281 + asmlinkage void do_notify_resume(struct pt_regs *regs, 282 + unsigned long thread_info_flags) 283 + { 284 + /* Handle pending signal delivery */ 285 + if (thread_info_flags & _TIF_SIGPENDING) 286 + do_signal(regs); 287 + 288 + if (thread_info_flags & _TIF_NOTIFY_RESUME) { 289 + clear_thread_flag(TIF_NOTIFY_RESUME); 290 + tracehook_notify_resume(regs); 291 + } 292 + }
+49
arch/riscv/kernel/sys_riscv.c
··· 1 + /* 2 + * Copyright (C) 2012 Regents of the University of California 3 + * Copyright (C) 2014 Darius Rad <darius@bluespec.com> 4 + * Copyright (C) 2017 SiFive 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation, version 2. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + */ 15 + 16 + #include <linux/syscalls.h> 17 + #include <asm/cmpxchg.h> 18 + #include <asm/unistd.h> 19 + 20 + static long riscv_sys_mmap(unsigned long addr, unsigned long len, 21 + unsigned long prot, unsigned long flags, 22 + unsigned long fd, off_t offset, 23 + unsigned long page_shift_offset) 24 + { 25 + if (unlikely(offset & (~PAGE_MASK >> page_shift_offset))) 26 + return -EINVAL; 27 + return sys_mmap_pgoff(addr, len, prot, flags, fd, 28 + offset >> (PAGE_SHIFT - page_shift_offset)); 29 + } 30 + 31 + #ifdef CONFIG_64BIT 32 + SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, 33 + unsigned long, prot, unsigned long, flags, 34 + unsigned long, fd, off_t, offset) 35 + { 36 + return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 0); 37 + } 38 + #else 39 + SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, 40 + unsigned long, prot, unsigned long, flags, 41 + unsigned long, fd, off_t, offset) 42 + { 43 + /* 44 + * Note that the shift for mmap2 is constant (12), 45 + * regardless of PAGE_SIZE 46 + */ 47 + return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 12); 48 + } 49 + #endif /* !CONFIG_64BIT */
+25
arch/riscv/kernel/syscall_table.c
··· 1 + /* 2 + * Copyright (C) 2009 Arnd Bergmann <arnd@arndb.de> 3 + * Copyright (C) 2012 Regents of the University of California 4 + * 5 + * This program is free software; you can redistribute it and/or 6 + * modify it under the terms of the GNU General Public License 7 + * as published by the Free Software Foundation, version 2. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + */ 14 + 15 + #include <linux/linkage.h> 16 + #include <linux/syscalls.h> 17 + #include <asm-generic/syscalls.h> 18 + 19 + #undef __SYSCALL 20 + #define __SYSCALL(nr, call) [nr] = (call), 21 + 22 + void *sys_call_table[__NR_syscalls] = { 23 + [0 ... __NR_syscalls - 1] = sys_ni_syscall, 24 + #include <asm/unistd.h> 25 + };
+2
arch/riscv/kernel/vdso/.gitignore
··· 1 + vdso.lds 2 + *.tmp
+63
arch/riscv/kernel/vdso/Makefile
··· 1 + # Copied from arch/tile/kernel/vdso/Makefile 2 + 3 + # Symbols present in the vdso 4 + vdso-syms = rt_sigreturn 5 + 6 + # Files to link into the vdso 7 + obj-vdso = $(patsubst %, %.o, $(vdso-syms)) 8 + 9 + # Build rules 10 + targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-dummy.o 11 + obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) 12 + 13 + obj-y += vdso.o vdso-syms.o 14 + CPPFLAGS_vdso.lds += -P -C -U$(ARCH) 15 + 16 + # Disable gcov profiling for VDSO code 17 + GCOV_PROFILE := n 18 + 19 + # Force dependency 20 + $(obj)/vdso.o: $(obj)/vdso.so 21 + 22 + # link rule for the .so file, .lds has to be first 23 + SYSCFLAGS_vdso.so.dbg = $(c_flags) 24 + $(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso) FORCE 25 + $(call if_changed,vdsold) 26 + 27 + # We also create a special relocatable object that should mirror the symbol 28 + # table and layout of the linked DSO. With ld -R we can then refer to 29 + # these symbols in the kernel code rather than hand-coded addresses. 30 + 31 + SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \ 32 + $(call cc-ldoption, -Wl$(comma)--hash-style=both) 33 + $(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE 34 + $(call if_changed,vdsold) 35 + 36 + LDFLAGS_vdso-syms.o := -r -R 37 + $(obj)/vdso-syms.o: $(obj)/vdso-dummy.o FORCE 38 + $(call if_changed,ld) 39 + 40 + # strip rule for the .so file 41 + $(obj)/%.so: OBJCOPYFLAGS := -S 42 + $(obj)/%.so: $(obj)/%.so.dbg FORCE 43 + $(call if_changed,objcopy) 44 + 45 + # actual build commands 46 + # The DSO images are built using a special linker script 47 + # Add -lgcc so rv32 gets static muldi3 and lshrdi3 definitions. 48 + # Make sure only to export the intended __vdso_xxx symbol offsets. 49 + quiet_cmd_vdsold = VDSOLD $@ 50 + cmd_vdsold = $(CC) $(KCFLAGS) -nostdlib $(SYSCFLAGS_$(@F)) \ 51 + -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp -lgcc && \ 52 + $(CROSS_COMPILE)objcopy \ 53 + $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ 54 + 55 + # install commands for the unstripped file 56 + quiet_cmd_vdso_install = INSTALL $@ 57 + cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ 58 + 59 + vdso.so: $(obj)/vdso.so.dbg 60 + @mkdir -p $(MODLIB)/vdso 61 + $(call cmd,vdso_install) 62 + 63 + vdso_install: vdso.so
+24
arch/riscv/kernel/vdso/rt_sigreturn.S
··· 1 + /* 2 + * Copyright (C) 2014 Regents of the University of California 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation, version 2. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #include <linux/linkage.h> 15 + #include <asm/unistd.h> 16 + 17 + .text 18 + ENTRY(__vdso_rt_sigreturn) 19 + .cfi_startproc 20 + .cfi_signal_frame 21 + li a7, __NR_rt_sigreturn 22 + scall 23 + .cfi_endproc 24 + ENDPROC(__vdso_rt_sigreturn)
+27
arch/riscv/kernel/vdso/vdso.S
··· 1 + /* 2 + * Copyright (C) 2014 Regents of the University of California 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation, version 2. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #include <linux/init.h> 15 + #include <linux/linkage.h> 16 + #include <asm/page.h> 17 + 18 + __PAGE_ALIGNED_DATA 19 + 20 + .globl vdso_start, vdso_end 21 + .balign PAGE_SIZE 22 + vdso_start: 23 + .incbin "arch/riscv/kernel/vdso/vdso.so" 24 + .balign PAGE_SIZE 25 + vdso_end: 26 + 27 + .previous
+77
arch/riscv/kernel/vdso/vdso.lds.S
··· 1 + /* 2 + * Copyright (C) 2012 Regents of the University of California 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License 6 + * as published by the Free Software Foundation, version 2. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + OUTPUT_ARCH(riscv) 15 + 16 + SECTIONS 17 + { 18 + . = SIZEOF_HEADERS; 19 + 20 + .hash : { *(.hash) } :text 21 + .gnu.hash : { *(.gnu.hash) } 22 + .dynsym : { *(.dynsym) } 23 + .dynstr : { *(.dynstr) } 24 + .gnu.version : { *(.gnu.version) } 25 + .gnu.version_d : { *(.gnu.version_d) } 26 + .gnu.version_r : { *(.gnu.version_r) } 27 + 28 + .note : { *(.note.*) } :text :note 29 + .dynamic : { *(.dynamic) } :text :dynamic 30 + 31 + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr 32 + .eh_frame : { KEEP (*(.eh_frame)) } :text 33 + 34 + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } 35 + 36 + /* 37 + * This linker script is used both with -r and with -shared. 38 + * For the layouts to match, we need to skip more than enough 39 + * space for the dynamic symbol table, etc. If this amount is 40 + * insufficient, ld -shared will error; simply increase it here. 41 + */ 42 + . = 0x800; 43 + .text : { *(.text .text.*) } :text 44 + 45 + .data : { 46 + *(.got.plt) *(.got) 47 + *(.data .data.* .gnu.linkonce.d.*) 48 + *(.dynbss) 49 + *(.bss .bss.* .gnu.linkonce.b.*) 50 + } 51 + } 52 + 53 + /* 54 + * We must supply the ELF program headers explicitly to get just one 55 + * PT_LOAD segment, and set the flags explicitly to make segments read-only. 56 + */ 57 + PHDRS 58 + { 59 + text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */ 60 + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ 61 + note PT_NOTE FLAGS(4); /* PF_R */ 62 + eh_frame_hdr PT_GNU_EH_FRAME; 63 + } 64 + 65 + /* 66 + * This controls what symbols we export from the DSO. 67 + */ 68 + VERSION 69 + { 70 + LINUX_4.15 { 71 + global: 72 + __vdso_rt_sigreturn; 73 + __vdso_cmpxchg32; 74 + __vdso_cmpxchg64; 75 + local: *; 76 + }; 77 + }