aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-16 18:38:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-16 18:38:31 -0400
commitd0a16fe934383ecdb605ab9312d700fb9099f75e (patch)
treeb9763fcb1b2c7426adbffc6f0f921c79f3230609 /arch/parisc
parent76f0f227cffb570bc5ce343b1750f14907371d80 (diff)
parentfcc16a9e24ba6a2bb9f3af43d892eeec2a435d18 (diff)
Merge branch 'parisc-5.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc updates from Helge Deller: - Make the powerpc implementation to read elf files available as a public kexec interface so it can be re-used on other architectures (Sven) - Implement kexec on parisc (Sven) - Add kprobes on ftrace on parisc (Sven) - Fix kernel crash with HSC-PCI cards based on card-mode Dino - Add assembly implementations for memset, strlen, strcpy, strncpy and strcat - Some cleanups, documentation updates, warning fixes, ... * 'parisc-5.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: (25 commits) parisc: Have git ignore generated real2.S and firmware.c parisc: Disable HP HSC-PCI Cards to prevent kernel crash parisc: add support for kexec_file_load() syscall parisc: wire up kexec_file_load syscall parisc: add kexec syscall support parisc: add __pdc_cpu_rendezvous() kprobes/parisc: remove arch_kprobe_on_func_entry() kexec_elf: support 32 bit ELF files kexec_elf: remove unused variable in kexec_elf_load() kexec_elf: remove Elf_Rel macro kexec_elf: remove PURGATORY_STACK_SIZE kexec_elf: remove parsing of section headers kexec_elf: change order of elf_*_to_cpu() functions kexec: add KEXEC_ELF parisc: Save some bytes in dino driver parisc: Drop comments which are already in pci.h parisc: Convert eisa_enumerator to use pr_cont() parisc: Avoid warning when loading hppb driver parisc: speed up flush_tlb_all_local with qemu parisc: Add ALTERNATIVE_CODE() and ALT_COND_RUN_ON_QEMU ...
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/Kconfig25
-rw-r--r--arch/parisc/boot/compressed/.gitignore2
-rw-r--r--arch/parisc/include/asm/alternative.h11
-rw-r--r--arch/parisc/include/asm/fixmap.h1
-rw-r--r--arch/parisc/include/asm/ftrace.h1
-rw-r--r--arch/parisc/include/asm/kexec.h37
-rw-r--r--arch/parisc/include/asm/pdc.h1
-rw-r--r--arch/parisc/include/asm/string.h15
-rw-r--r--arch/parisc/kernel/Makefile2
-rw-r--r--arch/parisc/kernel/alternative.c23
-rw-r--r--arch/parisc/kernel/entry.S99
-rw-r--r--arch/parisc/kernel/firmware.c13
-rw-r--r--arch/parisc/kernel/ftrace.c64
-rw-r--r--arch/parisc/kernel/kexec.c112
-rw-r--r--arch/parisc/kernel/kexec_file.c86
-rw-r--r--arch/parisc/kernel/kprobes.c4
-rw-r--r--arch/parisc/kernel/pacache.S9
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c4
-rw-r--r--arch/parisc/kernel/pci.c11
-rw-r--r--arch/parisc/kernel/relocate_kernel.S149
-rw-r--r--arch/parisc/kernel/smp.c1
-rw-r--r--arch/parisc/kernel/syscalls/syscall.tbl3
-rw-r--r--arch/parisc/kernel/traps.c2
-rw-r--r--arch/parisc/lib/Makefile4
-rw-r--r--arch/parisc/lib/memset.c91
-rw-r--r--arch/parisc/lib/string.S136
26 files changed, 786 insertions, 120 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 6d732e451071..2e757c785239 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -61,6 +61,8 @@ config PARISC
61 select HAVE_KRETPROBES 61 select HAVE_KRETPROBES
62 select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1) 62 select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1)
63 select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE 63 select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
64 select HAVE_KPROBES_ON_FTRACE
65 select HAVE_DYNAMIC_FTRACE_WITH_REGS
64 66
65 help 67 help
66 The PA-RISC microprocessor is designed by Hewlett-Packard and used 68 The PA-RISC microprocessor is designed by Hewlett-Packard and used
@@ -344,6 +346,29 @@ config NR_CPUS
344 depends on SMP 346 depends on SMP
345 default "4" 347 default "4"
346 348
349config KEXEC
350 bool "Kexec system call"
351 select KEXEC_CORE
352 help
353 kexec is a system call that implements the ability to shutdown your
354 current kernel, and to start another kernel. It is like a reboot
355 but it is independent of the system firmware. And like a reboot
356 you can start any kernel with it, not just Linux.
357
358 It is an ongoing process to be certain the hardware in a machine
359 shutdown, so do not be surprised if this code does not
360 initially work for you.
361
362config KEXEC_FILE
363 bool "kexec file based system call"
364 select KEXEC_CORE
365 select KEXEC_ELF
366 help
367 This enables the kexec_file_load() System call. This is
368 file based and takes file descriptors as system call argument
369 for kernel and initramfs as opposed to list of segments as
370 accepted by previous system call.
371
347endmenu 372endmenu
348 373
349 374
diff --git a/arch/parisc/boot/compressed/.gitignore b/arch/parisc/boot/compressed/.gitignore
index ae06b9b4c02f..926cd41c1069 100644
--- a/arch/parisc/boot/compressed/.gitignore
+++ b/arch/parisc/boot/compressed/.gitignore
@@ -1,3 +1,5 @@
1firmware.c
2real2.S
1sizes.h 3sizes.h
2vmlinux 4vmlinux
3vmlinux.lds 5vmlinux.lds
diff --git a/arch/parisc/include/asm/alternative.h b/arch/parisc/include/asm/alternative.h
index 793d8baa3a10..0ec54f43d6d2 100644
--- a/arch/parisc/include/asm/alternative.h
+++ b/arch/parisc/include/asm/alternative.h
@@ -8,6 +8,7 @@
8#define ALT_COND_NO_ICACHE 0x04 /* if system has no i-cache */ 8#define ALT_COND_NO_ICACHE 0x04 /* if system has no i-cache */
9#define ALT_COND_NO_SPLIT_TLB 0x08 /* if split_tlb == 0 */ 9#define ALT_COND_NO_SPLIT_TLB 0x08 /* if split_tlb == 0 */
10#define ALT_COND_NO_IOC_FDC 0x10 /* if I/O cache does not need flushes */ 10#define ALT_COND_NO_IOC_FDC 0x10 /* if I/O cache does not need flushes */
11#define ALT_COND_RUN_ON_QEMU 0x20 /* if running on QEMU */
11 12
12#define INSN_PxTLB 0x02 /* modify pdtlb, pitlb */ 13#define INSN_PxTLB 0x02 /* modify pdtlb, pitlb */
13#define INSN_NOP 0x08000240 /* nop */ 14#define INSN_NOP 0x08000240 /* nop */
@@ -21,7 +22,7 @@
21 22
22struct alt_instr { 23struct alt_instr {
23 s32 orig_offset; /* offset to original instructions */ 24 s32 orig_offset; /* offset to original instructions */
24 u32 len; /* end of original instructions */ 25 s32 len; /* end of original instructions */
25 u32 cond; /* see ALT_COND_XXX */ 26 u32 cond; /* see ALT_COND_XXX */
26 u32 replacement; /* replacement instruction or code */ 27 u32 replacement; /* replacement instruction or code */
27}; 28};
@@ -40,12 +41,20 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
40 41
41#else 42#else
42 43
44/* to replace one single instructions by a new instruction */
43#define ALTERNATIVE(from, to, cond, replacement)\ 45#define ALTERNATIVE(from, to, cond, replacement)\
44 .section .altinstructions, "aw" ! \ 46 .section .altinstructions, "aw" ! \
45 .word (from - .), (to - from)/4 ! \ 47 .word (from - .), (to - from)/4 ! \
46 .word cond, replacement ! \ 48 .word cond, replacement ! \
47 .previous 49 .previous
48 50
51/* to replace multiple instructions by new code */
52#define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\
53 .section .altinstructions, "aw" ! \
54 .word (from - .), -num_instructions ! \
55 .word cond, (new_instr_ptr - .) ! \
56 .previous
57
49#endif /* __ASSEMBLY__ */ 58#endif /* __ASSEMBLY__ */
50 59
51#endif /* __ASM_PARISC_ALTERNATIVE_H */ 60#endif /* __ASM_PARISC_ALTERNATIVE_H */
diff --git a/arch/parisc/include/asm/fixmap.h b/arch/parisc/include/asm/fixmap.h
index 288da73d4cc0..e480b2c05407 100644
--- a/arch/parisc/include/asm/fixmap.h
+++ b/arch/parisc/include/asm/fixmap.h
@@ -30,6 +30,7 @@
30enum fixed_addresses { 30enum fixed_addresses {
31 /* Support writing RO kernel text via kprobes, jump labels, etc. */ 31 /* Support writing RO kernel text via kprobes, jump labels, etc. */
32 FIX_TEXT_POKE0, 32 FIX_TEXT_POKE0,
33 FIX_TEXT_KEXEC,
33 FIX_BITMAP_COUNT 34 FIX_BITMAP_COUNT
34}; 35};
35 36
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 958c0aa5dbb2..a7cf0d05ccf4 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -8,6 +8,7 @@ extern void mcount(void);
8#define MCOUNT_ADDR ((unsigned long)mcount) 8#define MCOUNT_ADDR ((unsigned long)mcount)
9#define MCOUNT_INSN_SIZE 4 9#define MCOUNT_INSN_SIZE 4
10#define CC_USING_NOP_MCOUNT 10#define CC_USING_NOP_MCOUNT
11#define ARCH_SUPPORTS_FTRACE_OPS 1
11extern unsigned long sys_call_table[]; 12extern unsigned long sys_call_table[];
12 13
13extern unsigned long return_address(unsigned int); 14extern unsigned long return_address(unsigned int);
diff --git a/arch/parisc/include/asm/kexec.h b/arch/parisc/include/asm/kexec.h
new file mode 100644
index 000000000000..a99ea747d7ed
--- /dev/null
+++ b/arch/parisc/include/asm/kexec.h
@@ -0,0 +1,37 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _ASM_PARISC_KEXEC_H
3#define _ASM_PARISC_KEXEC_H
4
5#ifdef CONFIG_KEXEC
6
7/* Maximum physical address we can use pages from */
8#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
9/* Maximum address we can reach in physical address mode */
10#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
11/* Maximum address we can use for the control code buffer */
12#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
13
14#define KEXEC_CONTROL_PAGE_SIZE 4096
15
16#define KEXEC_ARCH KEXEC_ARCH_PARISC
17#define ARCH_HAS_KIMAGE_ARCH
18
19#ifndef __ASSEMBLY__
20
21struct kimage_arch {
22 unsigned long initrd_start;
23 unsigned long initrd_end;
24 unsigned long cmdline;
25};
26
27static inline void crash_setup_regs(struct pt_regs *newregs,
28 struct pt_regs *oldregs)
29{
30 /* Dummy implementation for now */
31}
32
33#endif /* __ASSEMBLY__ */
34
35#endif /* CONFIG_KEXEC */
36
37#endif /* _ASM_PARISC_KEXEC_H */
diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h
index 19bb2e46cd36..b388d8176588 100644
--- a/arch/parisc/include/asm/pdc.h
+++ b/arch/parisc/include/asm/pdc.h
@@ -91,6 +91,7 @@ int pdc_sti_call(unsigned long func, unsigned long flags,
91 unsigned long inptr, unsigned long outputr, 91 unsigned long inptr, unsigned long outputr,
92 unsigned long glob_cfg); 92 unsigned long glob_cfg);
93 93
94int __pdc_cpu_rendezvous(void);
94static inline char * os_id_to_string(u16 os_id) { 95static inline char * os_id_to_string(u16 os_id) {
95 switch(os_id) { 96 switch(os_id) {
96 case OS_ID_NONE: return "No OS"; 97 case OS_ID_NONE: return "No OS";
diff --git a/arch/parisc/include/asm/string.h b/arch/parisc/include/asm/string.h
index f6e1132f4e35..4a0c9dbd62fd 100644
--- a/arch/parisc/include/asm/string.h
+++ b/arch/parisc/include/asm/string.h
@@ -8,4 +8,19 @@ extern void * memset(void *, int, size_t);
8#define __HAVE_ARCH_MEMCPY 8#define __HAVE_ARCH_MEMCPY
9void * memcpy(void * dest,const void *src,size_t count); 9void * memcpy(void * dest,const void *src,size_t count);
10 10
11#define __HAVE_ARCH_STRLEN
12extern size_t strlen(const char *s);
13
14#define __HAVE_ARCH_STRCPY
15extern char *strcpy(char *dest, const char *src);
16
17#define __HAVE_ARCH_STRNCPY
18extern char *strncpy(char *dest, const char *src, size_t count);
19
20#define __HAVE_ARCH_STRCAT
21extern char *strcat(char *dest, const char *src);
22
23#define __HAVE_ARCH_MEMSET
24extern void *memset(void *, int, size_t);
25
11#endif 26#endif
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index c232266b517c..2663c8f8be11 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -37,3 +37,5 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
37obj-$(CONFIG_JUMP_LABEL) += jump_label.o 37obj-$(CONFIG_JUMP_LABEL) += jump_label.o
38obj-$(CONFIG_KGDB) += kgdb.o 38obj-$(CONFIG_KGDB) += kgdb.o
39obj-$(CONFIG_KPROBES) += kprobes.o 39obj-$(CONFIG_KPROBES) += kprobes.o
40obj-$(CONFIG_KEXEC) += kexec.o relocate_kernel.o
41obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
diff --git a/arch/parisc/kernel/alternative.c b/arch/parisc/kernel/alternative.c
index ca1f5ca0540a..3c66d5c4d90d 100644
--- a/arch/parisc/kernel/alternative.c
+++ b/arch/parisc/kernel/alternative.c
@@ -28,7 +28,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
28 28
29 for (entry = start; entry < end; entry++, index++) { 29 for (entry = start; entry < end; entry++, index++) {
30 30
31 u32 *from, len, cond, replacement; 31 u32 *from, cond, replacement;
32 s32 len;
32 33
33 from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset); 34 from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset);
34 len = entry->len; 35 len = entry->len;
@@ -49,6 +50,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
49 continue; 50 continue;
50 if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0)) 51 if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0))
51 continue; 52 continue;
53 if ((cond & ALT_COND_RUN_ON_QEMU) && !running_on_qemu)
54 continue;
52 55
53 /* 56 /*
54 * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit 57 * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit
@@ -74,11 +77,19 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
74 if (replacement == INSN_NOP && len > 1) 77 if (replacement == INSN_NOP && len > 1)
75 replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */ 78 replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */
76 79
77 pr_debug("Do %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n", 80 pr_debug("ALTERNATIVE %3d: Cond %2x, Replace %2d instructions to 0x%08x @ 0x%px (%pS)\n",
78 index, cond, len, from, replacement); 81 index, cond, len, replacement, from, from);
79 82
80 /* Replace instruction */ 83 if (len < 0) {
81 *from = replacement; 84 /* Replace multiple instruction by new code */
85 u32 *source;
86 len = -len;
87 source = (u32 *)((ulong)&entry->replacement + entry->replacement);
88 memcpy(from, source, 4 * len);
89 } else {
90 /* Replace by one instruction */
91 *from = replacement;
92 }
82 applied++; 93 applied++;
83 } 94 }
84 95
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index d9d3387f7c47..1d1d748c227f 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1996,6 +1996,7 @@ _mcount:
1996 * calling mcount(), and 2 instructions for ftrace_stub(). That way we 1996 * calling mcount(), and 2 instructions for ftrace_stub(). That way we
1997 * have all on one L1 cacheline. 1997 * have all on one L1 cacheline.
1998 */ 1998 */
1999 ldi 0, %arg3
1999 b ftrace_function_trampoline 2000 b ftrace_function_trampoline
2000 copy %r3, %arg2 /* caller original %sp */ 2001 copy %r3, %arg2 /* caller original %sp */
2001ftrace_stub: 2002ftrace_stub:
@@ -2048,6 +2049,7 @@ ftrace_caller:
2048 LDREG 0(%r3), %r25 2049 LDREG 0(%r3), %r25
2049 copy %rp, %r26 2050 copy %rp, %r26
2050 ldo -8(%r25), %r25 2051 ldo -8(%r25), %r25
2052 ldi 0, %r23 /* no pt_regs */
2051 b,l ftrace_function_trampoline, %rp 2053 b,l ftrace_function_trampoline, %rp
2052 copy %r3, %r24 2054 copy %r3, %r24
2053 2055
@@ -2075,6 +2077,103 @@ ftrace_caller:
2075 2077
2076ENDPROC_CFI(ftrace_caller) 2078ENDPROC_CFI(ftrace_caller)
2077 2079
2080#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS
2081ENTRY_CFI(ftrace_regs_caller,caller,frame=FTRACE_FRAME_SIZE+PT_SZ_ALGN,
2082 CALLS,SAVE_RP,SAVE_SP)
2083ftrace_regs_caller:
2084 .global ftrace_regs_caller
2085
2086 ldo -FTRACE_FRAME_SIZE(%sp), %r1
2087 STREG %rp, -RP_OFFSET(%r1)
2088
2089 copy %sp, %r1
2090 ldo PT_SZ_ALGN(%sp), %sp
2091
2092 STREG %rp, PT_GR2(%r1)
2093 STREG %r3, PT_GR3(%r1)
2094 STREG %r4, PT_GR4(%r1)
2095 STREG %r5, PT_GR5(%r1)
2096 STREG %r6, PT_GR6(%r1)
2097 STREG %r7, PT_GR7(%r1)
2098 STREG %r8, PT_GR8(%r1)
2099 STREG %r9, PT_GR9(%r1)
2100 STREG %r10, PT_GR10(%r1)
2101 STREG %r11, PT_GR11(%r1)
2102 STREG %r12, PT_GR12(%r1)
2103 STREG %r13, PT_GR13(%r1)
2104 STREG %r14, PT_GR14(%r1)
2105 STREG %r15, PT_GR15(%r1)
2106 STREG %r16, PT_GR16(%r1)
2107 STREG %r17, PT_GR17(%r1)
2108 STREG %r18, PT_GR18(%r1)
2109 STREG %r19, PT_GR19(%r1)
2110 STREG %r20, PT_GR20(%r1)
2111 STREG %r21, PT_GR21(%r1)
2112 STREG %r22, PT_GR22(%r1)
2113 STREG %r23, PT_GR23(%r1)
2114 STREG %r24, PT_GR24(%r1)
2115 STREG %r25, PT_GR25(%r1)
2116 STREG %r26, PT_GR26(%r1)
2117 STREG %r27, PT_GR27(%r1)
2118 STREG %r28, PT_GR28(%r1)
2119 STREG %r29, PT_GR29(%r1)
2120 STREG %r30, PT_GR30(%r1)
2121 STREG %r31, PT_GR31(%r1)
2122 mfctl %cr11, %r26
2123 STREG %r26, PT_SAR(%r1)
2124
2125 copy %rp, %r26
2126 LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25
2127 ldo -8(%r25), %r25
2128 copy %r3, %arg2
2129 b,l ftrace_function_trampoline, %rp
2130 copy %r1, %arg3 /* struct pt_regs */
2131
2132 ldo -PT_SZ_ALGN(%sp), %r1
2133
2134 LDREG PT_SAR(%r1), %rp
2135 mtctl %rp, %cr11
2136
2137 LDREG PT_GR2(%r1), %rp
2138 LDREG PT_GR3(%r1), %r3
2139 LDREG PT_GR4(%r1), %r4
2140 LDREG PT_GR5(%r1), %r5
2141 LDREG PT_GR6(%r1), %r6
2142 LDREG PT_GR7(%r1), %r7
2143 LDREG PT_GR8(%r1), %r8
2144 LDREG PT_GR9(%r1), %r9
2145 LDREG PT_GR10(%r1),%r10
2146 LDREG PT_GR11(%r1),%r11
2147 LDREG PT_GR12(%r1),%r12
2148 LDREG PT_GR13(%r1),%r13
2149 LDREG PT_GR14(%r1),%r14
2150 LDREG PT_GR15(%r1),%r15
2151 LDREG PT_GR16(%r1),%r16
2152 LDREG PT_GR17(%r1),%r17
2153 LDREG PT_GR18(%r1),%r18
2154 LDREG PT_GR19(%r1),%r19
2155 LDREG PT_GR20(%r1),%r20
2156 LDREG PT_GR21(%r1),%r21
2157 LDREG PT_GR22(%r1),%r22
2158 LDREG PT_GR23(%r1),%r23
2159 LDREG PT_GR24(%r1),%r24
2160 LDREG PT_GR25(%r1),%r25
2161 LDREG PT_GR26(%r1),%r26
2162 LDREG PT_GR27(%r1),%r27
2163 LDREG PT_GR28(%r1),%r28
2164 LDREG PT_GR29(%r1),%r29
2165 LDREG PT_GR30(%r1),%r30
2166 LDREG PT_GR31(%r1),%r31
2167
2168 ldo -PT_SZ_ALGN(%sp), %sp
2169 LDREGM -FTRACE_FRAME_SIZE(%sp), %r1
2170 /* Adjust return point to jump back to beginning of traced function */
2171 ldo -4(%r1), %r1
2172 bv,n (%r1)
2173
2174ENDPROC_CFI(ftrace_regs_caller)
2175
2176#endif
2078#endif 2177#endif
2079 2178
2080#ifdef CONFIG_FUNCTION_GRAPH_TRACER 2179#ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 58cc08e7fd12..1d976f2ebff0 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -312,6 +312,19 @@ int pdc_chassis_disp(unsigned long disp)
312} 312}
313 313
314/** 314/**
315 * pdc_cpu_rendenzvous - Stop currently executing CPU
316 * @retval: -1 on error, 0 on success
317 */
318int __pdc_cpu_rendezvous(void)
319{
320 if (is_pdc_pat())
321 return mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_RENDEZVOUS);
322 else
323 return mem_pdc_call(PDC_PROC, 1, 0);
324}
325
326
327/**
315 * pdc_chassis_warn - Fetches chassis warnings 328 * pdc_chassis_warn - Fetches chassis warnings
316 * @retval: -1 on error, 0 on success 329 * @retval: -1 on error, 0 on success
317 */ 330 */
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
index b6fb30f2e4bf..b836fc61a24f 100644
--- a/arch/parisc/kernel/ftrace.c
+++ b/arch/parisc/kernel/ftrace.c
@@ -13,6 +13,8 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/ftrace.h> 14#include <linux/ftrace.h>
15#include <linux/uaccess.h> 15#include <linux/uaccess.h>
16#include <linux/kprobes.h>
17#include <linux/ptrace.h>
16 18
17#include <asm/assembly.h> 19#include <asm/assembly.h>
18#include <asm/sections.h> 20#include <asm/sections.h>
@@ -48,17 +50,22 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
48 50
49void notrace __hot ftrace_function_trampoline(unsigned long parent, 51void notrace __hot ftrace_function_trampoline(unsigned long parent,
50 unsigned long self_addr, 52 unsigned long self_addr,
51 unsigned long org_sp_gr3) 53 unsigned long org_sp_gr3,
54 struct pt_regs *regs)
52{ 55{
53#ifndef CONFIG_DYNAMIC_FTRACE 56#ifndef CONFIG_DYNAMIC_FTRACE
54 extern ftrace_func_t ftrace_trace_function; 57 extern ftrace_func_t ftrace_trace_function;
55#endif 58#endif
56 if (ftrace_trace_function != ftrace_stub) 59 extern struct ftrace_ops *function_trace_op;
57 ftrace_trace_function(self_addr, parent, NULL, NULL); 60
61 if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED &&
62 ftrace_trace_function != ftrace_stub)
63 ftrace_trace_function(self_addr, parent,
64 function_trace_op, regs);
58 65
59#ifdef CONFIG_FUNCTION_GRAPH_TRACER 66#ifdef CONFIG_FUNCTION_GRAPH_TRACER
60 if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub || 67 if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub ||
61 ftrace_graph_entry != ftrace_graph_entry_stub) { 68 ftrace_graph_entry != ftrace_graph_entry_stub) {
62 unsigned long *parent_rp; 69 unsigned long *parent_rp;
63 70
64 /* calculate pointer to %rp in stack */ 71 /* calculate pointer to %rp in stack */
@@ -96,6 +103,12 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
96 return 0; 103 return 0;
97} 104}
98 105
106int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
107 unsigned long addr)
108{
109 return 0;
110}
111
99unsigned long ftrace_call_adjust(unsigned long addr) 112unsigned long ftrace_call_adjust(unsigned long addr)
100{ 113{
101 return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4; 114 return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4;
@@ -187,3 +200,46 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
187 return 0; 200 return 0;
188} 201}
189#endif 202#endif
203
204#ifdef CONFIG_KPROBES_ON_FTRACE
205void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
206 struct ftrace_ops *ops, struct pt_regs *regs)
207{
208 struct kprobe_ctlblk *kcb;
209 struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip);
210
211 if (unlikely(!p) || kprobe_disabled(p))
212 return;
213
214 if (kprobe_running()) {
215 kprobes_inc_nmissed_count(p);
216 return;
217 }
218
219 __this_cpu_write(current_kprobe, p);
220
221 kcb = get_kprobe_ctlblk();
222 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
223
224 regs->iaoq[0] = ip;
225 regs->iaoq[1] = ip + 4;
226
227 if (!p->pre_handler || !p->pre_handler(p, regs)) {
228 regs->iaoq[0] = ip + 4;
229 regs->iaoq[1] = ip + 8;
230
231 if (unlikely(p->post_handler)) {
232 kcb->kprobe_status = KPROBE_HIT_SSDONE;
233 p->post_handler(p, regs, 0);
234 }
235 }
236 __this_cpu_write(current_kprobe, NULL);
237}
238NOKPROBE_SYMBOL(kprobe_ftrace_handler);
239
240int arch_prepare_kprobe_ftrace(struct kprobe *p)
241{
242 p->ainsn.insn = NULL;
243 return 0;
244}
245#endif
diff --git a/arch/parisc/kernel/kexec.c b/arch/parisc/kernel/kexec.c
new file mode 100644
index 000000000000..5eb7f30edc1f
--- /dev/null
+++ b/arch/parisc/kernel/kexec.c
@@ -0,0 +1,112 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/kernel.h>
4#include <linux/console.h>
5#include <linux/kexec.h>
6#include <linux/delay.h>
7#include <asm/cacheflush.h>
8#include <asm/sections.h>
9
10extern void relocate_new_kernel(unsigned long head,
11 unsigned long start,
12 unsigned long phys);
13
14extern const unsigned int relocate_new_kernel_size;
15extern unsigned int kexec_initrd_start_offset;
16extern unsigned int kexec_initrd_end_offset;
17extern unsigned int kexec_cmdline_offset;
18extern unsigned int kexec_free_mem_offset;
19
20static void kexec_show_segment_info(const struct kimage *kimage,
21 unsigned long n)
22{
23 pr_debug(" segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n",
24 n,
25 kimage->segment[n].mem,
26 kimage->segment[n].mem + kimage->segment[n].memsz,
27 (unsigned long)kimage->segment[n].memsz,
28 (unsigned long)kimage->segment[n].memsz / PAGE_SIZE);
29}
30
31static void kexec_image_info(const struct kimage *kimage)
32{
33 unsigned long i;
34
35 pr_debug("kexec kimage info:\n");
36 pr_debug(" type: %d\n", kimage->type);
37 pr_debug(" start: %lx\n", kimage->start);
38 pr_debug(" head: %lx\n", kimage->head);
39 pr_debug(" nr_segments: %lu\n", kimage->nr_segments);
40
41 for (i = 0; i < kimage->nr_segments; i++)
42 kexec_show_segment_info(kimage, i);
43
44#ifdef CONFIG_KEXEC_FILE
45 if (kimage->file_mode) {
46 pr_debug("cmdline: %.*s\n", (int)kimage->cmdline_buf_len,
47 kimage->cmdline_buf);
48 }
49#endif
50}
51
52void machine_kexec_cleanup(struct kimage *kimage)
53{
54}
55
56void machine_crash_shutdown(struct pt_regs *regs)
57{
58}
59
60void machine_shutdown(void)
61{
62 smp_send_stop();
63 while (num_online_cpus() > 1) {
64 cpu_relax();
65 mdelay(1);
66 }
67}
68
69void machine_kexec(struct kimage *image)
70{
71#ifdef CONFIG_64BIT
72 Elf64_Fdesc desc;
73#endif
74 void (*reloc)(unsigned long head,
75 unsigned long start,
76 unsigned long phys);
77
78 unsigned long phys = page_to_phys(image->control_code_page);
79 void *virt = (void *)__fix_to_virt(FIX_TEXT_KEXEC);
80 struct kimage_arch *arch = &image->arch;
81
82 set_fixmap(FIX_TEXT_KEXEC, phys);
83
84 flush_cache_all();
85
86#ifdef CONFIG_64BIT
87 reloc = (void *)&desc;
88 desc.addr = (long long)virt;
89#else
90 reloc = (void *)virt;
91#endif
92
93 memcpy(virt, dereference_function_descriptor(relocate_new_kernel),
94 relocate_new_kernel_size);
95
96 *(unsigned long *)(virt + kexec_cmdline_offset) = arch->cmdline;
97 *(unsigned long *)(virt + kexec_initrd_start_offset) = arch->initrd_start;
98 *(unsigned long *)(virt + kexec_initrd_end_offset) = arch->initrd_end;
99 *(unsigned long *)(virt + kexec_free_mem_offset) = PAGE0->mem_free;
100
101 flush_cache_all();
102 flush_tlb_all();
103 local_irq_disable();
104
105 reloc(image->head & PAGE_MASK, image->start, phys);
106}
107
108int machine_kexec_prepare(struct kimage *image)
109{
110 kexec_image_info(image);
111 return 0;
112}
diff --git a/arch/parisc/kernel/kexec_file.c b/arch/parisc/kernel/kexec_file.c
new file mode 100644
index 000000000000..8c534204f0fd
--- /dev/null
+++ b/arch/parisc/kernel/kexec_file.c
@@ -0,0 +1,86 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Load ELF vmlinux file for the kexec_file_load syscall.
4 *
5 * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
6 *
7 */
8#include <linux/elf.h>
9#include <linux/kexec.h>
10#include <linux/libfdt.h>
11#include <linux/module.h>
12#include <linux/of_fdt.h>
13#include <linux/slab.h>
14#include <linux/types.h>
15
16static void *elf_load(struct kimage *image, char *kernel_buf,
17 unsigned long kernel_len, char *initrd,
18 unsigned long initrd_len, char *cmdline,
19 unsigned long cmdline_len)
20{
21 int ret, i;
22 unsigned long kernel_load_addr;
23 struct elfhdr ehdr;
24 struct kexec_elf_info elf_info;
25 struct kexec_buf kbuf = { .image = image, .buf_min = 0,
26 .buf_max = -1UL, };
27
28 ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info);
29 if (ret)
30 goto out;
31
32 ret = kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &kernel_load_addr);
33 if (ret)
34 goto out;
35
36 image->start = __pa(elf_info.ehdr->e_entry);
37
38 for (i = 0; i < image->nr_segments; i++)
39 image->segment[i].mem = __pa(image->segment[i].mem);
40
41 pr_debug("Loaded the kernel at 0x%lx, entry at 0x%lx\n",
42 kernel_load_addr, image->start);
43
44 if (initrd != NULL) {
45 kbuf.buffer = initrd;
46 kbuf.bufsz = kbuf.memsz = initrd_len;
47 kbuf.buf_align = PAGE_SIZE;
48 kbuf.top_down = false;
49 kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
50 ret = kexec_add_buffer(&kbuf);
51 if (ret)
52 goto out;
53
54 pr_debug("Loaded initrd at 0x%lx\n", kbuf.mem);
55 image->arch.initrd_start = kbuf.mem;
56 image->arch.initrd_end = kbuf.mem + initrd_len;
57 }
58
59 if (cmdline != NULL) {
60 kbuf.buffer = cmdline;
61 kbuf.bufsz = kbuf.memsz = ALIGN(cmdline_len, 8);
62 kbuf.buf_align = PAGE_SIZE;
63 kbuf.top_down = false;
64 kbuf.buf_min = PAGE0->mem_free + PAGE_SIZE;
65 kbuf.buf_max = kernel_load_addr;
66 kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
67 ret = kexec_add_buffer(&kbuf);
68 if (ret)
69 goto out;
70
71 pr_debug("Loaded cmdline at 0x%lx\n", kbuf.mem);
72 image->arch.cmdline = kbuf.mem;
73 }
74out:
75 return NULL;
76}
77
78const struct kexec_file_ops kexec_elf_ops = {
79 .probe = kexec_elf_probe,
80 .load = elf_load,
81};
82
83const struct kexec_file_ops * const kexec_file_loaders[] = {
84 &kexec_elf_ops,
85 NULL
86};
diff --git a/arch/parisc/kernel/kprobes.c b/arch/parisc/kernel/kprobes.c
index 5d7f2692ac5a..77ec51818916 100644
--- a/arch/parisc/kernel/kprobes.c
+++ b/arch/parisc/kernel/kprobes.c
@@ -281,10 +281,6 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
281{ 281{
282 return p->addr == trampoline_p.addr; 282 return p->addr == trampoline_p.addr;
283} 283}
284bool arch_kprobe_on_func_entry(unsigned long offset)
285{
286 return !offset;
287}
288 284
289int __init arch_init_kprobes(void) 285int __init arch_init_kprobes(void)
290{ 286{
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index df46b0e5a915..fa092ed1e837 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -174,6 +174,15 @@ fdtdone:
174 174
1752: bv %r0(%r2) 1752: bv %r0(%r2)
176 nop 176 nop
177
178 /*
179 * When running in qemu, drop whole flush_tlb_all_local function and
180 * replace by one pdtlbe instruction, for which QEMU will drop all
181 * local TLB entries.
182 */
1833: pdtlbe %r0(%sr1,%r0)
184 bv,n %r0(%r2)
185 ALTERNATIVE_CODE(flush_tlb_all_local, 2, ALT_COND_RUN_ON_QEMU, 3b)
177ENDPROC_CFI(flush_tlb_all_local) 186ENDPROC_CFI(flush_tlb_all_local)
178 187
179 .import cache_info,data 188 .import cache_info,data
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index e8a6a751dfd8..8ed409ecec93 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -17,6 +17,10 @@
17 17
18#include <linux/string.h> 18#include <linux/string.h>
19EXPORT_SYMBOL(memset); 19EXPORT_SYMBOL(memset);
20EXPORT_SYMBOL(strlen);
21EXPORT_SYMBOL(strcpy);
22EXPORT_SYMBOL(strncpy);
23EXPORT_SYMBOL(strcat);
20 24
21#include <linux/atomic.h> 25#include <linux/atomic.h>
22EXPORT_SYMBOL(__xchg8); 26EXPORT_SYMBOL(__xchg8);
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index bc41ca243cfe..cf285b17a5ae 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -34,17 +34,6 @@
34#define DBG_RES(x...) 34#define DBG_RES(x...)
35#endif 35#endif
36 36
37/* To be used as: mdelay(pci_post_reset_delay);
38 *
39 * post_reset is the time the kernel should stall to prevent anyone from
40 * accessing the PCI bus once #RESET is de-asserted.
41 * PCI spec somewhere says 1 second but with multi-PCI bus systems,
42 * this makes the boot time much longer than necessary.
43 * 20ms seems to work for all the HP PCI implementations to date.
44 *
45 * #define pci_post_reset_delay 50
46 */
47
48struct pci_port_ops *pci_port __ro_after_init; 37struct pci_port_ops *pci_port __ro_after_init;
49struct pci_bios_ops *pci_bios __ro_after_init; 38struct pci_bios_ops *pci_bios __ro_after_init;
50 39
diff --git a/arch/parisc/kernel/relocate_kernel.S b/arch/parisc/kernel/relocate_kernel.S
new file mode 100644
index 000000000000..2561e52b8d9b
--- /dev/null
+++ b/arch/parisc/kernel/relocate_kernel.S
@@ -0,0 +1,149 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#include <linux/linkage.h>
3#include <linux/kexec.h>
4
5#include <asm/assembly.h>
6#include <asm/asm-offsets.h>
7#include <asm/page.h>
8#include <asm/setup.h>
9#include <asm/psw.h>
10
11.level PA_ASM_LEVEL
12
13.macro kexec_param name
14.align 8
15ENTRY(kexec\()_\name)
16#ifdef CONFIG_64BIT
17 .dword 0
18#else
19 .word 0
20#endif
21
22ENTRY(kexec\()_\name\()_offset)
23 .word kexec\()_\name - relocate_new_kernel
24.endm
25
26.text
27
28/* args:
29 * r26 - kimage->head
30 * r25 - start address of kernel
31 * r24 - physical address of relocate code
32 */
33
34ENTRY_CFI(relocate_new_kernel)
350: copy %arg1, %rp
36 /* disable I and Q bit, so we are allowed to execute RFI */
37 rsm PSW_SM_I, %r0
38 nop
39 nop
40 nop
41 nop
42 nop
43 nop
44 nop
45
46 rsm PSW_SM_Q, %r0
47 nop
48 nop
49 nop
50 nop
51 nop
52 nop
53 nop
54
55 /*
56 * After return-from-interrupt, we want to run without Code/Data
57 * translation enabled just like on a normal boot.
58 */
59
60 /* calculate new physical execution address */
61 ldo 1f-0b(%arg2), %r1
62 mtctl %r0, %cr17 /* IIASQ */
63 mtctl %r0, %cr17 /* IIASQ */
64 mtctl %r1, %cr18 /* IIAOQ */
65 ldo 4(%r1),%r1
66 mtctl %r1, %cr18 /* IIAOQ */
67#ifdef CONFIG_64BIT
68 depdi,z 1, PSW_W_BIT, 1, %r1
69 mtctl %r1, %cr22 /* IPSW */
70#else
71 mtctl %r0, %cr22 /* IPSW */
72#endif
73 /* lets go... */
74 rfi
751: nop
76 nop
77
78.Lloop:
79 LDREG,ma REG_SZ(%arg0), %r3
80 /* If crash kernel, no copy needed */
81 cmpib,COND(=),n 0,%r3,boot
82
83 bb,<,n %r3, 31 - IND_DONE_BIT, boot
84 bb,>=,n %r3, 31 - IND_INDIRECTION_BIT, .Lnotind
85 /* indirection, load and restart */
86 movb %r3, %arg0, .Lloop
87 depi 0, 31, PAGE_SHIFT, %arg0
88
89.Lnotind:
90 bb,>=,n %r3, 31 - IND_DESTINATION_BIT, .Lnotdest
91 b .Lloop
92 copy %r3, %r20
93
94.Lnotdest:
95 bb,>= %r3, 31 - IND_SOURCE_BIT, .Lloop
96 depi 0, 31, PAGE_SHIFT, %r3
97 copy %r3, %r21
98
99 /* copy page */
100 copy %r0, %r18
101 zdepi 1, 31 - PAGE_SHIFT, 1, %r18
102 add %r20, %r18, %r17
103
104 depi 0, 31, PAGE_SHIFT, %r20
105.Lcopy:
106 copy %r20, %r12
107 LDREG,ma REG_SZ(%r21), %r8
108 LDREG,ma REG_SZ(%r21), %r9
109 LDREG,ma REG_SZ(%r21), %r10
110 LDREG,ma REG_SZ(%r21), %r11
111 STREG,ma %r8, REG_SZ(%r20)
112 STREG,ma %r9, REG_SZ(%r20)
113 STREG,ma %r10, REG_SZ(%r20)
114 STREG,ma %r11, REG_SZ(%r20)
115
116#ifndef CONFIG_64BIT
117 LDREG,ma REG_SZ(%r21), %r8
118 LDREG,ma REG_SZ(%r21), %r9
119 LDREG,ma REG_SZ(%r21), %r10
120 LDREG,ma REG_SZ(%r21), %r11
121 STREG,ma %r8, REG_SZ(%r20)
122 STREG,ma %r9, REG_SZ(%r20)
123 STREG,ma %r10, REG_SZ(%r20)
124 STREG,ma %r11, REG_SZ(%r20)
125#endif
126
127 fdc %r0(%r12)
128 cmpb,COND(<<) %r20,%r17,.Lcopy
129 fic (%sr4, %r12)
130 b,n .Lloop
131
132boot:
133 mtctl %r0, %cr15
134
135 LDREG kexec_free_mem-0b(%arg2), %arg0
136 LDREG kexec_cmdline-0b(%arg2), %arg1
137 LDREG kexec_initrd_end-0b(%arg2), %arg3
138 LDREG kexec_initrd_start-0b(%arg2), %arg2
139 bv,n %r0(%rp)
140
141ENDPROC_CFI(relocate_new_kernel);
142
143ENTRY(relocate_new_kernel_size)
144 .word relocate_new_kernel_size - relocate_new_kernel
145
146kexec_param cmdline
147kexec_param initrd_start
148kexec_param initrd_end
149kexec_param free_mem
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index cbd074ba22da..e202c37e56af 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -109,6 +109,7 @@ halt_processor(void)
109 /* REVISIT : does PM *know* this CPU isn't available? */ 109 /* REVISIT : does PM *know* this CPU isn't available? */
110 set_cpu_online(smp_processor_id(), false); 110 set_cpu_online(smp_processor_id(), false);
111 local_irq_disable(); 111 local_irq_disable();
112 __pdc_cpu_rendezvous();
112 for (;;) 113 for (;;)
113 ; 114 ;
114} 115}
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index 670d1371aca1..285ff516150c 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -399,7 +399,8 @@
399352 common pkey_alloc sys_pkey_alloc 399352 common pkey_alloc sys_pkey_alloc
400353 common pkey_free sys_pkey_free 400353 common pkey_free sys_pkey_free
401354 common rseq sys_rseq 401354 common rseq sys_rseq
402# 355 through 402 are unassigned to sync up with generic numbers 402355 common kexec_file_load sys_kexec_file_load sys_kexec_file_load
403# up to 402 is unassigned and reserved for arch specific syscalls
403403 32 clock_gettime64 sys_clock_gettime sys_clock_gettime 404403 32 clock_gettime64 sys_clock_gettime sys_clock_gettime
404404 32 clock_settime64 sys_clock_settime sys_clock_settime 405404 32 clock_settime64 sys_clock_settime sys_clock_settime
405405 32 clock_adjtime64 sys_clock_adjtime sys_clock_adjtime 406405 32 clock_adjtime64 sys_clock_adjtime sys_clock_adjtime
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 58dcf445e32f..82fc01189488 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -29,6 +29,7 @@
29#include <linux/bug.h> 29#include <linux/bug.h>
30#include <linux/ratelimit.h> 30#include <linux/ratelimit.h>
31#include <linux/uaccess.h> 31#include <linux/uaccess.h>
32#include <linux/kdebug.h>
32 33
33#include <asm/assembly.h> 34#include <asm/assembly.h>
34#include <asm/io.h> 35#include <asm/io.h>
@@ -414,6 +415,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o
414{ 415{
415 static DEFINE_SPINLOCK(terminate_lock); 416 static DEFINE_SPINLOCK(terminate_lock);
416 417
418 (void)notify_die(DIE_OOPS, msg, regs, 0, code, SIGTRAP);
417 bust_spinlocks(1); 419 bust_spinlocks(1);
418 420
419 set_eiem(0); 421 set_eiem(0);
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
index 7b197667faf6..2d7a9974dbae 100644
--- a/arch/parisc/lib/Makefile
+++ b/arch/parisc/lib/Makefile
@@ -3,7 +3,7 @@
3# Makefile for parisc-specific library files 3# Makefile for parisc-specific library files
4# 4#
5 5
6lib-y := lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \ 6lib-y := lusercopy.o bitops.o checksum.o io.o memcpy.o \
7 ucmpdi2.o delay.o 7 ucmpdi2.o delay.o string.o
8 8
9obj-y := iomap.o 9obj-y := iomap.o
diff --git a/arch/parisc/lib/memset.c b/arch/parisc/lib/memset.c
deleted file mode 100644
index 1d7929bd7642..000000000000
--- a/arch/parisc/lib/memset.c
+++ /dev/null
@@ -1,91 +0,0 @@
1/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19/* Slight modifications for pa-risc linux - Paul Bame <bame@debian.org> */
20
21#include <linux/types.h>
22#include <asm/string.h>
23
24#define OPSIZ (BITS_PER_LONG/8)
25typedef unsigned long op_t;
26
27void *
28memset (void *dstpp, int sc, size_t len)
29{
30 unsigned int c = sc;
31 long int dstp = (long int) dstpp;
32
33 if (len >= 8)
34 {
35 size_t xlen;
36 op_t cccc;
37
38 cccc = (unsigned char) c;
39 cccc |= cccc << 8;
40 cccc |= cccc << 16;
41 if (OPSIZ > 4)
42 /* Do the shift in two steps to avoid warning if long has 32 bits. */
43 cccc |= (cccc << 16) << 16;
44
45 /* There are at least some bytes to set.
46 No need to test for LEN == 0 in this alignment loop. */
47 while (dstp % OPSIZ != 0)
48 {
49 ((unsigned char *) dstp)[0] = c;
50 dstp += 1;
51 len -= 1;
52 }
53
54 /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */
55 xlen = len / (OPSIZ * 8);
56 while (xlen > 0)
57 {
58 ((op_t *) dstp)[0] = cccc;
59 ((op_t *) dstp)[1] = cccc;
60 ((op_t *) dstp)[2] = cccc;
61 ((op_t *) dstp)[3] = cccc;
62 ((op_t *) dstp)[4] = cccc;
63 ((op_t *) dstp)[5] = cccc;
64 ((op_t *) dstp)[6] = cccc;
65 ((op_t *) dstp)[7] = cccc;
66 dstp += 8 * OPSIZ;
67 xlen -= 1;
68 }
69 len %= OPSIZ * 8;
70
71 /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */
72 xlen = len / OPSIZ;
73 while (xlen > 0)
74 {
75 ((op_t *) dstp)[0] = cccc;
76 dstp += OPSIZ;
77 xlen -= 1;
78 }
79 len %= OPSIZ;
80 }
81
82 /* Write the last few bytes. */
83 while (len > 0)
84 {
85 ((unsigned char *) dstp)[0] = c;
86 dstp += 1;
87 len -= 1;
88 }
89
90 return dstpp;
91}
diff --git a/arch/parisc/lib/string.S b/arch/parisc/lib/string.S
new file mode 100644
index 000000000000..4a64264427a6
--- /dev/null
+++ b/arch/parisc/lib/string.S
@@ -0,0 +1,136 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * PA-RISC assembly string functions
4 *
5 * Copyright (C) 2019 Helge Deller <deller@gmx.de>
6 */
7
8#include <asm/assembly.h>
9#include <linux/linkage.h>
10
11 .section .text.hot
12 .level PA_ASM_LEVEL
13
14 t0 = r20
15 t1 = r21
16 t2 = r22
17
18ENTRY_CFI(strlen, frame=0,no_calls)
19 or,COND(<>) arg0,r0,ret0
20 b,l,n .Lstrlen_null_ptr,r0
21 depwi 0,31,2,ret0
22 cmpb,COND(<>) arg0,ret0,.Lstrlen_not_aligned
23 ldw,ma 4(ret0),t0
24 cmpib,tr 0,r0,.Lstrlen_loop
25 uxor,nbz r0,t0,r0
26.Lstrlen_not_aligned:
27 uaddcm arg0,ret0,t1
28 shladd t1,3,r0,t1
29 mtsar t1
30 depwi -1,%sar,32,t0
31 uxor,nbz r0,t0,r0
32.Lstrlen_loop:
33 b,l,n .Lstrlen_end_loop,r0
34 ldw,ma 4(ret0),t0
35 cmpib,tr 0,r0,.Lstrlen_loop
36 uxor,nbz r0,t0,r0
37.Lstrlen_end_loop:
38 extrw,u,<> t0,7,8,r0
39 addib,tr,n -3,ret0,.Lstrlen_out
40 extrw,u,<> t0,15,8,r0
41 addib,tr,n -2,ret0,.Lstrlen_out
42 extrw,u,<> t0,23,8,r0
43 addi -1,ret0,ret0
44.Lstrlen_out:
45 bv r0(rp)
46 uaddcm ret0,arg0,ret0
47.Lstrlen_null_ptr:
48 bv,n r0(rp)
49ENDPROC_CFI(strlen)
50
51
52ENTRY_CFI(strcpy, frame=0,no_calls)
53 ldb 0(arg1),t0
54 stb t0,0(arg0)
55 ldo 0(arg0),ret0
56 ldo 1(arg1),t1
57 cmpb,= r0,t0,2f
58 ldo 1(arg0),t2
591: ldb 0(t1),arg1
60 stb arg1,0(t2)
61 ldo 1(t1),t1
62 cmpb,<> r0,arg1,1b
63 ldo 1(t2),t2
642: bv,n r0(rp)
65ENDPROC_CFI(strcpy)
66
67
68ENTRY_CFI(strncpy, frame=0,no_calls)
69 ldb 0(arg1),t0
70 stb t0,0(arg0)
71 ldo 1(arg1),t1
72 ldo 0(arg0),ret0
73 cmpb,= r0,t0,2f
74 ldo 1(arg0),arg1
751: ldo -1(arg2),arg2
76 cmpb,COND(=),n r0,arg2,2f
77 ldb 0(t1),arg0
78 stb arg0,0(arg1)
79 ldo 1(t1),t1
80 cmpb,<> r0,arg0,1b
81 ldo 1(arg1),arg1
822: bv,n r0(rp)
83ENDPROC_CFI(strncpy)
84
85
86ENTRY_CFI(strcat, frame=0,no_calls)
87 ldb 0(arg0),t0
88 cmpb,= t0,r0,2f
89 ldo 0(arg0),ret0
90 ldo 1(arg0),arg0
911: ldb 0(arg0),t1
92 cmpb,<>,n r0,t1,1b
93 ldo 1(arg0),arg0
942: ldb 0(arg1),t2
95 stb t2,0(arg0)
96 ldo 1(arg0),arg0
97 ldb 0(arg1),t0
98 cmpb,<> r0,t0,2b
99 ldo 1(arg1),arg1
100 bv,n r0(rp)
101ENDPROC_CFI(strcat)
102
103
104ENTRY_CFI(memset, frame=0,no_calls)
105 copy arg0,ret0
106 cmpb,COND(=) r0,arg0,4f
107 copy arg0,t2
108 cmpb,COND(=) r0,arg2,4f
109 ldo -1(arg2),arg3
110 subi -1,arg3,t0
111 subi 0,t0,t1
112 cmpiclr,COND(>=) 0,t1,arg2
113 ldo -1(t1),arg2
114 extru arg2,31,2,arg0
1152: stb arg1,0(t2)
116 ldo 1(t2),t2
117 addib,>= -1,arg0,2b
118 ldo -1(arg3),arg3
119 cmpiclr,COND(<=) 4,arg2,r0
120 b,l,n 4f,r0
121#ifdef CONFIG_64BIT
122 depd,* r0,63,2,arg2
123#else
124 depw r0,31,2,arg2
125#endif
126 ldo 1(t2),t2
1273: stb arg1,-1(t2)
128 stb arg1,0(t2)
129 stb arg1,1(t2)
130 stb arg1,2(t2)
131 addib,COND(>) -4,arg2,3b
132 ldo 4(t2),t2
1334: bv,n r0(rp)
134ENDPROC_CFI(memset)
135
136 .end