diff options
Diffstat (limited to 'arch/parisc')
39 files changed, 231 insertions, 242 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 14f655cf542e..88cfaa8af78e 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -4,13 +4,14 @@ config PARISC select ARCH_MIGHT_HAVE_PC_PARPORT select HAVE_IDE select HAVE_OPROFILE - select HAVE_FUNCTION_TRACER if 64BIT - select HAVE_FUNCTION_GRAPH_TRACER if 64BIT + select HAVE_FUNCTION_TRACER + select HAVE_FUNCTION_GRAPH_TRACER select ARCH_WANT_FRAME_POINTERS select RTC_CLASS select RTC_DRV_GENERIC select INIT_ALL_POSSIBLE select BUG + select BUILDTIME_EXTABLE_SORT select HAVE_PERF_EVENTS select GENERIC_ATOMIC64 if !64BIT select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE @@ -29,6 +30,7 @@ config PARISC select TTY # Needed for pdc_cons.c select HAVE_DEBUG_STACKOVERFLOW select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_SECCOMP_FILTER select ARCH_NO_COHERENT_DMA_MMAP help diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug index bc989e522a04..68b7cbd0810a 100644 --- a/arch/parisc/Kconfig.debug +++ b/arch/parisc/Kconfig.debug @@ -2,9 +2,13 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config TRACE_IRQFLAGS_SUPPORT + def_bool y + config DEBUG_RODATA bool "Write protect kernel read-only data structures" depends on DEBUG_KERNEL + default y help Mark the kernel read-only data as write-protected in the pagetables, in order to catch accidental (and incorrect) writes to such const diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 965a0999fc4c..75cb451b1f03 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -62,9 +62,7 @@ cflags-y += -mdisable-fpregs # Without this, "ld -r" results in .text sections that are too big # (> 0x40000) for branches to reach stubs. -ifndef CONFIG_FUNCTION_TRACER - cflags-y += -ffunction-sections -endif +cflags-y += -ffunction-sections # Use long jumps instead of long branches (needed if your linker fails to # link a too big vmlinux executable). Not enabled for building modules. diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig index 9387cc2693f6..db8f56bf3883 100644 --- a/arch/parisc/configs/712_defconfig +++ b/arch/parisc/configs/712_defconfig @@ -183,7 +183,6 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_DEBUG_RODATA=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_HMAC=y diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig index 0490199d7b15..1a4f776b49b8 100644 --- a/arch/parisc/configs/a500_defconfig +++ b/arch/parisc/configs/a500_defconfig @@ -193,7 +193,6 @@ CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_HMAC=y diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/default_defconfig index 4d8127e8428a..310b6657e4ac 100644 --- a/arch/parisc/configs/default_defconfig +++ b/arch/parisc/configs/default_defconfig @@ -211,7 +211,6 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_MD4=m diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig index 0ffb08ff5125..5b04d703a924 100644 --- a/arch/parisc/configs/generic-32bit_defconfig +++ b/arch/parisc/configs/generic-32bit_defconfig @@ -301,7 +301,6 @@ CONFIG_RCU_CPU_STALL_INFO=y CONFIG_LATENCYTOP=y CONFIG_LKDTM=m CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_HMAC=y diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h index b3069fd83468..60e6f07b7e32 100644 --- a/arch/parisc/include/asm/assembly.h +++ b/arch/parisc/include/asm/assembly.h @@ -523,7 +523,7 @@ */ #define ASM_EXCEPTIONTABLE_ENTRY(fault_addr, except_addr) \ .section __ex_table,"aw" ! \ - ASM_ULONG_INSN fault_addr, except_addr ! \ + .word (fault_addr - .), (except_addr - .) ! \ .previous diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h index 3d0e17bcc8e9..df0f52bd18b4 100644 --- a/arch/parisc/include/asm/cache.h +++ b/arch/parisc/include/asm/cache.h @@ -22,6 +22,9 @@ #define __read_mostly __attribute__((__section__(".data..read_mostly"))) +/* Read-only memory is marked before mark_rodata_ro() is called. */ +#define __ro_after_init __read_mostly + void parisc_cache_init(void); /* initializes cache-flushing */ void disable_sr_hashing_asm(int); /* low level support for above */ void disable_sr_hashing(void); /* turns off space register hashing */ diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index 845272ce9cc5..7bd69bd43a01 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h @@ -121,10 +121,6 @@ flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vma } } -#ifdef CONFIG_DEBUG_RODATA -void mark_rodata_ro(void); -#endif - #include <asm/kmap_types.h> #define ARCH_HAS_KMAP diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h index c84b2fcb18a9..60c2c42619c9 100644 --- a/arch/parisc/include/asm/checksum.h +++ b/arch/parisc/include/asm/checksum.h @@ -85,9 +85,8 @@ static inline __sum16 csum_fold(__wsum csum) } static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) + __u32 len, __u8 proto, + __wsum sum) { __asm__( " add %1, %0, %0\n" @@ -104,9 +103,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, * returns a 16-bit checksum, already complemented */ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) + __u32 len, __u8 proto, + __wsum sum) { return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); } @@ -124,7 +122,7 @@ static inline __sum16 ip_compute_csum(const void *buf, int len) #define _HAVE_ARCH_IPV6_CSUM static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, - __u32 len, unsigned short proto, + __u32 len, __u8 proto, __wsum sum) { __asm__ __volatile__ ( diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index 0448a2c8eafb..3387307cc33e 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h @@ -183,6 +183,13 @@ typedef struct compat_siginfo { int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ int _fd; } _sigpoll; + + /* SIGSYS */ + struct { + compat_uptr_t _call_addr; /* calling user insn */ + int _syscall; /* triggering system call number */ + compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */ + } _sigsys; } _sifields; } compat_siginfo_t; diff --git a/arch/parisc/include/asm/floppy.h b/arch/parisc/include/asm/floppy.h index f84ff12574b7..6d8276cd25ca 100644 --- a/arch/parisc/include/asm/floppy.h +++ b/arch/parisc/include/asm/floppy.h @@ -33,7 +33,7 @@ * floppy accesses go through the track buffer. */ #define _CROSS_64KB(a,s,vdma) \ -(!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) +(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64)) #define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1) diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h index 544ed8ef87eb..24cd81d58d70 100644 --- a/arch/parisc/include/asm/ftrace.h +++ b/arch/parisc/include/asm/ftrace.h @@ -4,23 +4,7 @@ #ifndef __ASSEMBLY__ extern void mcount(void); -/* - * Stack of return addresses for functions of a thread. - * Used in struct thread_info - */ -struct ftrace_ret_stack { - unsigned long ret; - unsigned long func; - unsigned long long calltime; -}; - -/* - * Primary handler of a function return. - * It relays on ftrace_return_to_handler. - * Defined in entry.S - */ -extern void return_to_handler(void); - +#define MCOUNT_INSN_SIZE 4 extern unsigned long return_address(unsigned int); diff --git a/arch/parisc/include/asm/pci.h b/arch/parisc/include/asm/pci.h index 89c53bfff055..defebd956585 100644 --- a/arch/parisc/include/asm/pci.h +++ b/arch/parisc/include/asm/pci.h @@ -194,9 +194,6 @@ extern void pcibios_init_bridge(struct pci_dev *); #define PCIBIOS_MIN_IO 0x10 #define PCIBIOS_MIN_MEM 0x1000 /* NBPG - but pci/setup-res.c dies */ -/* export the pci_ DMA API in terms of the dma_ one */ -#include <asm-generic/pci-dma-compat.h> - static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) { return channel ? 15 : 14; diff --git a/arch/parisc/include/asm/syscall.h b/arch/parisc/include/asm/syscall.h index a5eba95d87fe..637ce8d6f375 100644 --- a/arch/parisc/include/asm/syscall.h +++ b/arch/parisc/include/asm/syscall.h @@ -39,6 +39,19 @@ static inline void syscall_get_arguments(struct task_struct *tsk, } } +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + regs->gr[28] = error ? error : val; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + /* do nothing */ +} + static inline int syscall_get_arch(void) { int arch = AUDIT_ARCH_PARISC; diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 0abdd4c607ed..7955e43f3f3f 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -44,30 +44,29 @@ static inline long access_ok(int type, const void __user * addr, #define LDD_USER(ptr) BUILD_BUG() #define STD_KERNEL(x, ptr) __put_kernel_asm64(x, ptr) #define STD_USER(x, ptr) __put_user_asm64(x, ptr) -#define ASM_WORD_INSN ".word\t" #else #define LDD_KERNEL(ptr) __get_kernel_asm("ldd", ptr) #define LDD_USER(ptr) __get_user_asm("ldd", ptr) #define STD_KERNEL(x, ptr) __put_kernel_asm("std", x, ptr) #define STD_USER(x, ptr) __put_user_asm("std", x, ptr) -#define ASM_WORD_INSN ".dword\t" #endif /* - * The exception table contains two values: the first is an address - * for an instruction that is allowed to fault, and the second is - * the address to the fixup routine. Even on a 64bit kernel we could - * use a 32bit (unsigned int) address here. + * The exception table contains two values: the first is the relative offset to + * the address of the instruction that is allowed to fault, and the second is + * the relative offset to the address of the fixup routine. Since relative + * addresses are used, 32bit values are sufficient even on 64bit kernel. */ +#define ARCH_HAS_RELATIVE_EXTABLE struct exception_table_entry { - unsigned long insn; /* address of insn that is allowed to fault. */ - unsigned long fixup; /* fixup routine */ + int insn; /* relative address of insn that is allowed to fault. */ + int fixup; /* relative address of fixup routine */ }; #define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\ ".section __ex_table,\"aw\"\n" \ - ASM_WORD_INSN #fault_addr ", " #except_addr "\n\t" \ + ".word (" #fault_addr " - .), (" #except_addr " - .)\n\t" \ ".previous\n" /* @@ -76,6 +75,7 @@ struct exception_table_entry { */ struct exception_data { unsigned long fault_ip; + unsigned long fault_gp; unsigned long fault_space; unsigned long fault_addr; }; diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index f9cf1223422c..9c935d717df9 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -87,4 +87,6 @@ #define SO_ATTACH_REUSEPORT_CBPF 0x402C #define SO_ATTACH_REUSEPORT_EBPF 0x402D +#define SO_CNX_ADVICE 0x402E + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h index 35bdccbb2036..cc0ce92c93c7 100644 --- a/arch/parisc/include/uapi/asm/unistd.h +++ b/arch/parisc/include/uapi/asm/unistd.h @@ -235,8 +235,8 @@ #define __NR_io_getevents (__NR_Linux + 217) #define __NR_io_submit (__NR_Linux + 218) #define __NR_io_cancel (__NR_Linux + 219) -#define __NR_alloc_hugepages (__NR_Linux + 220) -#define __NR_free_hugepages (__NR_Linux + 221) +#define __NR_alloc_hugepages (__NR_Linux + 220) /* not used */ +#define __NR_free_hugepages (__NR_Linux + 221) /* not used */ #define __NR_exit_group (__NR_Linux + 222) #define __NR_lookup_dcookie (__NR_Linux + 223) #define __NR_epoll_create (__NR_Linux + 224) @@ -361,8 +361,11 @@ #define __NR_membarrier (__NR_Linux + 343) #define __NR_userfaultfd (__NR_Linux + 344) #define __NR_mlock2 (__NR_Linux + 345) +#define __NR_copy_file_range (__NR_Linux + 346) +#define __NR_preadv2 (__NR_Linux + 347) +#define __NR_pwritev2 (__NR_Linux + 348) -#define __NR_Linux_syscalls (__NR_mlock2 + 1) +#define __NR_Linux_syscalls (__NR_pwritev2 + 1) #define __IGNORE_select /* newselect */ diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index ff87b4603e3d..69a11183d48d 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -15,11 +15,7 @@ ifdef CONFIG_FUNCTION_TRACER # Do not profile debug and lowlevel utilities CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_cache.o = -pg -CFLAGS_REMOVE_irq.o = -pg -CFLAGS_REMOVE_pacache.o = -pg CFLAGS_REMOVE_perf.o = -pg -CFLAGS_REMOVE_traps.o = -pg -CFLAGS_REMOVE_unaligned.o = -pg CFLAGS_REMOVE_unwind.o = -pg endif diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c index d2f62570a7b1..78d30d2ea2d8 100644 --- a/arch/parisc/kernel/asm-offsets.c +++ b/arch/parisc/kernel/asm-offsets.c @@ -299,6 +299,7 @@ int main(void) #endif BLANK(); DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); + DEFINE(EXCDATA_GP, offsetof(struct exception_data, fault_gp)); DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr)); BLANK(); diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 91c2a39cd5aa..67001277256c 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -319,7 +319,7 @@ void flush_dcache_page(struct page *page) if (!mapping) return; - pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); + pgoff = page->index; /* We have carefully arranged in arch_get_unmapped_area() that * *any* mappings of a file are always congruently mapped (whether diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 623496c11756..39127d3e70e5 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -1970,43 +1970,98 @@ pt_regs_ok: b intr_restore copy %r25,%r16 - .import schedule,code syscall_do_resched: - BL schedule,%r2 + load32 syscall_check_resched,%r2 /* if resched, we start over again */ + load32 schedule,%r19 + bv %r0(%r19) /* jumps to schedule() */ #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #else nop #endif - b syscall_check_resched /* if resched, we start over again */ - nop ENDPROC(syscall_exit) #ifdef CONFIG_FUNCTION_TRACER + .import ftrace_function_trampoline,code -ENTRY(_mcount) - copy %r3, %arg2 + .align L1_CACHE_BYTES + .globl mcount + .type mcount, @function +ENTRY(mcount) +_mcount: + .export _mcount,data + .proc + .callinfo caller,frame=0 + .entry + /* + * The 64bit mcount() function pointer needs 4 dwords, of which the + * first two are free. We optimize it here and put 2 instructions for + * calling mcount(), and 2 instructions for ftrace_stub(). That way we + * have all on one L1 cacheline. + */ b ftrace_function_trampoline + copy %r3, %arg2 /* caller original %sp */ +ftrace_stub: + .globl ftrace_stub + .type ftrace_stub, @function +#ifdef CONFIG_64BIT + bve (%rp) +#else + bv %r0(%rp) +#endif nop -ENDPROC(_mcount) +#ifdef CONFIG_64BIT + .dword mcount + .dword 0 /* code in head.S puts value of global gp here */ +#endif + .exit + .procend +ENDPROC(mcount) + .align 8 + .globl return_to_handler + .type return_to_handler, @function ENTRY(return_to_handler) - load32 return_trampoline, %rp - copy %ret0, %arg0 - copy %ret1, %arg1 - b ftrace_return_to_handler - nop -return_trampoline: - copy %ret0, %rp - copy %r23, %ret0 - copy %r24, %ret1 + .proc + .callinfo caller,frame=FRAME_SIZE + .entry + .export parisc_return_to_handler,data +parisc_return_to_handler: + copy %r3,%r1 + STREG %r0,-RP_OFFSET(%sp) /* store 0 as %rp */ + copy %sp,%r3 + STREGM %r1,FRAME_SIZE(%sp) + STREG %ret0,8(%r3) + STREG %ret1,16(%r3) -.globl ftrace_stub -ftrace_stub: +#ifdef CONFIG_64BIT + loadgp +#endif + + /* call ftrace_return_to_handler(0) */ +#ifdef CONFIG_64BIT + ldo -16(%sp),%ret1 /* Reference param save area */ +#endif + BL ftrace_return_to_handler,%r2 + ldi 0,%r26 + copy %ret0,%rp + + /* restore original return values */ + LDREG 8(%r3),%ret0 + LDREG 16(%r3),%ret1 + + /* return from function */ +#ifdef CONFIG_64BIT + bve (%rp) +#else bv %r0(%rp) - nop +#endif + LDREGM -FRAME_SIZE(%sp),%r3 + .exit + .procend ENDPROC(return_to_handler) + #endif /* CONFIG_FUNCTION_TRACER */ #ifdef CONFIG_IRQSTACKS diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c index 559d400f9385..b13f9ec6f294 100644 --- a/arch/parisc/kernel/ftrace.c +++ b/arch/parisc/kernel/ftrace.c @@ -1,6 +1,6 @@ /* * Code for tracing calls in Linux kernel. - * Copyright (C) 2009 Helge Deller <deller@gmx.de> + * Copyright (C) 2009-2016 Helge Deller <deller@gmx.de> * * based on code for x86 which is: * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> @@ -13,104 +13,21 @@ #include <linux/init.h> #include <linux/ftrace.h> +#include <asm/assembly.h> #include <asm/sections.h> #include <asm/ftrace.h> - #ifdef CONFIG_FUNCTION_GRAPH_TRACER - -/* Add a function return address to the trace stack on thread info.*/ -static int push_return_trace(unsigned long ret, unsigned long long time, - unsigned long func, int *depth) -{ - int index; - - if (!current->ret_stack) - return -EBUSY; - - /* The return trace stack is full */ - if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) { - atomic_inc(¤t->trace_overrun); - return -EBUSY; - } - - index = ++current->curr_ret_stack; - barrier(); - current->ret_stack[index].ret = ret; - current->ret_stack[index].func = func; - current->ret_stack[index].calltime = time; - *depth = index; - - return 0; -} - -/* Retrieve a function return address to the trace stack on thread info.*/ -static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret) -{ - int index; - - index = current->curr_ret_stack; - - if (unlikely(index < 0)) { - ftrace_graph_stop(); - WARN_ON(1); - /* Might as well panic, otherwise we have no where to go */ - *ret = (unsigned long) - dereference_function_descriptor(&panic); - return; - } - - *ret = current->ret_stack[index].ret; - trace->func = current->ret_stack[index].func; - trace->calltime = current->ret_stack[index].calltime; - trace->overrun = atomic_read(¤t->trace_overrun); - trace->depth = index; - barrier(); - current->curr_ret_stack--; - -} - -/* - * Send the trace to the ring-buffer. - * @return the original return address. - */ -unsigned long ftrace_return_to_handler(unsigned long retval0, - unsigned long retval1) -{ - struct ftrace_graph_ret trace; - unsigned long ret; - - pop_return_trace(&trace, &ret); - trace.rettime = local_clock(); - ftrace_graph_return(&trace); - - if (unlikely(!ret)) { - ftrace_graph_stop(); - WARN_ON(1); - /* Might as well panic. What else to do? */ - ret = (unsigned long) - dereference_function_descriptor(&panic); - } - - /* HACK: we hand over the old functions' return values - in %r23 and %r24. Assembly in entry.S will take care - and move those to their final registers %ret0 and %ret1 */ - asm( "copy %0, %%r23 \n\t" - "copy %1, %%r24 \n" : : "r" (retval0), "r" (retval1) ); - - return ret; -} - /* * Hook the return address and push it in the stack of return addrs * in current thread info. */ -void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) +static void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) { unsigned long old; - unsigned long long calltime; struct ftrace_graph_ent trace; + extern int parisc_return_to_handler; if (unlikely(ftrace_graph_is_dead())) return; @@ -119,64 +36,47 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) return; old = *parent; - *parent = (unsigned long) - dereference_function_descriptor(&return_to_handler); - if (unlikely(!__kernel_text_address(old))) { - ftrace_graph_stop(); - *parent = old; - WARN_ON(1); - return; - } - - calltime = local_clock(); + trace.func = self_addr; + trace.depth = current->curr_ret_stack + 1; - if (push_return_trace(old, calltime, - self_addr, &trace.depth) == -EBUSY) { - *parent = old; + /* Only trace if the calling function expects to */ + if (!ftrace_graph_entry(&trace)) return; - } - trace.func = self_addr; + if (ftrace_push_return_trace(old, self_addr, &trace.depth, + 0 ) == -EBUSY) + return; - /* Only trace if the calling function expects to */ - if (!ftrace_graph_entry(&trace)) { - current->curr_ret_stack--; - *parent = old; - } + /* activate parisc_return_to_handler() as return point */ + *parent = (unsigned long) &parisc_return_to_handler; } - #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ - -void ftrace_function_trampoline(unsigned long parent, +void notrace ftrace_function_trampoline(unsigned long parent, unsigned long self_addr, unsigned long org_sp_gr3) { - extern ftrace_func_t ftrace_trace_function; + extern ftrace_func_t ftrace_trace_function; /* depends on CONFIG_DYNAMIC_FTRACE */ + extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace); if (ftrace_trace_function != ftrace_stub) { - ftrace_trace_function(parent, self_addr); + /* struct ftrace_ops *op, struct pt_regs *regs); */ + ftrace_trace_function(parent, self_addr, NULL, NULL); return; } + #ifdef CONFIG_FUNCTION_GRAPH_TRACER - if (ftrace_graph_entry && ftrace_graph_return) { - unsigned long sp; + if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub || + ftrace_graph_entry != ftrace_graph_entry_stub) { unsigned long *parent_rp; - asm volatile ("copy %%r30, %0" : "=r"(sp)); - /* sanity check: is stack pointer which we got from - assembler function in entry.S in a reasonable - range compared to current stack pointer? */ - if ((sp - org_sp_gr3) > 0x400) - return; - /* calculate pointer to %rp in stack */ - parent_rp = (unsigned long *) org_sp_gr3 - 0x10; + parent_rp = (unsigned long *) (org_sp_gr3 - RP_OFFSET); /* sanity check: parent_rp should hold parent */ if (*parent_rp != parent) return; - + prepare_ftrace_return(parent_rp, self_addr); return; } diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index 75aa0db9f69e..bbbe360b458f 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S @@ -129,6 +129,15 @@ $pgt_fill_loop: /* And the stack pointer too */ ldo THREAD_SZ_ALGN(%r6),%sp +#if defined(CONFIG_64BIT) && defined(CONFIG_FUNCTION_TRACER) + .import _mcount,data + /* initialize mcount FPTR */ + /* Get the global data pointer */ + loadgp + load32 PA(_mcount), %r10 + std %dp,0x18(%r10) +#endif + #ifdef CONFIG_SMP /* Set the smp rendezvous address into page zero. ** It would be safer to do this in init_smp_config() but diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index b9d75d9fa9ac..a0ecdb4abcc8 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -660,6 +660,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, } *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); break; + case R_PARISC_PCREL32: + /* 32-bit PC relative address */ + *loc = val - dot - 8 + addend; + break; default: printk(KERN_ERR "module %s: Unknown relocation: %u\n", @@ -788,6 +792,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, CHECK_RELOC(val, 22); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); break; + case R_PARISC_PCREL32: + /* 32-bit PC relative address */ + *loc = val - dot - 8 + addend; + break; case R_PARISC_DIR64: /* 64-bit effective address */ *loc64 = val + addend; diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 568b2c61ea02..3cad8aadc69e 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -47,11 +47,11 @@ EXPORT_SYMBOL(__cmpxchg_u64); EXPORT_SYMBOL(lclear_user); EXPORT_SYMBOL(lstrnlen_user); -/* Global fixups */ -extern void fixup_get_user_skip_1(void); -extern void fixup_get_user_skip_2(void); -extern void fixup_put_user_skip_1(void); -extern void fixup_put_user_skip_2(void); +/* Global fixups - defined as int to avoid creation of function pointers */ +extern int fixup_get_user_skip_1; +extern int fixup_get_user_skip_2; +extern int fixup_put_user_skip_1; +extern int fixup_put_user_skip_2; EXPORT_SYMBOL(fixup_get_user_skip_1); EXPORT_SYMBOL(fixup_get_user_skip_2); EXPORT_SYMBOL(fixup_put_user_skip_1); diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 9585c81f755f..8fb81a391599 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -269,14 +269,20 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, long do_syscall_trace_enter(struct pt_regs *regs) { - long ret = 0; - /* Do the secure computing check first. */ - secure_computing_strict(regs->gr[20]); + if (secure_computing() == -1) + return -1; if (test_thread_flag(TIF_SYSCALL_TRACE) && - tracehook_report_syscall_entry(regs)) - ret = -1L; + tracehook_report_syscall_entry(regs)) { + /* + * Tracing decided this syscall should not happen or the + * debugger stored an invalid system call number. Skip + * the system call and the system call restart handling. + */ + regs->gr[20] = -1UL; + goto out; + } #ifdef CONFIG_64BIT if (!is_compat_task()) @@ -290,7 +296,12 @@ long do_syscall_trace_enter(struct pt_regs *regs) regs->gr[24] & 0xffffffff, regs->gr[23] & 0xffffffff); - return ret ? : regs->gr[20]; +out: + /* + * Sign extend the syscall number to 64bit since it may have been + * modified by a compat ptrace call + */ + return (int) ((u32) regs->gr[20]); } void do_syscall_trace_exit(struct pt_regs *regs) diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index 984abbee71ca..c342b2e17492 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -371,6 +371,11 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from) val = (compat_int_t)from->si_int; err |= __put_user(val, &to->si_int); break; + case __SI_SYS >> 16: + err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr); + err |= __put_user(from->si_syscall, &to->si_syscall); + err |= __put_user(from->si_arch, &to->si_arch); + break; } } return err; diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 52e85973a283..c2a9cc55a62f 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -305,7 +305,7 @@ void __init smp_callin(void) local_irq_enable(); /* Interrupts have been off until now */ - cpu_startup_entry(CPUHP_ONLINE); + cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); /* NOTREACHED */ panic("smp_callin() AAAAaaaaahhhh....\n"); diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 5aba01ac457f..0a393a04e891 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -368,16 +368,6 @@ asmlinkage long parisc_fallocate(int fd, int mode, u32 offhi, u32 offlo, ((u64)lenhi << 32) | lenlo); } -asmlinkage unsigned long sys_alloc_hugepages(int key, unsigned long addr, unsigned long len, int prot, int flag) -{ - return -ENOMEM; -} - -asmlinkage int sys_free_hugepages(unsigned long addr) -{ - return -EINVAL; -} - long parisc_personality(unsigned long personality) { long err; diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 3fbd7252a4b2..c976ebfe2269 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -329,6 +329,7 @@ tracesys_next: ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ LDREG TI_TASK(%r1), %r1 + LDREG TASK_PT_GR28(%r1), %r28 /* Restore return value */ LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */ LDREG TASK_PT_GR25(%r1), %r25 LDREG TASK_PT_GR24(%r1), %r24 @@ -342,8 +343,9 @@ tracesys_next: stw %r21, -56(%r30) /* 6th argument */ #endif + cmpib,COND(=),n -1,%r20,tracesys_exit /* seccomp may have returned -1 */ comiclr,>>= __NR_Linux_syscalls, %r20, %r0 - b,n .Lsyscall_nosys + b,n .Ltracesys_nosys LDREGX %r20(%r19), %r19 @@ -359,6 +361,9 @@ tracesys_next: be 0(%sr7,%r19) ldo R%tracesys_exit(%r2),%r2 +.Ltracesys_nosys: + ldo -ENOSYS(%r0),%r28 /* set errno */ + /* Do *not* call this function on the gateway page, because it makes a direct call to syscall_trace. */ diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index d4ffcfbc9885..3cfef1de8061 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -315,8 +315,8 @@ ENTRY_COMP(io_getevents) ENTRY_COMP(io_submit) ENTRY_SAME(io_cancel) - ENTRY_SAME(alloc_hugepages) /* 220 */ - ENTRY_SAME(free_hugepages) + ENTRY_SAME(ni_syscall) /* 220: was alloc_hugepages */ + ENTRY_SAME(ni_syscall) /* was free_hugepages */ ENTRY_SAME(exit_group) ENTRY_COMP(lookup_dcookie) ENTRY_SAME(epoll_create) @@ -441,6 +441,9 @@ ENTRY_SAME(membarrier) ENTRY_SAME(userfaultfd) ENTRY_SAME(mlock2) /* 345 */ + ENTRY_SAME(copy_file_range) + ENTRY_COMP(preadv2) + ENTRY_COMP(pwritev2) .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b)) diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 553b09855cfd..97d6b208e129 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -284,11 +284,8 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) if (in_interrupt()) panic("Fatal exception in interrupt"); - if (panic_on_oops) { - printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); - ssleep(5); + if (panic_on_oops) panic("Fatal exception"); - } oops_exit(); do_exit(SIGSEGV); @@ -798,6 +795,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs) if (fault_space == 0 && !faulthandler_disabled()) { + /* Clean up and return if in exception table. */ + if (fixup_exception(regs)) + return; pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); parisc_terminate("Kernel Fault", regs, code, fault_address); } diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 308f29081d46..f3ead0b6ce46 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -72,6 +72,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.text.do_softirq) *(.text.sys_exit) *(.text.do_sigaltstack) diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S index 536ef66bb94b..1052b747e011 100644 --- a/arch/parisc/lib/fixup.S +++ b/arch/parisc/lib/fixup.S @@ -26,6 +26,7 @@ #ifdef CONFIG_SMP .macro get_fault_ip t1 t2 + loadgp addil LT%__per_cpu_offset,%r27 LDREG RT%__per_cpu_offset(%r1),\t1 /* t2 = smp_processor_id() */ @@ -40,14 +41,19 @@ LDREG RT%exception_data(%r1),\t1 /* t1 = this_cpu_ptr(&exception_data) */ add,l \t1,\t2,\t1 + /* %r27 = t1->fault_gp - restore gp */ + LDREG EXCDATA_GP(\t1), %r27 /* t1 = t1->fault_ip */ LDREG EXCDATA_IP(\t1), \t1 .endm #else .macro get_fault_ip t1 t2 + loadgp /* t1 = this_cpu_ptr(&exception_data) */ addil LT%exception_data,%r27 LDREG RT%exception_data(%r1),\t2 + /* %r27 = t2->fault_gp - restore gp */ + LDREG EXCDATA_GP(\t2), %r27 /* t1 = t2->fault_ip */ LDREG EXCDATA_IP(\t2), \t1 .endm diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index a762864ec92e..16dbe81c97c9 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -140,21 +140,17 @@ int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *fix; - /* If we only stored 32bit addresses in the exception table we can drop - * out if we faulted on a 64bit address. */ - if ((sizeof(regs->iaoq[0]) > sizeof(fix->insn)) - && (regs->iaoq[0] >> 32)) - return 0; - fix = search_exception_tables(regs->iaoq[0]); if (fix) { struct exception_data *d; d = this_cpu_ptr(&exception_data); d->fault_ip = regs->iaoq[0]; + d->fault_gp = regs->gr[27]; d->fault_space = regs->isr; d->fault_addr = regs->ior; - regs->iaoq[0] = ((fix->fixup) & ~3); + regs->iaoq[0] = (unsigned long)&fix->fixup + fix->fixup; + regs->iaoq[0] &= ~3; /* * NOTE: In some cases the faulting instruction * may be in the delay slot of a branch. We diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c index 54ba39262b82..5d6eea925cf4 100644 --- a/arch/parisc/mm/hugetlbpage.c +++ b/arch/parisc/mm/hugetlbpage.c @@ -63,7 +63,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, if (pud) { pmd = pmd_alloc(mm, pud, addr); if (pmd) - pte = pte_alloc_map(mm, NULL, pmd, addr); + pte = pte_alloc_map(mm, pmd, addr); } return pte; } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 1b366c477687..6b3e7c6ee096 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -22,7 +22,7 @@ #include <linux/swap.h> #include <linux/unistd.h> #include <linux/nodemask.h> /* for node_online_map */ -#include <linux/pagemap.h> /* for release_pages and page_cache_release */ +#include <linux/pagemap.h> /* for release_pages */ #include <linux/compat.h> #include <asm/pgalloc.h> @@ -55,12 +55,12 @@ signed char pfnnid_map[PFNNID_MAP_MAX] __read_mostly; static struct resource data_resource = { .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource code_resource = { .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource pdcdata_resource = { @@ -201,7 +201,7 @@ static void __init setup_bootmem(void) res->name = "System RAM"; res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT; res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); } |