diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/crypto/Makefile | 2 | ||||
-rw-r--r-- | arch/sparc/crypto/crc32c_glue.c | 1 | ||||
-rw-r--r-- | arch/sparc/include/asm/Kbuild | 1 | ||||
-rw-r--r-- | arch/sparc/include/asm/asm-prototypes.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/compat.h | 59 | ||||
-rw-r--r-- | arch/sparc/include/asm/hypervisor.h | 138 | ||||
-rw-r--r-- | arch/sparc/include/asm/pgtable_64.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/thread_info_32.h | 3 | ||||
-rw-r--r-- | arch/sparc/include/asm/thread_info_64.h | 3 | ||||
-rw-r--r-- | arch/sparc/include/uapi/asm/oradax.h | 91 | ||||
-rw-r--r-- | arch/sparc/include/uapi/asm/poll.h | 28 | ||||
-rw-r--r-- | arch/sparc/kernel/hvapi.c | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/hvcalls.S | 57 | ||||
-rw-r--r-- | arch/sparc/kernel/signal32.c | 69 | ||||
-rw-r--r-- | arch/sparc/kernel/signal_64.c | 3 | ||||
-rw-r--r-- | arch/sparc/mm/tlb.c | 23 | ||||
-rw-r--r-- | arch/sparc/net/bpf_jit_comp_32.c | 2 | ||||
-rw-r--r-- | arch/sparc/net/bpf_jit_comp_64.c | 66 | ||||
-rw-r--r-- | arch/sparc/vdso/vma.c | 2 |
19 files changed, 375 insertions, 178 deletions
diff --git a/arch/sparc/crypto/Makefile b/arch/sparc/crypto/Makefile index 818d3aa5172e..d257186c27d1 100644 --- a/arch/sparc/crypto/Makefile +++ b/arch/sparc/crypto/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_CRYPTO_MD5_SPARC64) += md5-sparc64.o obj-$(CONFIG_CRYPTO_AES_SPARC64) += aes-sparc64.o obj-$(CONFIG_CRYPTO_DES_SPARC64) += des-sparc64.o -obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o +obj-$(CONFIG_CRYPTO_CAMELLIA_SPARC64) += camellia-sparc64.o obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c index d1064e46efe8..8aa664638c3c 100644 --- a/arch/sparc/crypto/crc32c_glue.c +++ b/arch/sparc/crypto/crc32c_glue.c @@ -133,6 +133,7 @@ static struct shash_alg alg = { .cra_name = "crc32c", .cra_driver_name = "crc32c-sparc64", .cra_priority = SPARC_CR_OPCODE_PRIORITY, + .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, .cra_blocksize = CHKSUM_BLOCK_SIZE, .cra_ctxsize = sizeof(u32), .cra_alignmask = 7, diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 80ddc01f57ac..ac67828da201 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild @@ -1,7 +1,6 @@ # User exported sparc header files -generic-y += clkdev.h generic-y += div64.h generic-y += emergency-restart.h generic-y += exec.h diff --git a/arch/sparc/include/asm/asm-prototypes.h b/arch/sparc/include/asm/asm-prototypes.h index 96e0972e8dbf..4987c735ff56 100644 --- a/arch/sparc/include/asm/asm-prototypes.h +++ b/arch/sparc/include/asm/asm-prototypes.h @@ -6,7 +6,7 @@ #include <asm/xor.h> #include <asm/checksum.h> #include <asm/trap_block.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/atomic.h> #include <asm/ftrace.h> #include <asm/cacheflush.h> diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index fa38c78de0f0..615283e16f22 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -149,65 +149,6 @@ typedef u32 compat_old_sigset_t; typedef u32 compat_sigset_word; -typedef union compat_sigval { - compat_int_t sival_int; - compat_uptr_t sival_ptr; -} compat_sigval_t; - -#define SI_PAD_SIZE32 (128/sizeof(int) - 3) - -typedef struct compat_siginfo { - int si_signo; - int si_errno; - int si_code; - - union { - int _pad[SI_PAD_SIZE32]; - - /* kill() */ - struct { - compat_pid_t _pid; /* sender's pid */ - unsigned int _uid; /* sender's uid */ - } _kill; - - /* POSIX.1b timers */ - struct { - compat_timer_t _tid; /* timer id */ - int _overrun; /* overrun count */ - compat_sigval_t _sigval; /* same as below */ - int _sys_private; /* not to be passed to user */ - } _timer; - - /* POSIX.1b signals */ - struct { - compat_pid_t _pid; /* sender's pid */ - unsigned int _uid; /* sender's uid */ - compat_sigval_t _sigval; - } _rt; - - /* SIGCHLD */ - struct { - compat_pid_t _pid; /* which child */ - unsigned int _uid; /* sender's uid */ - int _status; /* exit code */ - compat_clock_t _utime; - compat_clock_t _stime; - } _sigchld; - - /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */ - struct { - u32 _addr; /* faulting insn/memory ref. */ - int _trapno; - } _sigfault; - - /* SIGPOLL */ - struct { - int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ - int _fd; - } _sigpoll; - } _sifields; -} compat_siginfo_t; - #define COMPAT_OFF_T_MAX 0x7fffffff /* diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h index 89a0c57aed59..ab9c6b027b75 100644 --- a/arch/sparc/include/asm/hypervisor.h +++ b/arch/sparc/include/asm/hypervisor.h @@ -76,6 +76,10 @@ #define HV_ETOOMANY 15 /* Too many items specified */ #define HV_ECHANNEL 16 /* Invalid LDC channel */ #define HV_EBUSY 17 /* Resource busy */ +#define HV_EUNAVAILABLE 23 /* Resource or operation not + * currently available, but may + * become available in the future + */ /* mach_exit() * TRAP: HV_FAST_TRAP @@ -941,6 +945,139 @@ unsigned long sun4v_mmu_map_perm_addr(unsigned long vaddr, */ #define HV_FAST_MEM_SYNC 0x32 +/* Coprocessor services + * + * M7 and later processors provide an on-chip coprocessor which + * accelerates database operations, and is known internally as + * DAX. + */ + +/* ccb_submit() + * TRAP: HV_FAST_TRAP + * FUNCTION: HV_CCB_SUBMIT + * ARG0: address of CCB array + * ARG1: size (in bytes) of CCB array being submitted + * ARG2: flags + * ARG3: reserved + * RET0: status (success or error code) + * RET1: size (in bytes) of CCB array that was accepted (might be less + * than arg1) + * RET2: status data + * if status == ENOMAP or ENOACCESS, identifies the VA in question + * if status == EUNAVAILBLE, unavailable code + * RET3: reserved + * + * ERRORS: EOK successful submission (check size) + * EWOULDBLOCK could not finish submissions, try again + * EBADALIGN array not 64B aligned or size not 64B multiple + * ENORADDR invalid RA for array or in CCB + * ENOMAP could not translate address (see status data) + * EINVAL invalid ccb or arguments + * ETOOMANY too many ccbs with all-or-nothing flag + * ENOACCESS guest has no access to submit ccbs or address + * in CCB does not have correct permissions (check + * status data) + * EUNAVAILABLE ccb operation could not be performed at this + * time (check status data) + * Status data codes: + * 0 - exact CCB could not be executed + * 1 - CCB opcode cannot be executed + * 2 - CCB version cannot be executed + * 3 - vcpu cannot execute CCBs + * 4 - no CCBs can be executed + */ + +#define HV_CCB_SUBMIT 0x34 +#ifndef __ASSEMBLY__ +unsigned long sun4v_ccb_submit(unsigned long ccb_buf, + unsigned long len, + unsigned long flags, + unsigned long reserved, + void *submitted_len, + void *status_data); +#endif + +/* flags (ARG2) */ +#define HV_CCB_QUERY_CMD BIT(1) +#define HV_CCB_ARG0_TYPE_REAL 0UL +#define HV_CCB_ARG0_TYPE_PRIMARY BIT(4) +#define HV_CCB_ARG0_TYPE_SECONDARY BIT(5) +#define HV_CCB_ARG0_TYPE_NUCLEUS GENMASK(5, 4) +#define HV_CCB_ARG0_PRIVILEGED BIT(6) +#define HV_CCB_ALL_OR_NOTHING BIT(7) +#define HV_CCB_QUEUE_INFO BIT(8) +#define HV_CCB_VA_REJECT 0UL +#define HV_CCB_VA_SECONDARY BIT(13) +#define HV_CCB_VA_NUCLEUS GENMASK(13, 12) +#define HV_CCB_VA_PRIVILEGED BIT(14) +#define HV_CCB_VA_READ_ADI_DISABLE BIT(15) /* DAX2 only */ + +/* ccb_info() + * TRAP: HV_FAST_TRAP + * FUNCTION: HV_CCB_INFO + * ARG0: real address of CCB completion area + * RET0: status (success or error code) + * RET1: info array + * - RET1[0]: CCB state + * - RET1[1]: dax unit + * - RET1[2]: queue number + * - RET1[3]: queue position + * + * ERRORS: EOK operation successful + * EBADALIGN address not 64B aligned + * ENORADDR RA in address not valid + * EINVAL CA not valid + * EWOULDBLOCK info not available for this CCB currently, try + * again + * ENOACCESS guest cannot use dax + */ + +#define HV_CCB_INFO 0x35 +#ifndef __ASSEMBLY__ +unsigned long sun4v_ccb_info(unsigned long ca, + void *info_arr); +#endif + +/* info array byte offsets (RET1) */ +#define CCB_INFO_OFFSET_CCB_STATE 0 +#define CCB_INFO_OFFSET_DAX_UNIT 2 +#define CCB_INFO_OFFSET_QUEUE_NUM 4 +#define CCB_INFO_OFFSET_QUEUE_POS 6 + +/* CCB state (RET1[0]) */ +#define HV_CCB_STATE_COMPLETED 0 +#define HV_CCB_STATE_ENQUEUED 1 +#define HV_CCB_STATE_INPROGRESS 2 +#define HV_CCB_STATE_NOTFOUND 3 + +/* ccb_kill() + * TRAP: HV_FAST_TRAP + * FUNCTION: HV_CCB_KILL + * ARG0: real address of CCB completion area + * RET0: status (success or error code) + * RET1: CCB kill status + * + * ERRORS: EOK operation successful + * EBADALIGN address not 64B aligned + * ENORADDR RA in address not valid + * EINVAL CA not valid + * EWOULDBLOCK kill not available for this CCB currently, try + * again + * ENOACCESS guest cannot use dax + */ + +#define HV_CCB_KILL 0x36 +#ifndef __ASSEMBLY__ +unsigned long sun4v_ccb_kill(unsigned long ca, + void *kill_status); +#endif + +/* CCB kill status (RET1) */ +#define HV_CCB_KILL_COMPLETED 0 +#define HV_CCB_KILL_DEQUEUED 1 +#define HV_CCB_KILL_KILLED 2 +#define HV_CCB_KILL_NOTFOUND 3 + /* Time of day services. * * The hypervisor maintains the time of day on a per-domain basis. @@ -3355,6 +3492,7 @@ unsigned long sun4v_m7_set_perfreg(unsigned long reg_num, #define HV_GRP_SDIO_ERR 0x0109 #define HV_GRP_REBOOT_DATA 0x0110 #define HV_GRP_ATU 0x0111 +#define HV_GRP_DAX 0x0113 #define HV_GRP_M7_PERF 0x0114 #define HV_GRP_NIAG_PERF 0x0200 #define HV_GRP_FIRE_PERF 0x0201 diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 9937c5ff94a9..339920fdf9ed 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -1010,7 +1010,7 @@ void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmd); #define __HAVE_ARCH_PMDP_INVALIDATE -extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, +extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp); #define __HAVE_ARCH_PGTABLE_DEPOSIT diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h index febaaeb1a0fe..548b366165dd 100644 --- a/arch/sparc/include/asm/thread_info_32.h +++ b/arch/sparc/include/asm/thread_info_32.h @@ -63,9 +63,6 @@ struct thread_info { .preempt_count = INIT_PREEMPT_COUNT, \ } -#define init_thread_info (init_thread_union.thread_info) -#define init_stack (init_thread_union.stack) - /* how to get the thread information struct from C */ register struct thread_info *current_thread_info_reg asm("g6"); #define current_thread_info() (current_thread_info_reg) diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index caf915321ba9..f7e7b0baec9f 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -120,9 +120,6 @@ struct thread_info { .preempt_count = INIT_PREEMPT_COUNT, \ } -#define init_thread_info (init_thread_union.thread_info) -#define init_stack (init_thread_union.stack) - /* how to get the thread information struct from C */ register struct thread_info *current_thread_info_reg asm("g6"); #define current_thread_info() (current_thread_info_reg) diff --git a/arch/sparc/include/uapi/asm/oradax.h b/arch/sparc/include/uapi/asm/oradax.h new file mode 100644 index 000000000000..722951908b0a --- /dev/null +++ b/arch/sparc/include/uapi/asm/oradax.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * + * 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 3 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 <http://www.gnu.org/licenses/>. + */ + +/* + * Oracle DAX driver API definitions + */ + +#ifndef _ORADAX_H +#define _ORADAX_H + +#include <linux/types.h> + +#define CCB_KILL 0 +#define CCB_INFO 1 +#define CCB_DEQUEUE 2 + +struct dax_command { + __u16 command; /* CCB_KILL/INFO/DEQUEUE */ + __u16 ca_offset; /* offset into mmapped completion area */ +}; + +struct ccb_kill_result { + __u16 action; /* action taken to kill ccb */ +}; + +struct ccb_info_result { + __u16 state; /* state of enqueued ccb */ + __u16 inst_num; /* dax instance number of enqueued ccb */ + __u16 q_num; /* queue number of enqueued ccb */ + __u16 q_pos; /* ccb position in queue */ +}; + +struct ccb_exec_result { + __u64 status_data; /* additional status data (e.g. bad VA) */ + __u32 status; /* one of DAX_SUBMIT_* */ +}; + +union ccb_result { + struct ccb_exec_result exec; + struct ccb_info_result info; + struct ccb_kill_result kill; +}; + +#define DAX_MMAP_LEN (16 * 1024) +#define DAX_MAX_CCBS 15 +#define DAX_CCB_BUF_MAXLEN (DAX_MAX_CCBS * 64) +#define DAX_NAME "oradax" + +/* CCB_EXEC status */ +#define DAX_SUBMIT_OK 0 +#define DAX_SUBMIT_ERR_RETRY 1 +#define DAX_SUBMIT_ERR_WOULDBLOCK 2 +#define DAX_SUBMIT_ERR_BUSY 3 +#define DAX_SUBMIT_ERR_THR_INIT 4 +#define DAX_SUBMIT_ERR_ARG_INVAL 5 +#define DAX_SUBMIT_ERR_CCB_INVAL 6 +#define DAX_SUBMIT_ERR_NO_CA_AVAIL 7 +#define DAX_SUBMIT_ERR_CCB_ARR_MMU_MISS 8 +#define DAX_SUBMIT_ERR_NOMAP 9 +#define DAX_SUBMIT_ERR_NOACCESS 10 +#define DAX_SUBMIT_ERR_TOOMANY 11 +#define DAX_SUBMIT_ERR_UNAVAIL 12 +#define DAX_SUBMIT_ERR_INTERNAL 13 + +/* CCB_INFO states - must match HV_CCB_STATE_* definitions */ +#define DAX_CCB_COMPLETED 0 +#define DAX_CCB_ENQUEUED 1 +#define DAX_CCB_INPROGRESS 2 +#define DAX_CCB_NOTFOUND 3 + +/* CCB_KILL actions - must match HV_CCB_KILL_* definitions */ +#define DAX_KILL_COMPLETED 0 +#define DAX_KILL_DEQUEUED 1 +#define DAX_KILL_KILLED 2 +#define DAX_KILL_NOTFOUND 3 + +#endif /* _ORADAX_H */ diff --git a/arch/sparc/include/uapi/asm/poll.h b/arch/sparc/include/uapi/asm/poll.h index 72356c999125..2a81e79aa3ea 100644 --- a/arch/sparc/include/uapi/asm/poll.h +++ b/arch/sparc/include/uapi/asm/poll.h @@ -2,11 +2,31 @@ #ifndef __SPARC_POLL_H #define __SPARC_POLL_H +#ifndef __KERNEL__ #define POLLWRNORM POLLOUT -#define POLLWRBAND 256 -#define POLLMSG 512 -#define POLLREMOVE 1024 -#define POLLRDHUP 2048 +#define POLLWRBAND (__force __poll_t)256 +#define POLLMSG (__force __poll_t)512 +#define POLLREMOVE (__force __poll_t)1024 +#define POLLRDHUP (__force __poll_t)2048 +#else +#define __ARCH_HAS_MANGLED_POLL +static inline __u16 mangle_poll(__poll_t val) +{ + __u16 v = (__force __u16)val; + /* bit 9 -> bit 8, bit 8 -> bit 2, bit 13 -> bit 11 */ + return (v & ~0x300) | ((v & 0x200) >> 1) | ((v & 0x100) >> 6) | + ((v & 0x2000) >> 2); + + +} + +static inline __poll_t demangle_poll(__u16 v) +{ + /* bit 8 -> bit 9, bit 2 -> bits 2 and 8 */ + return (__force __poll_t)((v & ~0x100) | ((v & 0x100) << 1) | + ((v & 4) << 6) | ((v & 0x800) << 2)); +} +#endif #include <asm-generic/poll.h> diff --git a/arch/sparc/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c index a2bc1b2955b4..717ec7ef07f9 100644 --- a/arch/sparc/kernel/hvapi.c +++ b/arch/sparc/kernel/hvapi.c @@ -41,6 +41,7 @@ static struct api_info api_table[] = { { .group = HV_GRP_SDIO_ERR, }, { .group = HV_GRP_REBOOT_DATA, }, { .group = HV_GRP_ATU, .flags = FLAG_PRE_API }, + { .group = HV_GRP_DAX, }, { .group = HV_GRP_NIAG_PERF, .flags = FLAG_PRE_API }, { .group = HV_GRP_FIRE_PERF, }, { .group = HV_GRP_N2_CPU, }, diff --git a/arch/sparc/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S index bdfd3d8c6707..2f865a464576 100644 --- a/arch/sparc/kernel/hvcalls.S +++ b/arch/sparc/kernel/hvcalls.S @@ -871,3 +871,60 @@ ENTRY(sun4v_m7_set_perfreg) retl nop ENDPROC(sun4v_m7_set_perfreg) + + /* %o0: address of CCB array + * %o1: size (in bytes) of CCB array + * %o2: flags + * %o3: reserved + * + * returns: + * %o0: status + * %o1: size (in bytes) of the CCB array that was accepted + * %o2: status data + * %o3: reserved + */ +ENTRY(sun4v_ccb_submit) + mov %o5, %g1 + mov HV_CCB_SUBMIT, %o5 + ta HV_FAST_TRAP + stx %o1, [%o4] + retl + stx %o2, [%g1] +ENDPROC(sun4v_ccb_submit) +EXPORT_SYMBOL(sun4v_ccb_submit) + + /* %o0: completion area ra for the ccb to get info + * + * returns: + * %o0: status + * %o1: CCB state + * %o2: position + * %o3: dax unit + * %o4: queue + */ +ENTRY(sun4v_ccb_info) + mov %o1, %g1 + mov HV_CCB_INFO, %o5 + ta HV_FAST_TRAP + sth %o1, [%g1 + CCB_INFO_OFFSET_CCB_STATE] + sth %o2, [%g1 + CCB_INFO_OFFSET_QUEUE_POS] + sth %o3, [%g1 + CCB_INFO_OFFSET_DAX_UNIT] + retl + sth %o4, [%g1 + CCB_INFO_OFFSET_QUEUE_NUM] +ENDPROC(sun4v_ccb_info) +EXPORT_SYMBOL(sun4v_ccb_info) + + /* %o0: completion area ra for the ccb to kill + * + * returns: + * %o0: status + * %o1: result of the kill + */ +ENTRY(sun4v_ccb_kill) + mov %o1, %g1 + mov HV_CCB_KILL, %o5 + ta HV_FAST_TRAP + retl + sth %o1, [%g1] +ENDPROC(sun4v_ccb_kill) +EXPORT_SYMBOL(sun4v_ccb_kill) diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 54a6159b9cd8..44d379db3f64 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -70,75 +70,6 @@ struct rt_signal_frame32 { /* __siginfo_rwin_t * */u32 rwin_save; } __attribute__((aligned(8))); -int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) -{ - int err; - - if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) - return -EFAULT; - - /* If you change siginfo_t structure, please be sure - this code is fixed accordingly. - It should never copy any pad contained in the structure - to avoid security leaks, but must copy the generic - 3 ints plus the relevant union member. - This routine must convert siginfo from 64bit to 32bit as well - at the same time. */ - err = __put_user(from->si_signo, &to->si_signo); - err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user(from->si_code, &to->si_code); - if (from->si_code < 0) - err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); - else { - switch (siginfo_layout(from->si_signo, from->si_code)) { - case SIL_TIMER: - err |= __put_user(from->si_tid, &to->si_tid); - err |= __put_user(from->si_overrun, &to->si_overrun); - err |= __put_user(from->si_int, &to->si_int); - break; - case SIL_CHLD: - err |= __put_user(from->si_utime, &to->si_utime); - err |= __put_user(from->si_stime, &to->si_stime); - err |= __put_user(from->si_status, &to->si_status); - default: - case SIL_KILL: - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - break; - case SIL_FAULT: - err |= __put_user(from->si_trapno, &to->si_trapno); - err |= __put_user((unsigned long)from->si_addr, &to->si_addr); - break; - case SIL_POLL: - err |= __put_user(from->si_band, &to->si_band); - err |= __put_user(from->si_fd, &to->si_fd); - break; - case SIL_RT: - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user(from->si_int, &to->si_int); - break; - } - } - return err; -} - -/* CAUTION: This is just a very minimalist implementation for the - * sake of compat_sys_rt_sigqueueinfo() - */ -int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) -{ - if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t))) - return -EFAULT; - - if (copy_from_user(to, from, 3*sizeof(int)) || - copy_from_user(to->_sifields._pad, from->_sifields._pad, - SI_PAD_SIZE)) - return -EFAULT; - - return 0; -} - /* Checks if the fp is valid. We always build signal frames which are * 16-byte aligned, therefore we can always enforce that the restore * frame has that property as well. diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 20426a1c28f2..48366e5eb5b2 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -9,9 +9,6 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ -#ifdef CONFIG_COMPAT -#include <linux/compat.h> /* for compat_old_sigset_t */ -#endif #include <linux/sched.h> #include <linux/kernel.h> #include <linux/signal.h> diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index 4ae86bc0d35c..847ddffbf38a 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -219,17 +219,28 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, } } +static inline pmd_t pmdp_establish(struct vm_area_struct *vma, + unsigned long address, pmd_t *pmdp, pmd_t pmd) +{ + pmd_t old; + + do { + old = *pmdp; + } while (cmpxchg64(&pmdp->pmd, old.pmd, pmd.pmd) != old.pmd); + + return old; +} + /* * This routine is only called when splitting a THP */ -void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, +pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp) { - pmd_t entry = *pmdp; - - pmd_val(entry) &= ~_PAGE_VALID; + pmd_t old, entry; - set_pmd_at(vma->vm_mm, address, pmdp, entry); + entry = __pmd(pmd_val(*pmdp) & ~_PAGE_VALID); + old = pmdp_establish(vma, address, pmdp, entry); flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); /* @@ -240,6 +251,8 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, if ((pmd_val(entry) & _PAGE_PMD_HUGE) && !is_huge_zero_page(pmd_page(entry))) (vma->vm_mm)->context.thp_pte_count--; + + return old; } void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, diff --git a/arch/sparc/net/bpf_jit_comp_32.c b/arch/sparc/net/bpf_jit_comp_32.c index 09e318eb34ee..3bd8ca95e521 100644 --- a/arch/sparc/net/bpf_jit_comp_32.c +++ b/arch/sparc/net/bpf_jit_comp_32.c @@ -11,8 +11,6 @@ #include "bpf_jit_32.h" -int bpf_jit_enable __read_mostly; - static inline bool is_simm13(unsigned int value) { return value + 0x1000 < 0x2000; diff --git a/arch/sparc/net/bpf_jit_comp_64.c b/arch/sparc/net/bpf_jit_comp_64.c index ff5f9cb3039a..48a25869349b 100644 --- a/arch/sparc/net/bpf_jit_comp_64.c +++ b/arch/sparc/net/bpf_jit_comp_64.c @@ -12,8 +12,6 @@ #include "bpf_jit_64.h" -int bpf_jit_enable __read_mostly; - static inline bool is_simm13(unsigned int value) { return value + 0x1000 < 0x2000; @@ -969,31 +967,17 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) emit_alu(MULX, src, dst, ctx); break; case BPF_ALU | BPF_DIV | BPF_X: - emit_cmp(src, G0, ctx); - emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx); - emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx); - emit_write_y(G0, ctx); emit_alu(DIV, src, dst, ctx); break; - case BPF_ALU64 | BPF_DIV | BPF_X: - emit_cmp(src, G0, ctx); - emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx); - emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx); - emit_alu(UDIVX, src, dst, ctx); break; - case BPF_ALU | BPF_MOD | BPF_X: { const u8 tmp = bpf2sparc[TMP_REG_1]; ctx->tmp_1_used = true; - emit_cmp(src, G0, ctx); - emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx); - emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx); - emit_write_y(G0, ctx); emit_alu3(DIV, dst, src, tmp, ctx); emit_alu3(MULX, tmp, src, tmp, ctx); @@ -1005,10 +989,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) ctx->tmp_1_used = true; - emit_cmp(src, G0, ctx); - emit_branch(BE|ANNUL, ctx->idx, ctx->epilogue_offset, ctx); - emit_loadimm(0, bpf2sparc[BPF_REG_0], ctx); - emit_alu3(UDIVX, dst, src, tmp, ctx); emit_alu3(MULX, tmp, src, tmp, ctx); emit_alu3(SUB, dst, tmp, dst, ctx); @@ -1509,17 +1489,25 @@ static void jit_fill_hole(void *area, unsigned int size) *ptr++ = 0x91d02005; /* ta 5 */ } +struct sparc64_jit_data { + struct bpf_binary_header *header; + u8 *image; + struct jit_ctx ctx; +}; + struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) { struct bpf_prog *tmp, *orig_prog = prog; + struct sparc64_jit_data *jit_data; struct bpf_binary_header *header; bool tmp_blinded = false; + bool extra_pass = false; struct jit_ctx ctx; u32 image_size; u8 *image_ptr; int pass; - if (!bpf_jit_enable) + if (!prog->jit_requested) return orig_prog; tmp = bpf_jit_blind_constants(prog); @@ -1533,13 +1521,31 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = tmp; } + jit_data = prog->aux->jit_data; + if (!jit_data) { + jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL); + if (!jit_data) { + prog = orig_prog; + goto out; + } + prog->aux->jit_data = jit_data; + } + if (jit_data->ctx.offset) { + ctx = jit_data->ctx; + image_ptr = jit_data->image; + header = jit_data->header; + extra_pass = true; + image_size = sizeof(u32) * ctx.idx; + goto skip_init_ctx; + } + memset(&ctx, 0, sizeof(ctx)); ctx.prog = prog; ctx.offset = kcalloc(prog->len, sizeof(unsigned int), GFP_KERNEL); if (ctx.offset == NULL) { prog = orig_prog; - goto out; + goto out_off; } /* Fake pass to detect features used, and get an accurate assessment @@ -1562,7 +1568,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) } ctx.image = (u32 *)image_ptr; - +skip_init_ctx: for (pass = 1; pass < 3; pass++) { ctx.idx = 0; @@ -1593,14 +1599,24 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) bpf_flush_icache(header, (u8 *)header + (header->pages * PAGE_SIZE)); - bpf_jit_binary_lock_ro(header); + if (!prog->is_func || extra_pass) { + bpf_jit_binary_lock_ro(header); + } else { + jit_data->ctx = ctx; + jit_data->image = image_ptr; + jit_data->header = header; + } prog->bpf_func = (void *)ctx.image; prog->jited = 1; prog->jited_len = image_size; + if (!prog->is_func || extra_pass) { out_off: - kfree(ctx.offset); + kfree(ctx.offset); + kfree(jit_data); + prog->aux->jit_data = NULL; + } out: if (tmp_blinded) bpf_jit_prog_release_other(prog, prog == orig_prog ? diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c index 0a6f50098e23..f51595f861b8 100644 --- a/arch/sparc/vdso/vma.c +++ b/arch/sparc/vdso/vma.c @@ -251,7 +251,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) else return map_vdso(&vdso_image_32_builtin, &vdso_mapping32); #else - return map_vdso(&vdso_image_64_builtin, &vdso_mapping64); + return map_vdso(&vdso_image_64_builtin, &vdso_mapping64); #endif } |