diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-07 22:34:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-07 22:34:17 -0400 |
commit | d3511f53bb2475f2a4e8460bee5a1ae6dea2a433 (patch) | |
tree | 8141260e4fb705d8f94548150572433c685e6829 | |
parent | 02aff8db6438ce29371fd9cd54c57213f4bb4536 (diff) | |
parent | 62217beb394e654bbd2bb87c533dadd2d8bf62c6 (diff) |
Merge branch 'parisc-5.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc updates from Helge Deller:
"Many great new features, fixes and optimizations, including:
- Convert page table updates to use per-pagetable spinlocks which
overall improves performance on SMP machines a lot, by Mikulas
Patocka
- Kernel debugger (KGDB) support, by Sven Schnelle
- KPROBES support, by Sven Schnelle
- Lots of TLB lock/flush improvements, by Dave Anglin
- Drop DISCONTIGMEM and switch to SPARSEMEM
- Added JUMP_LABEL, branch runtime-patching support
- Lots of other small speedups and cleanups, e.g. for QEMU, stack
randomization, avoidance of name clashes, documentation updates,
etc ..."
* 'parisc-5.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: (28 commits)
parisc: Add static branch and JUMP_LABEL feature
parisc: Use PA_ASM_LEVEL in boot code
parisc: Rename LEVEL to PA_ASM_LEVEL to avoid name clash with DRBD code
parisc: Update huge TLB page support to use per-pagetable spinlock
parisc: Use per-pagetable spinlock
parisc: Allow live-patching of __meminit functions
parisc: Add memory barrier to asm pdc and sync instructions
parisc: Add memory clobber to TLB purges
parisc: Use ldcw instruction for SMP spinlock release barrier
parisc: Remove lock code to serialize TLB operations in pacache.S
parisc: Switch from DISCONTIGMEM to SPARSEMEM
parisc: enable wide mode early
parisc: update feature lists
parisc: Show n/a if product number not available
parisc: remove unused flags parameter in __patch_text()
doc: update kprobes supported architecture list
parisc: Implement kretprobes
parisc: remove kprobes.h from generic-y
parisc: Implement kprobes
parisc: add functions required by KPROBE_EVENTS
...
50 files changed, 1258 insertions, 295 deletions
diff --git a/Documentation/features/debug/kgdb/arch-support.txt b/Documentation/features/debug/kgdb/arch-support.txt index 3e6b8f07d5d0..38c40cfa0578 100644 --- a/Documentation/features/debug/kgdb/arch-support.txt +++ b/Documentation/features/debug/kgdb/arch-support.txt | |||
@@ -21,7 +21,7 @@ | |||
21 | | nds32: | TODO | | 21 | | nds32: | TODO | |
22 | | nios2: | ok | | 22 | | nios2: | ok | |
23 | | openrisc: | TODO | | 23 | | openrisc: | TODO | |
24 | | parisc: | TODO | | 24 | | parisc: | ok | |
25 | | powerpc: | ok | | 25 | | powerpc: | ok | |
26 | | riscv: | TODO | | 26 | | riscv: | TODO | |
27 | | s390: | TODO | | 27 | | s390: | TODO | |
diff --git a/Documentation/features/debug/kprobes/arch-support.txt b/Documentation/features/debug/kprobes/arch-support.txt index f4e45bd58fea..e68239b5d2f0 100644 --- a/Documentation/features/debug/kprobes/arch-support.txt +++ b/Documentation/features/debug/kprobes/arch-support.txt | |||
@@ -21,7 +21,7 @@ | |||
21 | | nds32: | TODO | | 21 | | nds32: | TODO | |
22 | | nios2: | TODO | | 22 | | nios2: | TODO | |
23 | | openrisc: | TODO | | 23 | | openrisc: | TODO | |
24 | | parisc: | TODO | | 24 | | parisc: | ok | |
25 | | powerpc: | ok | | 25 | | powerpc: | ok | |
26 | | riscv: | ok | | 26 | | riscv: | ok | |
27 | | s390: | ok | | 27 | | s390: | ok | |
diff --git a/Documentation/features/debug/kretprobes/arch-support.txt b/Documentation/features/debug/kretprobes/arch-support.txt index 1d5651ef11f8..f17131b328e5 100644 --- a/Documentation/features/debug/kretprobes/arch-support.txt +++ b/Documentation/features/debug/kretprobes/arch-support.txt | |||
@@ -21,7 +21,7 @@ | |||
21 | | nds32: | TODO | | 21 | | nds32: | TODO | |
22 | | nios2: | TODO | | 22 | | nios2: | TODO | |
23 | | openrisc: | TODO | | 23 | | openrisc: | TODO | |
24 | | parisc: | TODO | | 24 | | parisc: | ok | |
25 | | powerpc: | ok | | 25 | | powerpc: | ok | |
26 | | riscv: | TODO | | 26 | | riscv: | TODO | |
27 | | s390: | ok | | 27 | | s390: | ok | |
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index ee60e519438a..8baab8832c5b 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt | |||
@@ -321,6 +321,7 @@ architectures: | |||
321 | - ppc | 321 | - ppc |
322 | - mips | 322 | - mips |
323 | - s390 | 323 | - s390 |
324 | - parisc | ||
324 | 325 | ||
325 | Configuring Kprobes | 326 | Configuring Kprobes |
326 | =================== | 327 | =================== |
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index f1ed8ddfe486..09407ed1aacd 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
@@ -36,6 +36,7 @@ config PARISC | |||
36 | select GENERIC_STRNCPY_FROM_USER | 36 | select GENERIC_STRNCPY_FROM_USER |
37 | select SYSCTL_ARCH_UNALIGN_ALLOW | 37 | select SYSCTL_ARCH_UNALIGN_ALLOW |
38 | select SYSCTL_EXCEPTION_TRACE | 38 | select SYSCTL_EXCEPTION_TRACE |
39 | select ARCH_DISCARD_MEMBLOCK | ||
39 | select HAVE_MOD_ARCH_SPECIFIC | 40 | select HAVE_MOD_ARCH_SPECIFIC |
40 | select VIRT_TO_BUS | 41 | select VIRT_TO_BUS |
41 | select MODULES_USE_ELF_RELA | 42 | select MODULES_USE_ELF_RELA |
@@ -44,6 +45,8 @@ config PARISC | |||
44 | select HAVE_DEBUG_STACKOVERFLOW | 45 | select HAVE_DEBUG_STACKOVERFLOW |
45 | select HAVE_ARCH_AUDITSYSCALL | 46 | select HAVE_ARCH_AUDITSYSCALL |
46 | select HAVE_ARCH_HASH | 47 | select HAVE_ARCH_HASH |
48 | select HAVE_ARCH_JUMP_LABEL | ||
49 | select HAVE_ARCH_JUMP_LABEL_RELATIVE | ||
47 | select HAVE_ARCH_SECCOMP_FILTER | 50 | select HAVE_ARCH_SECCOMP_FILTER |
48 | select HAVE_ARCH_TRACEHOOK | 51 | select HAVE_ARCH_TRACEHOOK |
49 | select HAVE_REGS_AND_STACK_ACCESS_API | 52 | select HAVE_REGS_AND_STACK_ACCESS_API |
@@ -54,6 +57,9 @@ config PARISC | |||
54 | select CPU_NO_EFFICIENT_FFS | 57 | select CPU_NO_EFFICIENT_FFS |
55 | select NEED_DMA_MAP_STATE | 58 | select NEED_DMA_MAP_STATE |
56 | select NEED_SG_DMA_LENGTH | 59 | select NEED_SG_DMA_LENGTH |
60 | select HAVE_ARCH_KGDB | ||
61 | select HAVE_KPROBES | ||
62 | select HAVE_KRETPROBES | ||
57 | 63 | ||
58 | help | 64 | help |
59 | The PA-RISC microprocessor is designed by Hewlett-Packard and used | 65 | The PA-RISC microprocessor is designed by Hewlett-Packard and used |
@@ -305,21 +311,16 @@ config ARCH_SELECT_MEMORY_MODEL | |||
305 | def_bool y | 311 | def_bool y |
306 | depends on 64BIT | 312 | depends on 64BIT |
307 | 313 | ||
308 | config ARCH_DISCONTIGMEM_ENABLE | 314 | config ARCH_SPARSEMEM_ENABLE |
309 | def_bool y | 315 | def_bool y |
310 | depends on 64BIT | 316 | depends on 64BIT |
311 | 317 | ||
312 | config ARCH_FLATMEM_ENABLE | 318 | config ARCH_FLATMEM_ENABLE |
313 | def_bool y | 319 | def_bool y |
314 | 320 | ||
315 | config ARCH_DISCONTIGMEM_DEFAULT | 321 | config ARCH_SPARSEMEM_DEFAULT |
316 | def_bool y | 322 | def_bool y |
317 | depends on ARCH_DISCONTIGMEM_ENABLE | 323 | depends on ARCH_SPARSEMEM_ENABLE |
318 | |||
319 | config NODES_SHIFT | ||
320 | int | ||
321 | default "3" | ||
322 | depends on NEED_MULTIPLE_NODES | ||
323 | 324 | ||
324 | source "kernel/Kconfig.hz" | 325 | source "kernel/Kconfig.hz" |
325 | 326 | ||
diff --git a/arch/parisc/boot/compressed/head.S b/arch/parisc/boot/compressed/head.S index 5aba20fa48aa..e8b798fd0cf0 100644 --- a/arch/parisc/boot/compressed/head.S +++ b/arch/parisc/boot/compressed/head.S | |||
@@ -22,7 +22,7 @@ | |||
22 | __HEAD | 22 | __HEAD |
23 | 23 | ||
24 | ENTRY(startup) | 24 | ENTRY(startup) |
25 | .level LEVEL | 25 | .level PA_ASM_LEVEL |
26 | 26 | ||
27 | #define PSW_W_SM 0x200 | 27 | #define PSW_W_SM 0x200 |
28 | #define PSW_W_BIT 36 | 28 | #define PSW_W_BIT 36 |
@@ -63,7 +63,7 @@ $bss_loop: | |||
63 | load32 BOOTADDR(decompress_kernel),%r3 | 63 | load32 BOOTADDR(decompress_kernel),%r3 |
64 | 64 | ||
65 | #ifdef CONFIG_64BIT | 65 | #ifdef CONFIG_64BIT |
66 | .level LEVEL | 66 | .level PA_ASM_LEVEL |
67 | ssm PSW_W_SM, %r0 /* set W-bit */ | 67 | ssm PSW_W_SM, %r0 /* set W-bit */ |
68 | depdi 0, 31, 32, %r3 | 68 | depdi 0, 31, 32, %r3 |
69 | #endif | 69 | #endif |
@@ -72,7 +72,7 @@ $bss_loop: | |||
72 | 72 | ||
73 | startup_continue: | 73 | startup_continue: |
74 | #ifdef CONFIG_64BIT | 74 | #ifdef CONFIG_64BIT |
75 | .level LEVEL | 75 | .level PA_ASM_LEVEL |
76 | rsm PSW_W_SM, %r0 /* clear W-bit */ | 76 | rsm PSW_W_SM, %r0 /* clear W-bit */ |
77 | #endif | 77 | #endif |
78 | 78 | ||
diff --git a/arch/parisc/boot/compressed/misc.c b/arch/parisc/boot/compressed/misc.c index 2556bb181813..2d395998f524 100644 --- a/arch/parisc/boot/compressed/misc.c +++ b/arch/parisc/boot/compressed/misc.c | |||
@@ -145,14 +145,13 @@ static int putchar(int c) | |||
145 | 145 | ||
146 | void __noreturn error(char *x) | 146 | void __noreturn error(char *x) |
147 | { | 147 | { |
148 | puts("\n\n"); | 148 | if (x) puts(x); |
149 | puts(x); | 149 | puts("\n -- System halted\n"); |
150 | puts("\n\n -- System halted"); | ||
151 | while (1) /* wait forever */ | 150 | while (1) /* wait forever */ |
152 | ; | 151 | ; |
153 | } | 152 | } |
154 | 153 | ||
155 | static int print_hex(unsigned long num) | 154 | static int print_num(unsigned long num, int base) |
156 | { | 155 | { |
157 | const char hex[] = "0123456789abcdef"; | 156 | const char hex[] = "0123456789abcdef"; |
158 | char str[40]; | 157 | char str[40]; |
@@ -160,12 +159,14 @@ static int print_hex(unsigned long num) | |||
160 | 159 | ||
161 | str[i--] = '\0'; | 160 | str[i--] = '\0'; |
162 | do { | 161 | do { |
163 | str[i--] = hex[num & 0x0f]; | 162 | str[i--] = hex[num % base]; |
164 | num >>= 4; | 163 | num = num / base; |
165 | } while (num); | 164 | } while (num); |
166 | 165 | ||
167 | str[i--] = 'x'; | 166 | if (base == 16) { |
168 | str[i] = '0'; | 167 | str[i--] = 'x'; |
168 | str[i] = '0'; | ||
169 | } else i++; | ||
169 | puts(&str[i]); | 170 | puts(&str[i]); |
170 | 171 | ||
171 | return 0; | 172 | return 0; |
@@ -187,8 +188,9 @@ put: | |||
187 | 188 | ||
188 | if (fmt[++i] == '%') | 189 | if (fmt[++i] == '%') |
189 | goto put; | 190 | goto put; |
191 | print_num(va_arg(args, unsigned long), | ||
192 | fmt[i] == 'x' ? 16:10); | ||
190 | ++i; | 193 | ++i; |
191 | print_hex(va_arg(args, unsigned long)); | ||
192 | } | 194 | } |
193 | 195 | ||
194 | va_end(args); | 196 | va_end(args); |
@@ -327,8 +329,15 @@ unsigned long decompress_kernel(unsigned int started_wide, | |||
327 | free_mem_end_ptr = rd_start; | 329 | free_mem_end_ptr = rd_start; |
328 | #endif | 330 | #endif |
329 | 331 | ||
330 | if (free_mem_ptr >= free_mem_end_ptr) | 332 | if (free_mem_ptr >= free_mem_end_ptr) { |
331 | error("Kernel too big for machine."); | 333 | int free_ram; |
334 | free_ram = (free_mem_ptr >> 20) + 1; | ||
335 | if (free_ram < 32) | ||
336 | free_ram = 32; | ||
337 | printf("\nKernel requires at least %d MB RAM.\n", | ||
338 | free_ram); | ||
339 | error(NULL); | ||
340 | } | ||
332 | 341 | ||
333 | #ifdef DEBUG | 342 | #ifdef DEBUG |
334 | printf("\n"); | 343 | printf("\n"); |
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild index b8c7db777144..ed2d8cc94909 100644 --- a/arch/parisc/include/asm/Kbuild +++ b/arch/parisc/include/asm/Kbuild | |||
@@ -10,7 +10,6 @@ generic-y += hw_irq.h | |||
10 | generic-y += irq_regs.h | 10 | generic-y += irq_regs.h |
11 | generic-y += irq_work.h | 11 | generic-y += irq_work.h |
12 | generic-y += kdebug.h | 12 | generic-y += kdebug.h |
13 | generic-y += kprobes.h | ||
14 | generic-y += kvm_para.h | 13 | generic-y += kvm_para.h |
15 | generic-y += local.h | 14 | generic-y += local.h |
16 | generic-y += local64.h | 15 | generic-y += local64.h |
diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h index c17ec0ee6e7c..d85738a7bbe6 100644 --- a/arch/parisc/include/asm/assembly.h +++ b/arch/parisc/include/asm/assembly.h | |||
@@ -61,14 +61,14 @@ | |||
61 | #define LDCW ldcw,co | 61 | #define LDCW ldcw,co |
62 | #define BL b,l | 62 | #define BL b,l |
63 | # ifdef CONFIG_64BIT | 63 | # ifdef CONFIG_64BIT |
64 | # define LEVEL 2.0w | 64 | # define PA_ASM_LEVEL 2.0w |
65 | # else | 65 | # else |
66 | # define LEVEL 2.0 | 66 | # define PA_ASM_LEVEL 2.0 |
67 | # endif | 67 | # endif |
68 | #else | 68 | #else |
69 | #define LDCW ldcw | 69 | #define LDCW ldcw |
70 | #define BL bl | 70 | #define BL bl |
71 | #define LEVEL 1.1 | 71 | #define PA_ASM_LEVEL 1.1 |
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | #ifdef __ASSEMBLY__ | 74 | #ifdef __ASSEMBLY__ |
diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h index 006fb939cac8..4016fe1c65a9 100644 --- a/arch/parisc/include/asm/cache.h +++ b/arch/parisc/include/asm/cache.h | |||
@@ -44,22 +44,22 @@ void parisc_setup_cache_timing(void); | |||
44 | 44 | ||
45 | #define pdtlb(addr) asm volatile("pdtlb 0(%%sr1,%0)" \ | 45 | #define pdtlb(addr) asm volatile("pdtlb 0(%%sr1,%0)" \ |
46 | ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \ | 46 | ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \ |
47 | : : "r" (addr)) | 47 | : : "r" (addr) : "memory") |
48 | #define pitlb(addr) asm volatile("pitlb 0(%%sr1,%0)" \ | 48 | #define pitlb(addr) asm volatile("pitlb 0(%%sr1,%0)" \ |
49 | ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \ | 49 | ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \ |
50 | ALTERNATIVE(ALT_COND_NO_SPLIT_TLB, INSN_NOP) \ | 50 | ALTERNATIVE(ALT_COND_NO_SPLIT_TLB, INSN_NOP) \ |
51 | : : "r" (addr)) | 51 | : : "r" (addr) : "memory") |
52 | #define pdtlb_kernel(addr) asm volatile("pdtlb 0(%0)" \ | 52 | #define pdtlb_kernel(addr) asm volatile("pdtlb 0(%0)" \ |
53 | ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \ | 53 | ALTERNATIVE(ALT_COND_NO_SMP, INSN_PxTLB) \ |
54 | : : "r" (addr)) | 54 | : : "r" (addr) : "memory") |
55 | 55 | ||
56 | #define asm_io_fdc(addr) asm volatile("fdc %%r0(%0)" \ | 56 | #define asm_io_fdc(addr) asm volatile("fdc %%r0(%0)" \ |
57 | ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \ | 57 | ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \ |
58 | ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) \ | 58 | ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) \ |
59 | : : "r" (addr)) | 59 | : : "r" (addr) : "memory") |
60 | #define asm_io_sync() asm volatile("sync" \ | 60 | #define asm_io_sync() asm volatile("sync" \ |
61 | ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \ | 61 | ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \ |
62 | ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) :: ) | 62 | ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) :::"memory") |
63 | 63 | ||
64 | #endif /* ! __ASSEMBLY__ */ | 64 | #endif /* ! __ASSEMBLY__ */ |
65 | 65 | ||
diff --git a/arch/parisc/include/asm/fixmap.h b/arch/parisc/include/asm/fixmap.h index f7c3a0905de4..288da73d4cc0 100644 --- a/arch/parisc/include/asm/fixmap.h +++ b/arch/parisc/include/asm/fixmap.h | |||
@@ -15,17 +15,34 @@ | |||
15 | * from areas congruently mapped with user space. It is 8MB large | 15 | * from areas congruently mapped with user space. It is 8MB large |
16 | * and must be 16MB aligned */ | 16 | * and must be 16MB aligned */ |
17 | #define TMPALIAS_MAP_START ((__PAGE_OFFSET) - 16*1024*1024) | 17 | #define TMPALIAS_MAP_START ((__PAGE_OFFSET) - 16*1024*1024) |
18 | |||
19 | #define FIXMAP_SIZE (FIX_BITMAP_COUNT << PAGE_SHIFT) | ||
20 | #define FIXMAP_START (TMPALIAS_MAP_START - FIXMAP_SIZE) | ||
18 | /* This is the kernel area for all maps (vmalloc, dma etc.) most | 21 | /* This is the kernel area for all maps (vmalloc, dma etc.) most |
19 | * usually, it extends up to TMPALIAS_MAP_START. Virtual addresses | 22 | * usually, it extends up to TMPALIAS_MAP_START. Virtual addresses |
20 | * 0..GATEWAY_PAGE_SIZE are reserved for the gateway page */ | 23 | * 0..GATEWAY_PAGE_SIZE are reserved for the gateway page */ |
21 | #define KERNEL_MAP_START (GATEWAY_PAGE_SIZE) | 24 | #define KERNEL_MAP_START (GATEWAY_PAGE_SIZE) |
22 | #define KERNEL_MAP_END (TMPALIAS_MAP_START) | 25 | #define KERNEL_MAP_END (FIXMAP_START) |
23 | 26 | ||
24 | #ifndef __ASSEMBLY__ | 27 | #ifndef __ASSEMBLY__ |
28 | |||
29 | |||
30 | enum fixed_addresses { | ||
31 | /* Support writing RO kernel text via kprobes, jump labels, etc. */ | ||
32 | FIX_TEXT_POKE0, | ||
33 | FIX_BITMAP_COUNT | ||
34 | }; | ||
35 | |||
25 | extern void *parisc_vmalloc_start; | 36 | extern void *parisc_vmalloc_start; |
26 | #define PCXL_DMA_MAP_SIZE (8*1024*1024) | 37 | #define PCXL_DMA_MAP_SIZE (8*1024*1024) |
27 | #define VMALLOC_START ((unsigned long)parisc_vmalloc_start) | 38 | #define VMALLOC_START ((unsigned long)parisc_vmalloc_start) |
28 | #define VMALLOC_END (KERNEL_MAP_END) | 39 | #define VMALLOC_END (KERNEL_MAP_END) |
40 | |||
41 | #define __fix_to_virt(_x) (FIXMAP_START + ((_x) << PAGE_SHIFT)) | ||
42 | |||
43 | void set_fixmap(enum fixed_addresses idx, phys_addr_t phys); | ||
44 | void clear_fixmap(enum fixed_addresses idx); | ||
45 | |||
29 | #endif /*__ASSEMBLY__*/ | 46 | #endif /*__ASSEMBLY__*/ |
30 | 47 | ||
31 | #endif /*_ASM_FIXMAP_H*/ | 48 | #endif /*_ASM_FIXMAP_H*/ |
diff --git a/arch/parisc/include/asm/hardware.h b/arch/parisc/include/asm/hardware.h index d6e1ed145031..9d3d7737c58b 100644 --- a/arch/parisc/include/asm/hardware.h +++ b/arch/parisc/include/asm/hardware.h | |||
@@ -120,7 +120,7 @@ extern void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path); | |||
120 | extern void init_parisc_bus(void); | 120 | extern void init_parisc_bus(void); |
121 | extern struct device *hwpath_to_device(struct hardware_path *modpath); | 121 | extern struct device *hwpath_to_device(struct hardware_path *modpath); |
122 | extern void device_to_hwpath(struct device *dev, struct hardware_path *path); | 122 | extern void device_to_hwpath(struct device *dev, struct hardware_path *path); |
123 | 123 | extern int machine_has_merced_bus(void); | |
124 | 124 | ||
125 | /* inventory.c: */ | 125 | /* inventory.c: */ |
126 | extern void do_memory_inventory(void); | 126 | extern void do_memory_inventory(void); |
diff --git a/arch/parisc/include/asm/jump_label.h b/arch/parisc/include/asm/jump_label.h new file mode 100644 index 000000000000..7efb1aa2f7f8 --- /dev/null +++ b/arch/parisc/include/asm/jump_label.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef _ASM_PARISC_JUMP_LABEL_H | ||
3 | #define _ASM_PARISC_JUMP_LABEL_H | ||
4 | |||
5 | #ifndef __ASSEMBLY__ | ||
6 | |||
7 | #include <linux/types.h> | ||
8 | #include <asm/assembly.h> | ||
9 | |||
10 | #define JUMP_LABEL_NOP_SIZE 4 | ||
11 | |||
12 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) | ||
13 | { | ||
14 | asm_volatile_goto("1:\n\t" | ||
15 | "nop\n\t" | ||
16 | ".pushsection __jump_table, \"aw\"\n\t" | ||
17 | ".word 1b - ., %l[l_yes] - .\n\t" | ||
18 | __stringify(ASM_ULONG_INSN) " %c0 - .\n\t" | ||
19 | ".popsection\n\t" | ||
20 | : : "i" (&((char *)key)[branch]) : : l_yes); | ||
21 | |||
22 | return false; | ||
23 | l_yes: | ||
24 | return true; | ||
25 | } | ||
26 | |||
27 | static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) | ||
28 | { | ||
29 | asm_volatile_goto("1:\n\t" | ||
30 | "b,n %l[l_yes]\n\t" | ||
31 | ".pushsection __jump_table, \"aw\"\n\t" | ||
32 | ".word 1b - ., %l[l_yes] - .\n\t" | ||
33 | __stringify(ASM_ULONG_INSN) " %c0 - .\n\t" | ||
34 | ".popsection\n\t" | ||
35 | : : "i" (&((char *)key)[branch]) : : l_yes); | ||
36 | |||
37 | return false; | ||
38 | l_yes: | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | #endif /* __ASSEMBLY__ */ | ||
43 | #endif | ||
diff --git a/arch/parisc/include/asm/kgdb.h b/arch/parisc/include/asm/kgdb.h new file mode 100644 index 000000000000..f23e7f8f13a5 --- /dev/null +++ b/arch/parisc/include/asm/kgdb.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * PA-RISC KGDB support | ||
4 | * | ||
5 | * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #ifndef __PARISC_KGDB_H__ | ||
10 | #define __PARISC_KGDB_H__ | ||
11 | |||
12 | #define BREAK_INSTR_SIZE 4 | ||
13 | #define PARISC_KGDB_COMPILED_BREAK_INSN 0x3ffc01f | ||
14 | #define PARISC_KGDB_BREAK_INSN 0x3ffa01f | ||
15 | |||
16 | |||
17 | #define NUMREGBYTES sizeof(struct parisc_gdb_regs) | ||
18 | #define BUFMAX 4096 | ||
19 | |||
20 | #define CACHE_FLUSH_IS_SAFE 1 | ||
21 | |||
22 | #ifndef __ASSEMBLY__ | ||
23 | |||
24 | static inline void arch_kgdb_breakpoint(void) | ||
25 | { | ||
26 | asm(".word %0" : : "i"(PARISC_KGDB_COMPILED_BREAK_INSN) : "memory"); | ||
27 | } | ||
28 | |||
29 | struct parisc_gdb_regs { | ||
30 | unsigned long gpr[32]; | ||
31 | unsigned long sar; | ||
32 | unsigned long iaoq_f; | ||
33 | unsigned long iasq_f; | ||
34 | unsigned long iaoq_b; | ||
35 | unsigned long iasq_b; | ||
36 | unsigned long eiem; | ||
37 | unsigned long iir; | ||
38 | unsigned long isr; | ||
39 | unsigned long ior; | ||
40 | unsigned long ipsw; | ||
41 | unsigned long __unused0; | ||
42 | unsigned long sr4; | ||
43 | unsigned long sr0; | ||
44 | unsigned long sr1; | ||
45 | unsigned long sr2; | ||
46 | unsigned long sr3; | ||
47 | unsigned long sr5; | ||
48 | unsigned long sr6; | ||
49 | unsigned long sr7; | ||
50 | unsigned long cr0; | ||
51 | unsigned long pid1; | ||
52 | unsigned long pid2; | ||
53 | unsigned long scrccr; | ||
54 | unsigned long pid3; | ||
55 | unsigned long pid4; | ||
56 | unsigned long cr24; | ||
57 | unsigned long cr25; | ||
58 | unsigned long cr26; | ||
59 | unsigned long cr27; | ||
60 | unsigned long cr28; | ||
61 | unsigned long cr29; | ||
62 | unsigned long cr30; | ||
63 | |||
64 | u64 fr[32]; | ||
65 | }; | ||
66 | |||
67 | #endif | ||
68 | #endif | ||
diff --git a/arch/parisc/include/asm/kprobes.h b/arch/parisc/include/asm/kprobes.h new file mode 100644 index 000000000000..e09cf2deeafe --- /dev/null +++ b/arch/parisc/include/asm/kprobes.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * arch/parisc/include/asm/kprobes.h | ||
4 | * | ||
5 | * PA-RISC kprobes implementation | ||
6 | * | ||
7 | * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> | ||
8 | */ | ||
9 | |||
10 | #ifndef _PARISC_KPROBES_H | ||
11 | #define _PARISC_KPROBES_H | ||
12 | |||
13 | #ifdef CONFIG_KPROBES | ||
14 | |||
15 | #include <asm-generic/kprobes.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/ptrace.h> | ||
18 | #include <linux/notifier.h> | ||
19 | |||
20 | #define PARISC_KPROBES_BREAK_INSN 0x3ff801f | ||
21 | #define __ARCH_WANT_KPROBES_INSN_SLOT | ||
22 | #define MAX_INSN_SIZE 1 | ||
23 | |||
24 | typedef u32 kprobe_opcode_t; | ||
25 | struct kprobe; | ||
26 | |||
27 | void arch_remove_kprobe(struct kprobe *p); | ||
28 | |||
29 | #define flush_insn_slot(p) \ | ||
30 | flush_icache_range((unsigned long)&(p)->ainsn.insn[0], \ | ||
31 | (unsigned long)&(p)->ainsn.insn[0] + \ | ||
32 | sizeof(kprobe_opcode_t)) | ||
33 | |||
34 | #define kretprobe_blacklist_size 0 | ||
35 | |||
36 | struct arch_specific_insn { | ||
37 | kprobe_opcode_t *insn; | ||
38 | }; | ||
39 | |||
40 | struct prev_kprobe { | ||
41 | struct kprobe *kp; | ||
42 | unsigned long status; | ||
43 | }; | ||
44 | |||
45 | struct kprobe_ctlblk { | ||
46 | unsigned int kprobe_status; | ||
47 | struct prev_kprobe prev_kprobe; | ||
48 | unsigned long iaoq[2]; | ||
49 | }; | ||
50 | |||
51 | int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs); | ||
52 | int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs); | ||
53 | |||
54 | #endif /* CONFIG_KPROBES */ | ||
55 | #endif /* _PARISC_KPROBES_H */ | ||
diff --git a/arch/parisc/include/asm/mmzone.h b/arch/parisc/include/asm/mmzone.h index fafa3893fd70..8d390406d862 100644 --- a/arch/parisc/include/asm/mmzone.h +++ b/arch/parisc/include/asm/mmzone.h | |||
@@ -2,62 +2,6 @@ | |||
2 | #ifndef _PARISC_MMZONE_H | 2 | #ifndef _PARISC_MMZONE_H |
3 | #define _PARISC_MMZONE_H | 3 | #define _PARISC_MMZONE_H |
4 | 4 | ||
5 | #define MAX_PHYSMEM_RANGES 8 /* Fix the size for now (current known max is 3) */ | 5 | #define MAX_PHYSMEM_RANGES 4 /* Fix the size for now (current known max is 3) */ |
6 | 6 | ||
7 | #ifdef CONFIG_DISCONTIGMEM | ||
8 | |||
9 | extern int npmem_ranges; | ||
10 | |||
11 | struct node_map_data { | ||
12 | pg_data_t pg_data; | ||
13 | }; | ||
14 | |||
15 | extern struct node_map_data node_data[]; | ||
16 | |||
17 | #define NODE_DATA(nid) (&node_data[nid].pg_data) | ||
18 | |||
19 | /* We have these possible memory map layouts: | ||
20 | * Astro: 0-3.75, 67.75-68, 4-64 | ||
21 | * zx1: 0-1, 257-260, 4-256 | ||
22 | * Stretch (N-class): 0-2, 4-32, 34-xxx | ||
23 | */ | ||
24 | |||
25 | /* Since each 1GB can only belong to one region (node), we can create | ||
26 | * an index table for pfn to nid lookup; each entry in pfnnid_map | ||
27 | * represents 1GB, and contains the node that the memory belongs to. */ | ||
28 | |||
29 | #define PFNNID_SHIFT (30 - PAGE_SHIFT) | ||
30 | #define PFNNID_MAP_MAX 512 /* support 512GB */ | ||
31 | extern signed char pfnnid_map[PFNNID_MAP_MAX]; | ||
32 | |||
33 | #ifndef CONFIG_64BIT | ||
34 | #define pfn_is_io(pfn) ((pfn & (0xf0000000UL >> PAGE_SHIFT)) == (0xf0000000UL >> PAGE_SHIFT)) | ||
35 | #else | ||
36 | /* io can be 0xf0f0f0f0f0xxxxxx or 0xfffffffff0000000 */ | ||
37 | #define pfn_is_io(pfn) ((pfn & (0xf000000000000000UL >> PAGE_SHIFT)) == (0xf000000000000000UL >> PAGE_SHIFT)) | ||
38 | #endif | ||
39 | |||
40 | static inline int pfn_to_nid(unsigned long pfn) | ||
41 | { | ||
42 | unsigned int i; | ||
43 | |||
44 | if (unlikely(pfn_is_io(pfn))) | ||
45 | return 0; | ||
46 | |||
47 | i = pfn >> PFNNID_SHIFT; | ||
48 | BUG_ON(i >= ARRAY_SIZE(pfnnid_map)); | ||
49 | |||
50 | return pfnnid_map[i]; | ||
51 | } | ||
52 | |||
53 | static inline int pfn_valid(int pfn) | ||
54 | { | ||
55 | int nid = pfn_to_nid(pfn); | ||
56 | |||
57 | if (nid >= 0) | ||
58 | return (pfn < node_end_pfn(nid)); | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | #endif | ||
63 | #endif /* _PARISC_MMZONE_H */ | 7 | #endif /* _PARISC_MMZONE_H */ |
diff --git a/arch/parisc/include/asm/page.h b/arch/parisc/include/asm/page.h index b77f49ce6220..93caf17ac5e2 100644 --- a/arch/parisc/include/asm/page.h +++ b/arch/parisc/include/asm/page.h | |||
@@ -147,9 +147,9 @@ extern int npmem_ranges; | |||
147 | #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) | 147 | #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) |
148 | #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) | 148 | #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) |
149 | 149 | ||
150 | #ifndef CONFIG_DISCONTIGMEM | 150 | #ifndef CONFIG_SPARSEMEM |
151 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 151 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
152 | #endif /* CONFIG_DISCONTIGMEM */ | 152 | #endif |
153 | 153 | ||
154 | #ifdef CONFIG_HUGETLB_PAGE | 154 | #ifdef CONFIG_HUGETLB_PAGE |
155 | #define HPAGE_SHIFT PMD_SHIFT /* fixed for transparent huge pages */ | 155 | #define HPAGE_SHIFT PMD_SHIFT /* fixed for transparent huge pages */ |
diff --git a/arch/parisc/include/asm/patch.h b/arch/parisc/include/asm/patch.h new file mode 100644 index 000000000000..685b58a13968 --- /dev/null +++ b/arch/parisc/include/asm/patch.h | |||
@@ -0,0 +1,11 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef _PARISC_KERNEL_PATCH_H | ||
3 | #define _PARISC_KERNEL_PATCH_H | ||
4 | |||
5 | /* stop machine and patch kernel text */ | ||
6 | void patch_text(void *addr, unsigned int insn); | ||
7 | |||
8 | /* patch kernel text with machine already stopped (e.g. in kgdb) */ | ||
9 | void __patch_text(void *addr, unsigned int insn); | ||
10 | |||
11 | #endif | ||
diff --git a/arch/parisc/include/asm/pgalloc.h b/arch/parisc/include/asm/pgalloc.h index d05c678c77c4..ea75cc966dae 100644 --- a/arch/parisc/include/asm/pgalloc.h +++ b/arch/parisc/include/asm/pgalloc.h | |||
@@ -41,6 +41,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) | |||
41 | __pgd_val_set(*pgd, PxD_FLAG_ATTACHED); | 41 | __pgd_val_set(*pgd, PxD_FLAG_ATTACHED); |
42 | #endif | 42 | #endif |
43 | } | 43 | } |
44 | spin_lock_init(pgd_spinlock(actual_pgd)); | ||
44 | return actual_pgd; | 45 | return actual_pgd; |
45 | } | 46 | } |
46 | 47 | ||
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index c7bb74e22436..a39b079e73f2 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <asm/processor.h> | 17 | #include <asm/processor.h> |
18 | #include <asm/cache.h> | 18 | #include <asm/cache.h> |
19 | 19 | ||
20 | extern spinlock_t pa_tlb_lock; | 20 | static inline spinlock_t *pgd_spinlock(pgd_t *); |
21 | 21 | ||
22 | /* | 22 | /* |
23 | * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel | 23 | * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel |
@@ -34,16 +34,46 @@ extern spinlock_t pa_tlb_lock; | |||
34 | */ | 34 | */ |
35 | #define kern_addr_valid(addr) (1) | 35 | #define kern_addr_valid(addr) (1) |
36 | 36 | ||
37 | /* Purge data and instruction TLB entries. Must be called holding | 37 | /* This is for the serialization of PxTLB broadcasts. At least on the N class |
38 | * the pa_tlb_lock. The TLB purge instructions are slow on SMP | 38 | * systems, only one PxTLB inter processor broadcast can be active at any one |
39 | * machines since the purge must be broadcast to all CPUs. | 39 | * time on the Merced bus. |
40 | |||
41 | * PTE updates are protected by locks in the PMD. | ||
42 | */ | ||
43 | extern spinlock_t pa_tlb_flush_lock; | ||
44 | extern spinlock_t pa_swapper_pg_lock; | ||
45 | #if defined(CONFIG_64BIT) && defined(CONFIG_SMP) | ||
46 | extern int pa_serialize_tlb_flushes; | ||
47 | #else | ||
48 | #define pa_serialize_tlb_flushes (0) | ||
49 | #endif | ||
50 | |||
51 | #define purge_tlb_start(flags) do { \ | ||
52 | if (pa_serialize_tlb_flushes) \ | ||
53 | spin_lock_irqsave(&pa_tlb_flush_lock, flags); \ | ||
54 | else \ | ||
55 | local_irq_save(flags); \ | ||
56 | } while (0) | ||
57 | #define purge_tlb_end(flags) do { \ | ||
58 | if (pa_serialize_tlb_flushes) \ | ||
59 | spin_unlock_irqrestore(&pa_tlb_flush_lock, flags); \ | ||
60 | else \ | ||
61 | local_irq_restore(flags); \ | ||
62 | } while (0) | ||
63 | |||
64 | /* Purge data and instruction TLB entries. The TLB purge instructions | ||
65 | * are slow on SMP machines since the purge must be broadcast to all CPUs. | ||
40 | */ | 66 | */ |
41 | 67 | ||
42 | static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) | 68 | static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) |
43 | { | 69 | { |
70 | unsigned long flags; | ||
71 | |||
72 | purge_tlb_start(flags); | ||
44 | mtsp(mm->context, 1); | 73 | mtsp(mm->context, 1); |
45 | pdtlb(addr); | 74 | pdtlb(addr); |
46 | pitlb(addr); | 75 | pitlb(addr); |
76 | purge_tlb_end(flags); | ||
47 | } | 77 | } |
48 | 78 | ||
49 | /* Certain architectures need to do special things when PTEs | 79 | /* Certain architectures need to do special things when PTEs |
@@ -59,11 +89,11 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) | |||
59 | do { \ | 89 | do { \ |
60 | pte_t old_pte; \ | 90 | pte_t old_pte; \ |
61 | unsigned long flags; \ | 91 | unsigned long flags; \ |
62 | spin_lock_irqsave(&pa_tlb_lock, flags); \ | 92 | spin_lock_irqsave(pgd_spinlock((mm)->pgd), flags);\ |
63 | old_pte = *ptep; \ | 93 | old_pte = *ptep; \ |
64 | set_pte(ptep, pteval); \ | 94 | set_pte(ptep, pteval); \ |
65 | purge_tlb_entries(mm, addr); \ | 95 | purge_tlb_entries(mm, addr); \ |
66 | spin_unlock_irqrestore(&pa_tlb_lock, flags); \ | 96 | spin_unlock_irqrestore(pgd_spinlock((mm)->pgd), flags);\ |
67 | } while (0) | 97 | } while (0) |
68 | 98 | ||
69 | #endif /* !__ASSEMBLY__ */ | 99 | #endif /* !__ASSEMBLY__ */ |
@@ -88,10 +118,10 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) | |||
88 | #if CONFIG_PGTABLE_LEVELS == 3 | 118 | #if CONFIG_PGTABLE_LEVELS == 3 |
89 | #define PGD_ORDER 1 /* Number of pages per pgd */ | 119 | #define PGD_ORDER 1 /* Number of pages per pgd */ |
90 | #define PMD_ORDER 1 /* Number of pages per pmd */ | 120 | #define PMD_ORDER 1 /* Number of pages per pmd */ |
91 | #define PGD_ALLOC_ORDER 2 /* first pgd contains pmd */ | 121 | #define PGD_ALLOC_ORDER (2 + 1) /* first pgd contains pmd */ |
92 | #else | 122 | #else |
93 | #define PGD_ORDER 1 /* Number of pages per pgd */ | 123 | #define PGD_ORDER 1 /* Number of pages per pgd */ |
94 | #define PGD_ALLOC_ORDER PGD_ORDER | 124 | #define PGD_ALLOC_ORDER (PGD_ORDER + 1) |
95 | #endif | 125 | #endif |
96 | 126 | ||
97 | /* Definitions for 3rd level (we use PLD here for Page Lower directory | 127 | /* Definitions for 3rd level (we use PLD here for Page Lower directory |
@@ -459,6 +489,15 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); | |||
459 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) | 489 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) |
460 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) | 490 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) |
461 | 491 | ||
492 | |||
493 | static inline spinlock_t *pgd_spinlock(pgd_t *pgd) | ||
494 | { | ||
495 | if (unlikely(pgd == swapper_pg_dir)) | ||
496 | return &pa_swapper_pg_lock; | ||
497 | return (spinlock_t *)((char *)pgd + (PAGE_SIZE << (PGD_ALLOC_ORDER - 1))); | ||
498 | } | ||
499 | |||
500 | |||
462 | static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) | 501 | static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) |
463 | { | 502 | { |
464 | pte_t pte; | 503 | pte_t pte; |
@@ -467,15 +506,15 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned | |||
467 | if (!pte_young(*ptep)) | 506 | if (!pte_young(*ptep)) |
468 | return 0; | 507 | return 0; |
469 | 508 | ||
470 | spin_lock_irqsave(&pa_tlb_lock, flags); | 509 | spin_lock_irqsave(pgd_spinlock(vma->vm_mm->pgd), flags); |
471 | pte = *ptep; | 510 | pte = *ptep; |
472 | if (!pte_young(pte)) { | 511 | if (!pte_young(pte)) { |
473 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | 512 | spin_unlock_irqrestore(pgd_spinlock(vma->vm_mm->pgd), flags); |
474 | return 0; | 513 | return 0; |
475 | } | 514 | } |
476 | set_pte(ptep, pte_mkold(pte)); | 515 | set_pte(ptep, pte_mkold(pte)); |
477 | purge_tlb_entries(vma->vm_mm, addr); | 516 | purge_tlb_entries(vma->vm_mm, addr); |
478 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | 517 | spin_unlock_irqrestore(pgd_spinlock(vma->vm_mm->pgd), flags); |
479 | return 1; | 518 | return 1; |
480 | } | 519 | } |
481 | 520 | ||
@@ -485,11 +524,11 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
485 | pte_t old_pte; | 524 | pte_t old_pte; |
486 | unsigned long flags; | 525 | unsigned long flags; |
487 | 526 | ||
488 | spin_lock_irqsave(&pa_tlb_lock, flags); | 527 | spin_lock_irqsave(pgd_spinlock(mm->pgd), flags); |
489 | old_pte = *ptep; | 528 | old_pte = *ptep; |
490 | set_pte(ptep, __pte(0)); | 529 | set_pte(ptep, __pte(0)); |
491 | purge_tlb_entries(mm, addr); | 530 | purge_tlb_entries(mm, addr); |
492 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | 531 | spin_unlock_irqrestore(pgd_spinlock(mm->pgd), flags); |
493 | 532 | ||
494 | return old_pte; | 533 | return old_pte; |
495 | } | 534 | } |
@@ -497,10 +536,10 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
497 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 536 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
498 | { | 537 | { |
499 | unsigned long flags; | 538 | unsigned long flags; |
500 | spin_lock_irqsave(&pa_tlb_lock, flags); | 539 | spin_lock_irqsave(pgd_spinlock(mm->pgd), flags); |
501 | set_pte(ptep, pte_wrprotect(*ptep)); | 540 | set_pte(ptep, pte_wrprotect(*ptep)); |
502 | purge_tlb_entries(mm, addr); | 541 | purge_tlb_entries(mm, addr); |
503 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | 542 | spin_unlock_irqrestore(pgd_spinlock(mm->pgd), flags); |
504 | } | 543 | } |
505 | 544 | ||
506 | #define pte_same(A,B) (pte_val(A) == pte_val(B)) | 545 | #define pte_same(A,B) (pte_val(A) == pte_val(B)) |
diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h index 9ff033d261ab..143fb2a89dd8 100644 --- a/arch/parisc/include/asm/ptrace.h +++ b/arch/parisc/include/asm/ptrace.h | |||
@@ -37,4 +37,17 @@ extern int regs_query_register_offset(const char *name); | |||
37 | extern const char *regs_query_register_name(unsigned int offset); | 37 | extern const char *regs_query_register_name(unsigned int offset); |
38 | #define MAX_REG_OFFSET (offsetof(struct pt_regs, ipsw)) | 38 | #define MAX_REG_OFFSET (offsetof(struct pt_regs, ipsw)) |
39 | 39 | ||
40 | #define kernel_stack_pointer(regs) ((regs)->gr[30]) | ||
41 | |||
42 | static inline unsigned long regs_get_register(struct pt_regs *regs, | ||
43 | unsigned int offset) | ||
44 | { | ||
45 | if (unlikely(offset > MAX_REG_OFFSET)) | ||
46 | return 0; | ||
47 | return *(unsigned long *)((unsigned long)regs + offset); | ||
48 | } | ||
49 | |||
50 | unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n); | ||
51 | int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr); | ||
52 | |||
40 | #endif | 53 | #endif |
diff --git a/arch/parisc/include/asm/sparsemem.h b/arch/parisc/include/asm/sparsemem.h new file mode 100644 index 000000000000..b5c3a79045b4 --- /dev/null +++ b/arch/parisc/include/asm/sparsemem.h | |||
@@ -0,0 +1,14 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef ASM_PARISC_SPARSEMEM_H | ||
3 | #define ASM_PARISC_SPARSEMEM_H | ||
4 | |||
5 | /* We have these possible memory map layouts: | ||
6 | * Astro: 0-3.75, 67.75-68, 4-64 | ||
7 | * zx1: 0-1, 257-260, 4-256 | ||
8 | * Stretch (N-class): 0-2, 4-32, 34-xxx | ||
9 | */ | ||
10 | |||
11 | #define MAX_PHYSMEM_BITS 39 /* 512 GB */ | ||
12 | #define SECTION_SIZE_BITS 27 /* 128 MB */ | ||
13 | |||
14 | #endif | ||
diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h index 8a63515f03bf..197d2247e4db 100644 --- a/arch/parisc/include/asm/spinlock.h +++ b/arch/parisc/include/asm/spinlock.h | |||
@@ -37,7 +37,11 @@ static inline void arch_spin_unlock(arch_spinlock_t *x) | |||
37 | volatile unsigned int *a; | 37 | volatile unsigned int *a; |
38 | 38 | ||
39 | a = __ldcw_align(x); | 39 | a = __ldcw_align(x); |
40 | #ifdef CONFIG_SMP | ||
41 | (void) __ldcw(a); | ||
42 | #else | ||
40 | mb(); | 43 | mb(); |
44 | #endif | ||
41 | *a = 1; | 45 | *a = 1; |
42 | } | 46 | } |
43 | 47 | ||
diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h index 6804374efa66..c5ded01d45be 100644 --- a/arch/parisc/include/asm/tlbflush.h +++ b/arch/parisc/include/asm/tlbflush.h | |||
@@ -8,21 +8,6 @@ | |||
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include <asm/mmu_context.h> | 9 | #include <asm/mmu_context.h> |
10 | 10 | ||
11 | |||
12 | /* This is for the serialisation of PxTLB broadcasts. At least on the | ||
13 | * N class systems, only one PxTLB inter processor broadcast can be | ||
14 | * active at any one time on the Merced bus. This tlb purge | ||
15 | * synchronisation is fairly lightweight and harmless so we activate | ||
16 | * it on all systems not just the N class. | ||
17 | |||
18 | * It is also used to ensure PTE updates are atomic and consistent | ||
19 | * with the TLB. | ||
20 | */ | ||
21 | extern spinlock_t pa_tlb_lock; | ||
22 | |||
23 | #define purge_tlb_start(flags) spin_lock_irqsave(&pa_tlb_lock, flags) | ||
24 | #define purge_tlb_end(flags) spin_unlock_irqrestore(&pa_tlb_lock, flags) | ||
25 | |||
26 | extern void flush_tlb_all(void); | 11 | extern void flush_tlb_all(void); |
27 | extern void flush_tlb_all_local(void *); | 12 | extern void flush_tlb_all_local(void *); |
28 | 13 | ||
@@ -79,13 +64,6 @@ static inline void flush_tlb_mm(struct mm_struct *mm) | |||
79 | static inline void flush_tlb_page(struct vm_area_struct *vma, | 64 | static inline void flush_tlb_page(struct vm_area_struct *vma, |
80 | unsigned long addr) | 65 | unsigned long addr) |
81 | { | 66 | { |
82 | unsigned long flags, sid; | 67 | purge_tlb_entries(vma->vm_mm, addr); |
83 | |||
84 | sid = vma->vm_mm->context; | ||
85 | purge_tlb_start(flags); | ||
86 | mtsp(sid, 1); | ||
87 | pdtlb(addr); | ||
88 | pitlb(addr); | ||
89 | purge_tlb_end(flags); | ||
90 | } | 68 | } |
91 | #endif | 69 | #endif |
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index 8e5f1ab65c68..fc0df5c44468 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile | |||
@@ -9,7 +9,8 @@ obj-y := cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \ | |||
9 | pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ | 9 | pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ |
10 | ptrace.o hardware.o inventory.o drivers.o alternative.o \ | 10 | ptrace.o hardware.o inventory.o drivers.o alternative.o \ |
11 | signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \ | 11 | signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \ |
12 | process.o processor.o pdc_cons.o pdc_chassis.o unwind.o | 12 | process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \ |
13 | patch.o | ||
13 | 14 | ||
14 | ifdef CONFIG_FUNCTION_TRACER | 15 | ifdef CONFIG_FUNCTION_TRACER |
15 | # Do not profile debug and lowlevel utilities | 16 | # Do not profile debug and lowlevel utilities |
@@ -32,3 +33,6 @@ obj-$(CONFIG_64BIT) += perf.o perf_asm.o $(obj64-y) | |||
32 | obj-$(CONFIG_PARISC_CPU_TOPOLOGY) += topology.o | 33 | obj-$(CONFIG_PARISC_CPU_TOPOLOGY) += topology.o |
33 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o | 34 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o |
34 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | 35 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
36 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o | ||
37 | obj-$(CONFIG_KGDB) += kgdb.o | ||
38 | obj-$(CONFIG_KPROBES) += kprobes.o | ||
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 804880efa11e..0338561968a4 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c | |||
@@ -40,12 +40,19 @@ void purge_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); | |||
40 | void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr); | 40 | void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr); |
41 | 41 | ||
42 | 42 | ||
43 | /* On some machines (e.g. ones with the Merced bus), there can be | 43 | /* On some machines (i.e., ones with the Merced bus), there can be |
44 | * only a single PxTLB broadcast at a time; this must be guaranteed | 44 | * only a single PxTLB broadcast at a time; this must be guaranteed |
45 | * by software. We put a spinlock around all TLB flushes to | 45 | * by software. We need a spinlock around all TLB flushes to ensure |
46 | * ensure this. | 46 | * this. |
47 | */ | 47 | */ |
48 | DEFINE_SPINLOCK(pa_tlb_lock); | 48 | DEFINE_SPINLOCK(pa_tlb_flush_lock); |
49 | |||
50 | /* Swapper page setup lock. */ | ||
51 | DEFINE_SPINLOCK(pa_swapper_pg_lock); | ||
52 | |||
53 | #if defined(CONFIG_64BIT) && defined(CONFIG_SMP) | ||
54 | int pa_serialize_tlb_flushes __read_mostly; | ||
55 | #endif | ||
49 | 56 | ||
50 | struct pdc_cache_info cache_info __read_mostly; | 57 | struct pdc_cache_info cache_info __read_mostly; |
51 | #ifndef CONFIG_PA20 | 58 | #ifndef CONFIG_PA20 |
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index 5eb979d04b90..15e7b3be7b6b 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/io.h> | 38 | #include <asm/io.h> |
39 | #include <asm/pdc.h> | 39 | #include <asm/pdc.h> |
40 | #include <asm/parisc-device.h> | 40 | #include <asm/parisc-device.h> |
41 | #include <asm/ropes.h> | ||
41 | 42 | ||
42 | /* See comments in include/asm-parisc/pci.h */ | 43 | /* See comments in include/asm-parisc/pci.h */ |
43 | const struct dma_map_ops *hppa_dma_ops __read_mostly; | 44 | const struct dma_map_ops *hppa_dma_ops __read_mostly; |
@@ -257,6 +258,30 @@ static struct parisc_device *find_device_by_addr(unsigned long hpa) | |||
257 | return ret ? d.dev : NULL; | 258 | return ret ? d.dev : NULL; |
258 | } | 259 | } |
259 | 260 | ||
261 | static int __init is_IKE_device(struct device *dev, void *data) | ||
262 | { | ||
263 | struct parisc_device *pdev = to_parisc_device(dev); | ||
264 | |||
265 | if (!check_dev(dev)) | ||
266 | return 0; | ||
267 | if (pdev->id.hw_type != HPHW_BCPORT) | ||
268 | return 0; | ||
269 | if (IS_IKE(pdev) || | ||
270 | (pdev->id.hversion == REO_MERCED_PORT) || | ||
271 | (pdev->id.hversion == REOG_MERCED_PORT)) { | ||
272 | return 1; | ||
273 | } | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | int __init machine_has_merced_bus(void) | ||
278 | { | ||
279 | int ret; | ||
280 | |||
281 | ret = for_each_padev(is_IKE_device, NULL); | ||
282 | return ret ? 1 : 0; | ||
283 | } | ||
284 | |||
260 | /** | 285 | /** |
261 | * find_pa_parent_type - Find a parent of a specific type | 286 | * find_pa_parent_type - Find a parent of a specific type |
262 | * @dev: The device to start searching from | 287 | * @dev: The device to start searching from |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index d5eb19efa65b..a1fc04570ade 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -50,12 +50,8 @@ | |||
50 | 50 | ||
51 | .import pa_tlb_lock,data | 51 | .import pa_tlb_lock,data |
52 | .macro load_pa_tlb_lock reg | 52 | .macro load_pa_tlb_lock reg |
53 | #if __PA_LDCW_ALIGNMENT > 4 | 53 | mfctl %cr25,\reg |
54 | load32 PA(pa_tlb_lock) + __PA_LDCW_ALIGNMENT-1, \reg | 54 | addil L%(PAGE_SIZE << (PGD_ALLOC_ORDER - 1)),\reg |
55 | depi 0,31,__PA_LDCW_ALIGN_ORDER, \reg | ||
56 | #else | ||
57 | load32 PA(pa_tlb_lock), \reg | ||
58 | #endif | ||
59 | .endm | 55 | .endm |
60 | 56 | ||
61 | /* space_to_prot macro creates a prot id from a space id */ | 57 | /* space_to_prot macro creates a prot id from a space id */ |
@@ -471,8 +467,9 @@ | |||
471 | nop | 467 | nop |
472 | LDREG 0(\ptp),\pte | 468 | LDREG 0(\ptp),\pte |
473 | bb,<,n \pte,_PAGE_PRESENT_BIT,3f | 469 | bb,<,n \pte,_PAGE_PRESENT_BIT,3f |
470 | LDCW 0(\tmp),\tmp1 | ||
474 | b \fault | 471 | b \fault |
475 | stw,ma \spc,0(\tmp) | 472 | stw \spc,0(\tmp) |
476 | 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) | 473 | 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) |
477 | #endif | 474 | #endif |
478 | 2: LDREG 0(\ptp),\pte | 475 | 2: LDREG 0(\ptp),\pte |
@@ -481,20 +478,22 @@ | |||
481 | .endm | 478 | .endm |
482 | 479 | ||
483 | /* Release pa_tlb_lock lock without reloading lock address. */ | 480 | /* Release pa_tlb_lock lock without reloading lock address. */ |
484 | .macro tlb_unlock0 spc,tmp | 481 | .macro tlb_unlock0 spc,tmp,tmp1 |
485 | #ifdef CONFIG_SMP | 482 | #ifdef CONFIG_SMP |
486 | 98: or,COND(=) %r0,\spc,%r0 | 483 | 98: or,COND(=) %r0,\spc,%r0 |
487 | stw,ma \spc,0(\tmp) | 484 | LDCW 0(\tmp),\tmp1 |
485 | or,COND(=) %r0,\spc,%r0 | ||
486 | stw \spc,0(\tmp) | ||
488 | 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) | 487 | 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) |
489 | #endif | 488 | #endif |
490 | .endm | 489 | .endm |
491 | 490 | ||
492 | /* Release pa_tlb_lock lock. */ | 491 | /* Release pa_tlb_lock lock. */ |
493 | .macro tlb_unlock1 spc,tmp | 492 | .macro tlb_unlock1 spc,tmp,tmp1 |
494 | #ifdef CONFIG_SMP | 493 | #ifdef CONFIG_SMP |
495 | 98: load_pa_tlb_lock \tmp | 494 | 98: load_pa_tlb_lock \tmp |
496 | 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) | 495 | 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) |
497 | tlb_unlock0 \spc,\tmp | 496 | tlb_unlock0 \spc,\tmp,\tmp1 |
498 | #endif | 497 | #endif |
499 | .endm | 498 | .endm |
500 | 499 | ||
@@ -1177,7 +1176,7 @@ dtlb_miss_20w: | |||
1177 | 1176 | ||
1178 | idtlbt pte,prot | 1177 | idtlbt pte,prot |
1179 | 1178 | ||
1180 | tlb_unlock1 spc,t0 | 1179 | tlb_unlock1 spc,t0,t1 |
1181 | rfir | 1180 | rfir |
1182 | nop | 1181 | nop |
1183 | 1182 | ||
@@ -1203,7 +1202,7 @@ nadtlb_miss_20w: | |||
1203 | 1202 | ||
1204 | idtlbt pte,prot | 1203 | idtlbt pte,prot |
1205 | 1204 | ||
1206 | tlb_unlock1 spc,t0 | 1205 | tlb_unlock1 spc,t0,t1 |
1207 | rfir | 1206 | rfir |
1208 | nop | 1207 | nop |
1209 | 1208 | ||
@@ -1237,7 +1236,7 @@ dtlb_miss_11: | |||
1237 | 1236 | ||
1238 | mtsp t1, %sr1 /* Restore sr1 */ | 1237 | mtsp t1, %sr1 /* Restore sr1 */ |
1239 | 1238 | ||
1240 | tlb_unlock1 spc,t0 | 1239 | tlb_unlock1 spc,t0,t1 |
1241 | rfir | 1240 | rfir |
1242 | nop | 1241 | nop |
1243 | 1242 | ||
@@ -1270,7 +1269,7 @@ nadtlb_miss_11: | |||
1270 | 1269 | ||
1271 | mtsp t1, %sr1 /* Restore sr1 */ | 1270 | mtsp t1, %sr1 /* Restore sr1 */ |
1272 | 1271 | ||
1273 | tlb_unlock1 spc,t0 | 1272 | tlb_unlock1 spc,t0,t1 |
1274 | rfir | 1273 | rfir |
1275 | nop | 1274 | nop |
1276 | 1275 | ||
@@ -1299,7 +1298,7 @@ dtlb_miss_20: | |||
1299 | 1298 | ||
1300 | idtlbt pte,prot | 1299 | idtlbt pte,prot |
1301 | 1300 | ||
1302 | tlb_unlock1 spc,t0 | 1301 | tlb_unlock1 spc,t0,t1 |
1303 | rfir | 1302 | rfir |
1304 | nop | 1303 | nop |
1305 | 1304 | ||
@@ -1327,7 +1326,7 @@ nadtlb_miss_20: | |||
1327 | 1326 | ||
1328 | idtlbt pte,prot | 1327 | idtlbt pte,prot |
1329 | 1328 | ||
1330 | tlb_unlock1 spc,t0 | 1329 | tlb_unlock1 spc,t0,t1 |
1331 | rfir | 1330 | rfir |
1332 | nop | 1331 | nop |
1333 | 1332 | ||
@@ -1434,7 +1433,7 @@ itlb_miss_20w: | |||
1434 | 1433 | ||
1435 | iitlbt pte,prot | 1434 | iitlbt pte,prot |
1436 | 1435 | ||
1437 | tlb_unlock1 spc,t0 | 1436 | tlb_unlock1 spc,t0,t1 |
1438 | rfir | 1437 | rfir |
1439 | nop | 1438 | nop |
1440 | 1439 | ||
@@ -1458,7 +1457,7 @@ naitlb_miss_20w: | |||
1458 | 1457 | ||
1459 | iitlbt pte,prot | 1458 | iitlbt pte,prot |
1460 | 1459 | ||
1461 | tlb_unlock1 spc,t0 | 1460 | tlb_unlock1 spc,t0,t1 |
1462 | rfir | 1461 | rfir |
1463 | nop | 1462 | nop |
1464 | 1463 | ||
@@ -1492,7 +1491,7 @@ itlb_miss_11: | |||
1492 | 1491 | ||
1493 | mtsp t1, %sr1 /* Restore sr1 */ | 1492 | mtsp t1, %sr1 /* Restore sr1 */ |
1494 | 1493 | ||
1495 | tlb_unlock1 spc,t0 | 1494 | tlb_unlock1 spc,t0,t1 |
1496 | rfir | 1495 | rfir |
1497 | nop | 1496 | nop |
1498 | 1497 | ||
@@ -1516,7 +1515,7 @@ naitlb_miss_11: | |||
1516 | 1515 | ||
1517 | mtsp t1, %sr1 /* Restore sr1 */ | 1516 | mtsp t1, %sr1 /* Restore sr1 */ |
1518 | 1517 | ||
1519 | tlb_unlock1 spc,t0 | 1518 | tlb_unlock1 spc,t0,t1 |
1520 | rfir | 1519 | rfir |
1521 | nop | 1520 | nop |
1522 | 1521 | ||
@@ -1546,7 +1545,7 @@ itlb_miss_20: | |||
1546 | 1545 | ||
1547 | iitlbt pte,prot | 1546 | iitlbt pte,prot |
1548 | 1547 | ||
1549 | tlb_unlock1 spc,t0 | 1548 | tlb_unlock1 spc,t0,t1 |
1550 | rfir | 1549 | rfir |
1551 | nop | 1550 | nop |
1552 | 1551 | ||
@@ -1566,7 +1565,7 @@ naitlb_miss_20: | |||
1566 | 1565 | ||
1567 | iitlbt pte,prot | 1566 | iitlbt pte,prot |
1568 | 1567 | ||
1569 | tlb_unlock1 spc,t0 | 1568 | tlb_unlock1 spc,t0,t1 |
1570 | rfir | 1569 | rfir |
1571 | nop | 1570 | nop |
1572 | 1571 | ||
@@ -1596,7 +1595,7 @@ dbit_trap_20w: | |||
1596 | 1595 | ||
1597 | idtlbt pte,prot | 1596 | idtlbt pte,prot |
1598 | 1597 | ||
1599 | tlb_unlock0 spc,t0 | 1598 | tlb_unlock0 spc,t0,t1 |
1600 | rfir | 1599 | rfir |
1601 | nop | 1600 | nop |
1602 | #else | 1601 | #else |
@@ -1622,7 +1621,7 @@ dbit_trap_11: | |||
1622 | 1621 | ||
1623 | mtsp t1, %sr1 /* Restore sr1 */ | 1622 | mtsp t1, %sr1 /* Restore sr1 */ |
1624 | 1623 | ||
1625 | tlb_unlock0 spc,t0 | 1624 | tlb_unlock0 spc,t0,t1 |
1626 | rfir | 1625 | rfir |
1627 | nop | 1626 | nop |
1628 | 1627 | ||
@@ -1642,7 +1641,7 @@ dbit_trap_20: | |||
1642 | 1641 | ||
1643 | idtlbt pte,prot | 1642 | idtlbt pte,prot |
1644 | 1643 | ||
1645 | tlb_unlock0 spc,t0 | 1644 | tlb_unlock0 spc,t0,t1 |
1646 | rfir | 1645 | rfir |
1647 | nop | 1646 | nop |
1648 | #endif | 1647 | #endif |
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index fbb4e43fda05..d12de2a13753 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/linkage.h> | 22 | #include <linux/linkage.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | 24 | ||
25 | .level LEVEL | 25 | .level PA_ASM_LEVEL |
26 | 26 | ||
27 | __INITDATA | 27 | __INITDATA |
28 | ENTRY(boot_args) | 28 | ENTRY(boot_args) |
@@ -258,7 +258,7 @@ stext_pdc_ret: | |||
258 | ldo R%PA(fault_vector_11)(%r10),%r10 | 258 | ldo R%PA(fault_vector_11)(%r10),%r10 |
259 | 259 | ||
260 | $is_pa20: | 260 | $is_pa20: |
261 | .level LEVEL /* restore 1.1 || 2.0w */ | 261 | .level PA_ASM_LEVEL /* restore 1.1 || 2.0w */ |
262 | #endif /*!CONFIG_64BIT*/ | 262 | #endif /*!CONFIG_64BIT*/ |
263 | load32 PA(fault_vector_20),%r10 | 263 | load32 PA(fault_vector_20),%r10 |
264 | 264 | ||
@@ -329,6 +329,19 @@ smp_slave_stext: | |||
329 | mtsp %r0,%sr6 | 329 | mtsp %r0,%sr6 |
330 | mtsp %r0,%sr7 | 330 | mtsp %r0,%sr7 |
331 | 331 | ||
332 | #ifdef CONFIG_64BIT | ||
333 | /* | ||
334 | * Enable Wide mode early, in case the task_struct for the idle | ||
335 | * task in smp_init_current_idle_task was allocated above 4GB. | ||
336 | */ | ||
337 | 1: mfia %rp /* clear upper part of pcoq */ | ||
338 | ldo 2f-1b(%rp),%rp | ||
339 | depdi 0,31,32,%rp | ||
340 | bv (%rp) | ||
341 | ssm PSW_SM_W,%r0 | ||
342 | 2: | ||
343 | #endif | ||
344 | |||
332 | /* Initialize the SP - monarch sets up smp_init_current_idle_task */ | 345 | /* Initialize the SP - monarch sets up smp_init_current_idle_task */ |
333 | load32 PA(smp_init_current_idle_task),%sp | 346 | load32 PA(smp_init_current_idle_task),%sp |
334 | LDREG 0(%sp),%sp /* load task address */ | 347 | LDREG 0(%sp),%sp /* load task address */ |
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index 35d05fdd7483..6f2d611347a1 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/processor.h> | 31 | #include <asm/processor.h> |
32 | #include <asm/page.h> | 32 | #include <asm/page.h> |
33 | #include <asm/parisc-device.h> | 33 | #include <asm/parisc-device.h> |
34 | #include <asm/tlbflush.h> | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | ** Debug options | 37 | ** Debug options |
@@ -638,4 +639,10 @@ void __init do_device_inventory(void) | |||
638 | } | 639 | } |
639 | printk(KERN_INFO "Found devices:\n"); | 640 | printk(KERN_INFO "Found devices:\n"); |
640 | print_parisc_devices(); | 641 | print_parisc_devices(); |
642 | |||
643 | #if defined(CONFIG_64BIT) && defined(CONFIG_SMP) | ||
644 | pa_serialize_tlb_flushes = machine_has_merced_bus(); | ||
645 | if (pa_serialize_tlb_flushes) | ||
646 | pr_info("Merced bus found: Enable PxTLB serialization.\n"); | ||
647 | #endif | ||
641 | } | 648 | } |
diff --git a/arch/parisc/kernel/jump_label.c b/arch/parisc/kernel/jump_label.c new file mode 100644 index 000000000000..d2f3cb12e282 --- /dev/null +++ b/arch/parisc/kernel/jump_label.c | |||
@@ -0,0 +1,55 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright (C) 2019 Helge Deller <deller@gmx.de> | ||
4 | * | ||
5 | * Based on arch/arm64/kernel/jump_label.c | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/jump_label.h> | ||
9 | #include <linux/bug.h> | ||
10 | #include <asm/alternative.h> | ||
11 | #include <asm/patch.h> | ||
12 | |||
13 | static inline int reassemble_17(int as17) | ||
14 | { | ||
15 | return (((as17 & 0x10000) >> 16) | | ||
16 | ((as17 & 0x0f800) << 5) | | ||
17 | ((as17 & 0x00400) >> 8) | | ||
18 | ((as17 & 0x003ff) << 3)); | ||
19 | } | ||
20 | |||
21 | void arch_jump_label_transform(struct jump_entry *entry, | ||
22 | enum jump_label_type type) | ||
23 | { | ||
24 | void *addr = (void *)jump_entry_code(entry); | ||
25 | u32 insn; | ||
26 | |||
27 | if (type == JUMP_LABEL_JMP) { | ||
28 | void *target = (void *)jump_entry_target(entry); | ||
29 | int distance = target - addr; | ||
30 | /* | ||
31 | * Encode the PA1.1 "b,n" instruction with a 17-bit | ||
32 | * displacement. In case we hit the BUG(), we could use | ||
33 | * another branch instruction with a 22-bit displacement on | ||
34 | * 64-bit CPUs instead. But this seems sufficient for now. | ||
35 | */ | ||
36 | distance -= 8; | ||
37 | BUG_ON(distance > 262143 || distance < -262144); | ||
38 | insn = 0xe8000002 | reassemble_17(distance >> 2); | ||
39 | } else { | ||
40 | insn = INSN_NOP; | ||
41 | } | ||
42 | |||
43 | patch_text(addr, insn); | ||
44 | } | ||
45 | |||
46 | void arch_jump_label_transform_static(struct jump_entry *entry, | ||
47 | enum jump_label_type type) | ||
48 | { | ||
49 | /* | ||
50 | * We use the architected NOP in arch_static_branch, so there's no | ||
51 | * need to patch an identical NOP over the top of it here. The core | ||
52 | * will call arch_jump_label_transform from a module notifier if the | ||
53 | * NOP needs to be replaced by a branch. | ||
54 | */ | ||
55 | } | ||
diff --git a/arch/parisc/kernel/kgdb.c b/arch/parisc/kernel/kgdb.c new file mode 100644 index 000000000000..664278db9b97 --- /dev/null +++ b/arch/parisc/kernel/kgdb.c | |||
@@ -0,0 +1,209 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * PA-RISC KGDB support | ||
4 | * | ||
5 | * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/kgdb.h> | ||
10 | #include <linux/string.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/notifier.h> | ||
13 | #include <linux/kdebug.h> | ||
14 | #include <linux/uaccess.h> | ||
15 | #include <asm/ptrace.h> | ||
16 | #include <asm/traps.h> | ||
17 | #include <asm/processor.h> | ||
18 | #include <asm/patch.h> | ||
19 | #include <asm/cacheflush.h> | ||
20 | |||
21 | const struct kgdb_arch arch_kgdb_ops = { | ||
22 | .gdb_bpt_instr = { 0x03, 0xff, 0xa0, 0x1f } | ||
23 | }; | ||
24 | |||
25 | static int __kgdb_notify(struct die_args *args, unsigned long cmd) | ||
26 | { | ||
27 | struct pt_regs *regs = args->regs; | ||
28 | |||
29 | if (kgdb_handle_exception(1, args->signr, cmd, regs)) | ||
30 | return NOTIFY_DONE; | ||
31 | return NOTIFY_STOP; | ||
32 | } | ||
33 | |||
34 | static int kgdb_notify(struct notifier_block *self, | ||
35 | unsigned long cmd, void *ptr) | ||
36 | { | ||
37 | unsigned long flags; | ||
38 | int ret; | ||
39 | |||
40 | local_irq_save(flags); | ||
41 | ret = __kgdb_notify(ptr, cmd); | ||
42 | local_irq_restore(flags); | ||
43 | |||
44 | return ret; | ||
45 | } | ||
46 | |||
47 | static struct notifier_block kgdb_notifier = { | ||
48 | .notifier_call = kgdb_notify, | ||
49 | .priority = -INT_MAX, | ||
50 | }; | ||
51 | |||
52 | int kgdb_arch_init(void) | ||
53 | { | ||
54 | return register_die_notifier(&kgdb_notifier); | ||
55 | } | ||
56 | |||
57 | void kgdb_arch_exit(void) | ||
58 | { | ||
59 | unregister_die_notifier(&kgdb_notifier); | ||
60 | } | ||
61 | |||
62 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
63 | { | ||
64 | struct parisc_gdb_regs *gr = (struct parisc_gdb_regs *)gdb_regs; | ||
65 | |||
66 | memset(gr, 0, sizeof(struct parisc_gdb_regs)); | ||
67 | |||
68 | memcpy(gr->gpr, regs->gr, sizeof(gr->gpr)); | ||
69 | memcpy(gr->fr, regs->fr, sizeof(gr->fr)); | ||
70 | |||
71 | gr->sr0 = regs->sr[0]; | ||
72 | gr->sr1 = regs->sr[1]; | ||
73 | gr->sr2 = regs->sr[2]; | ||
74 | gr->sr3 = regs->sr[3]; | ||
75 | gr->sr4 = regs->sr[4]; | ||
76 | gr->sr5 = regs->sr[5]; | ||
77 | gr->sr6 = regs->sr[6]; | ||
78 | gr->sr7 = regs->sr[7]; | ||
79 | |||
80 | gr->sar = regs->sar; | ||
81 | gr->iir = regs->iir; | ||
82 | gr->isr = regs->isr; | ||
83 | gr->ior = regs->ior; | ||
84 | gr->ipsw = regs->ipsw; | ||
85 | gr->cr27 = regs->cr27; | ||
86 | |||
87 | gr->iaoq_f = regs->iaoq[0]; | ||
88 | gr->iasq_f = regs->iasq[0]; | ||
89 | |||
90 | gr->iaoq_b = regs->iaoq[1]; | ||
91 | gr->iasq_b = regs->iasq[1]; | ||
92 | } | ||
93 | |||
94 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
95 | { | ||
96 | struct parisc_gdb_regs *gr = (struct parisc_gdb_regs *)gdb_regs; | ||
97 | |||
98 | |||
99 | memcpy(regs->gr, gr->gpr, sizeof(regs->gr)); | ||
100 | memcpy(regs->fr, gr->fr, sizeof(regs->fr)); | ||
101 | |||
102 | regs->sr[0] = gr->sr0; | ||
103 | regs->sr[1] = gr->sr1; | ||
104 | regs->sr[2] = gr->sr2; | ||
105 | regs->sr[3] = gr->sr3; | ||
106 | regs->sr[4] = gr->sr4; | ||
107 | regs->sr[5] = gr->sr5; | ||
108 | regs->sr[6] = gr->sr6; | ||
109 | regs->sr[7] = gr->sr7; | ||
110 | |||
111 | regs->sar = gr->sar; | ||
112 | regs->iir = gr->iir; | ||
113 | regs->isr = gr->isr; | ||
114 | regs->ior = gr->ior; | ||
115 | regs->ipsw = gr->ipsw; | ||
116 | regs->cr27 = gr->cr27; | ||
117 | |||
118 | regs->iaoq[0] = gr->iaoq_f; | ||
119 | regs->iasq[0] = gr->iasq_f; | ||
120 | |||
121 | regs->iaoq[1] = gr->iaoq_b; | ||
122 | regs->iasq[1] = gr->iasq_b; | ||
123 | } | ||
124 | |||
125 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, | ||
126 | struct task_struct *task) | ||
127 | { | ||
128 | struct pt_regs *regs = task_pt_regs(task); | ||
129 | unsigned long gr30, iaoq; | ||
130 | |||
131 | gr30 = regs->gr[30]; | ||
132 | iaoq = regs->iaoq[0]; | ||
133 | |||
134 | regs->gr[30] = regs->ksp; | ||
135 | regs->iaoq[0] = regs->kpc; | ||
136 | pt_regs_to_gdb_regs(gdb_regs, regs); | ||
137 | |||
138 | regs->gr[30] = gr30; | ||
139 | regs->iaoq[0] = iaoq; | ||
140 | |||
141 | } | ||
142 | |||
143 | static void step_instruction_queue(struct pt_regs *regs) | ||
144 | { | ||
145 | regs->iaoq[0] = regs->iaoq[1]; | ||
146 | regs->iaoq[1] += 4; | ||
147 | } | ||
148 | |||
149 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) | ||
150 | { | ||
151 | regs->iaoq[0] = ip; | ||
152 | regs->iaoq[1] = ip + 4; | ||
153 | } | ||
154 | |||
155 | int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) | ||
156 | { | ||
157 | int ret = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, | ||
158 | BREAK_INSTR_SIZE); | ||
159 | if (ret) | ||
160 | return ret; | ||
161 | |||
162 | __patch_text((void *)bpt->bpt_addr, | ||
163 | *(unsigned int *)&arch_kgdb_ops.gdb_bpt_instr); | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) | ||
168 | { | ||
169 | __patch_text((void *)bpt->bpt_addr, *(unsigned int *)&bpt->saved_instr); | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | int kgdb_arch_handle_exception(int trap, int signo, | ||
174 | int err_code, char *inbuf, char *outbuf, | ||
175 | struct pt_regs *regs) | ||
176 | { | ||
177 | unsigned long addr; | ||
178 | char *p = inbuf + 1; | ||
179 | |||
180 | switch (inbuf[0]) { | ||
181 | case 'D': | ||
182 | case 'c': | ||
183 | case 'k': | ||
184 | kgdb_contthread = NULL; | ||
185 | kgdb_single_step = 0; | ||
186 | |||
187 | if (kgdb_hex2long(&p, &addr)) | ||
188 | kgdb_arch_set_pc(regs, addr); | ||
189 | else if (trap == 9 && regs->iir == | ||
190 | PARISC_KGDB_COMPILED_BREAK_INSN) | ||
191 | step_instruction_queue(regs); | ||
192 | return 0; | ||
193 | case 's': | ||
194 | kgdb_single_step = 1; | ||
195 | if (kgdb_hex2long(&p, &addr)) { | ||
196 | kgdb_arch_set_pc(regs, addr); | ||
197 | } else if (trap == 9 && regs->iir == | ||
198 | PARISC_KGDB_COMPILED_BREAK_INSN) { | ||
199 | step_instruction_queue(regs); | ||
200 | mtctl(-1, 0); | ||
201 | } else { | ||
202 | mtctl(0, 0); | ||
203 | } | ||
204 | regs->gr[0] |= PSW_R; | ||
205 | return 0; | ||
206 | |||
207 | } | ||
208 | return -1; | ||
209 | } | ||
diff --git a/arch/parisc/kernel/kprobes.c b/arch/parisc/kernel/kprobes.c new file mode 100644 index 000000000000..d58960b33bda --- /dev/null +++ b/arch/parisc/kernel/kprobes.c | |||
@@ -0,0 +1,291 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * arch/parisc/kernel/kprobes.c | ||
4 | * | ||
5 | * PA-RISC kprobes implementation | ||
6 | * | ||
7 | * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> | ||
8 | */ | ||
9 | |||
10 | #include <linux/types.h> | ||
11 | #include <linux/kprobes.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <asm/cacheflush.h> | ||
14 | #include <asm/patch.h> | ||
15 | |||
16 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | ||
17 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | ||
18 | |||
19 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | ||
20 | { | ||
21 | if ((unsigned long)p->addr & 3UL) | ||
22 | return -EINVAL; | ||
23 | |||
24 | p->ainsn.insn = get_insn_slot(); | ||
25 | if (!p->ainsn.insn) | ||
26 | return -ENOMEM; | ||
27 | |||
28 | memcpy(p->ainsn.insn, p->addr, | ||
29 | MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); | ||
30 | p->opcode = *p->addr; | ||
31 | flush_insn_slot(p); | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | void __kprobes arch_remove_kprobe(struct kprobe *p) | ||
36 | { | ||
37 | if (!p->ainsn.insn) | ||
38 | return; | ||
39 | |||
40 | free_insn_slot(p->ainsn.insn, 0); | ||
41 | p->ainsn.insn = NULL; | ||
42 | } | ||
43 | |||
44 | void __kprobes arch_arm_kprobe(struct kprobe *p) | ||
45 | { | ||
46 | patch_text(p->addr, PARISC_KPROBES_BREAK_INSN); | ||
47 | } | ||
48 | |||
49 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | ||
50 | { | ||
51 | patch_text(p->addr, p->opcode); | ||
52 | } | ||
53 | |||
54 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) | ||
55 | { | ||
56 | kcb->prev_kprobe.kp = kprobe_running(); | ||
57 | kcb->prev_kprobe.status = kcb->kprobe_status; | ||
58 | } | ||
59 | |||
60 | static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) | ||
61 | { | ||
62 | __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); | ||
63 | kcb->kprobe_status = kcb->prev_kprobe.status; | ||
64 | } | ||
65 | |||
66 | static inline void __kprobes set_current_kprobe(struct kprobe *p) | ||
67 | { | ||
68 | __this_cpu_write(current_kprobe, p); | ||
69 | } | ||
70 | |||
71 | static void __kprobes setup_singlestep(struct kprobe *p, | ||
72 | struct kprobe_ctlblk *kcb, struct pt_regs *regs) | ||
73 | { | ||
74 | kcb->iaoq[0] = regs->iaoq[0]; | ||
75 | kcb->iaoq[1] = regs->iaoq[1]; | ||
76 | regs->iaoq[0] = (unsigned long)p->ainsn.insn; | ||
77 | mtctl(0, 0); | ||
78 | regs->gr[0] |= PSW_R; | ||
79 | } | ||
80 | |||
81 | int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs) | ||
82 | { | ||
83 | struct kprobe *p; | ||
84 | struct kprobe_ctlblk *kcb; | ||
85 | |||
86 | preempt_disable(); | ||
87 | |||
88 | kcb = get_kprobe_ctlblk(); | ||
89 | p = get_kprobe((unsigned long *)regs->iaoq[0]); | ||
90 | |||
91 | if (!p) { | ||
92 | preempt_enable_no_resched(); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | if (kprobe_running()) { | ||
97 | /* | ||
98 | * We have reentered the kprobe_handler, since another kprobe | ||
99 | * was hit while within the handler, we save the original | ||
100 | * kprobes and single step on the instruction of the new probe | ||
101 | * without calling any user handlers to avoid recursive | ||
102 | * kprobes. | ||
103 | */ | ||
104 | save_previous_kprobe(kcb); | ||
105 | set_current_kprobe(p); | ||
106 | kprobes_inc_nmissed_count(p); | ||
107 | setup_singlestep(p, kcb, regs); | ||
108 | kcb->kprobe_status = KPROBE_REENTER; | ||
109 | return 1; | ||
110 | } | ||
111 | |||
112 | set_current_kprobe(p); | ||
113 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | ||
114 | |||
115 | /* If we have no pre-handler or it returned 0, we continue with | ||
116 | * normal processing. If we have a pre-handler and it returned | ||
117 | * non-zero - which means user handler setup registers to exit | ||
118 | * to another instruction, we must skip the single stepping. | ||
119 | */ | ||
120 | |||
121 | if (!p->pre_handler || !p->pre_handler(p, regs)) { | ||
122 | setup_singlestep(p, kcb, regs); | ||
123 | kcb->kprobe_status = KPROBE_HIT_SS; | ||
124 | } else { | ||
125 | reset_current_kprobe(); | ||
126 | preempt_enable_no_resched(); | ||
127 | } | ||
128 | return 1; | ||
129 | } | ||
130 | |||
131 | int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs) | ||
132 | { | ||
133 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | ||
134 | struct kprobe *p = kprobe_running(); | ||
135 | |||
136 | if (regs->iaoq[0] != (unsigned long)p->ainsn.insn+4) | ||
137 | return 0; | ||
138 | |||
139 | /* restore back original saved kprobe variables and continue */ | ||
140 | if (kcb->kprobe_status == KPROBE_REENTER) { | ||
141 | restore_previous_kprobe(kcb); | ||
142 | return 1; | ||
143 | } | ||
144 | |||
145 | /* for absolute branch instructions we can copy iaoq_b. for relative | ||
146 | * branch instructions we need to calculate the new address based on the | ||
147 | * difference between iaoq_f and iaoq_b. We cannot use iaoq_b without | ||
148 | * modificationt because it's based on our ainsn.insn address. | ||
149 | */ | ||
150 | |||
151 | if (p->post_handler) | ||
152 | p->post_handler(p, regs, 0); | ||
153 | |||
154 | switch (regs->iir >> 26) { | ||
155 | case 0x38: /* BE */ | ||
156 | case 0x39: /* BE,L */ | ||
157 | case 0x3a: /* BV */ | ||
158 | case 0x3b: /* BVE */ | ||
159 | /* for absolute branches, regs->iaoq[1] has already the right | ||
160 | * address | ||
161 | */ | ||
162 | regs->iaoq[0] = kcb->iaoq[1]; | ||
163 | break; | ||
164 | default: | ||
165 | regs->iaoq[1] = kcb->iaoq[0]; | ||
166 | regs->iaoq[1] += (regs->iaoq[1] - regs->iaoq[0]) + 4; | ||
167 | regs->iaoq[0] = kcb->iaoq[1]; | ||
168 | break; | ||
169 | } | ||
170 | kcb->kprobe_status = KPROBE_HIT_SSDONE; | ||
171 | reset_current_kprobe(); | ||
172 | return 1; | ||
173 | } | ||
174 | |||
175 | static inline void kretprobe_trampoline(void) | ||
176 | { | ||
177 | asm volatile("nop"); | ||
178 | asm volatile("nop"); | ||
179 | } | ||
180 | |||
181 | static int __kprobes trampoline_probe_handler(struct kprobe *p, | ||
182 | struct pt_regs *regs); | ||
183 | |||
184 | static struct kprobe trampoline_p = { | ||
185 | .pre_handler = trampoline_probe_handler | ||
186 | }; | ||
187 | |||
188 | static int __kprobes trampoline_probe_handler(struct kprobe *p, | ||
189 | struct pt_regs *regs) | ||
190 | { | ||
191 | struct kretprobe_instance *ri = NULL; | ||
192 | struct hlist_head *head, empty_rp; | ||
193 | struct hlist_node *tmp; | ||
194 | unsigned long flags, orig_ret_address = 0; | ||
195 | unsigned long trampoline_address = (unsigned long)trampoline_p.addr; | ||
196 | kprobe_opcode_t *correct_ret_addr = NULL; | ||
197 | |||
198 | INIT_HLIST_HEAD(&empty_rp); | ||
199 | kretprobe_hash_lock(current, &head, &flags); | ||
200 | |||
201 | /* | ||
202 | * It is possible to have multiple instances associated with a given | ||
203 | * task either because multiple functions in the call path have | ||
204 | * a return probe installed on them, and/or more than one return | ||
205 | * probe was registered for a target function. | ||
206 | * | ||
207 | * We can handle this because: | ||
208 | * - instances are always inserted at the head of the list | ||
209 | * - when multiple return probes are registered for the same | ||
210 | * function, the first instance's ret_addr will point to the | ||
211 | * real return address, and all the rest will point to | ||
212 | * kretprobe_trampoline | ||
213 | */ | ||
214 | hlist_for_each_entry_safe(ri, tmp, head, hlist) { | ||
215 | if (ri->task != current) | ||
216 | /* another task is sharing our hash bucket */ | ||
217 | continue; | ||
218 | |||
219 | orig_ret_address = (unsigned long)ri->ret_addr; | ||
220 | |||
221 | if (orig_ret_address != trampoline_address) | ||
222 | /* | ||
223 | * This is the real return address. Any other | ||
224 | * instances associated with this task are for | ||
225 | * other calls deeper on the call stack | ||
226 | */ | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | ||
231 | |||
232 | correct_ret_addr = ri->ret_addr; | ||
233 | hlist_for_each_entry_safe(ri, tmp, head, hlist) { | ||
234 | if (ri->task != current) | ||
235 | /* another task is sharing our hash bucket */ | ||
236 | continue; | ||
237 | |||
238 | orig_ret_address = (unsigned long)ri->ret_addr; | ||
239 | if (ri->rp && ri->rp->handler) { | ||
240 | __this_cpu_write(current_kprobe, &ri->rp->kp); | ||
241 | get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; | ||
242 | ri->ret_addr = correct_ret_addr; | ||
243 | ri->rp->handler(ri, regs); | ||
244 | __this_cpu_write(current_kprobe, NULL); | ||
245 | } | ||
246 | |||
247 | recycle_rp_inst(ri, &empty_rp); | ||
248 | |||
249 | if (orig_ret_address != trampoline_address) | ||
250 | /* | ||
251 | * This is the real return address. Any other | ||
252 | * instances associated with this task are for | ||
253 | * other calls deeper on the call stack | ||
254 | */ | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | kretprobe_hash_unlock(current, &flags); | ||
259 | |||
260 | hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { | ||
261 | hlist_del(&ri->hlist); | ||
262 | kfree(ri); | ||
263 | } | ||
264 | instruction_pointer_set(regs, orig_ret_address); | ||
265 | return 1; | ||
266 | } | ||
267 | |||
268 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | ||
269 | struct pt_regs *regs) | ||
270 | { | ||
271 | ri->ret_addr = (kprobe_opcode_t *)regs->gr[2]; | ||
272 | |||
273 | /* Replace the return addr with trampoline addr. */ | ||
274 | regs->gr[2] = (unsigned long)trampoline_p.addr; | ||
275 | } | ||
276 | |||
277 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | ||
278 | { | ||
279 | return p->addr == trampoline_p.addr; | ||
280 | } | ||
281 | bool arch_kprobe_on_func_entry(unsigned long offset) | ||
282 | { | ||
283 | return !offset; | ||
284 | } | ||
285 | |||
286 | int __init arch_init_kprobes(void) | ||
287 | { | ||
288 | trampoline_p.addr = (kprobe_opcode_t *) | ||
289 | dereference_function_descriptor(kretprobe_trampoline); | ||
290 | return register_kprobe(&trampoline_p); | ||
291 | } | ||
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 187f032c9dd8..4e4e8eb25874 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S | |||
@@ -311,39 +311,6 @@ fdsync: | |||
311 | nop | 311 | nop |
312 | ENDPROC_CFI(flush_data_cache_local) | 312 | ENDPROC_CFI(flush_data_cache_local) |
313 | 313 | ||
314 | /* Macros to serialize TLB purge operations on SMP. */ | ||
315 | |||
316 | .macro tlb_lock la,flags,tmp | ||
317 | #ifdef CONFIG_SMP | ||
318 | 98: | ||
319 | #if __PA_LDCW_ALIGNMENT > 4 | ||
320 | load32 pa_tlb_lock + __PA_LDCW_ALIGNMENT-1, \la | ||
321 | depi 0,31,__PA_LDCW_ALIGN_ORDER, \la | ||
322 | #else | ||
323 | load32 pa_tlb_lock, \la | ||
324 | #endif | ||
325 | rsm PSW_SM_I,\flags | ||
326 | 1: LDCW 0(\la),\tmp | ||
327 | cmpib,<>,n 0,\tmp,3f | ||
328 | 2: ldw 0(\la),\tmp | ||
329 | cmpb,<> %r0,\tmp,1b | ||
330 | nop | ||
331 | b,n 2b | ||
332 | 3: | ||
333 | 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) | ||
334 | #endif | ||
335 | .endm | ||
336 | |||
337 | .macro tlb_unlock la,flags,tmp | ||
338 | #ifdef CONFIG_SMP | ||
339 | 98: ldi 1,\tmp | ||
340 | sync | ||
341 | stw \tmp,0(\la) | ||
342 | mtsm \flags | ||
343 | 99: ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP) | ||
344 | #endif | ||
345 | .endm | ||
346 | |||
347 | /* Clear page using kernel mapping. */ | 314 | /* Clear page using kernel mapping. */ |
348 | 315 | ||
349 | ENTRY_CFI(clear_page_asm) | 316 | ENTRY_CFI(clear_page_asm) |
@@ -601,10 +568,8 @@ ENTRY_CFI(copy_user_page_asm) | |||
601 | pdtlb,l %r0(%r28) | 568 | pdtlb,l %r0(%r28) |
602 | pdtlb,l %r0(%r29) | 569 | pdtlb,l %r0(%r29) |
603 | #else | 570 | #else |
604 | tlb_lock %r20,%r21,%r22 | ||
605 | 0: pdtlb %r0(%r28) | 571 | 0: pdtlb %r0(%r28) |
606 | 1: pdtlb %r0(%r29) | 572 | 1: pdtlb %r0(%r29) |
607 | tlb_unlock %r20,%r21,%r22 | ||
608 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) | 573 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) |
609 | ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB) | 574 | ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB) |
610 | #endif | 575 | #endif |
@@ -743,9 +708,7 @@ ENTRY_CFI(clear_user_page_asm) | |||
743 | #ifdef CONFIG_PA20 | 708 | #ifdef CONFIG_PA20 |
744 | pdtlb,l %r0(%r28) | 709 | pdtlb,l %r0(%r28) |
745 | #else | 710 | #else |
746 | tlb_lock %r20,%r21,%r22 | ||
747 | 0: pdtlb %r0(%r28) | 711 | 0: pdtlb %r0(%r28) |
748 | tlb_unlock %r20,%r21,%r22 | ||
749 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) | 712 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) |
750 | #endif | 713 | #endif |
751 | 714 | ||
@@ -821,9 +784,7 @@ ENTRY_CFI(flush_dcache_page_asm) | |||
821 | #ifdef CONFIG_PA20 | 784 | #ifdef CONFIG_PA20 |
822 | pdtlb,l %r0(%r28) | 785 | pdtlb,l %r0(%r28) |
823 | #else | 786 | #else |
824 | tlb_lock %r20,%r21,%r22 | ||
825 | 0: pdtlb %r0(%r28) | 787 | 0: pdtlb %r0(%r28) |
826 | tlb_unlock %r20,%r21,%r22 | ||
827 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) | 788 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) |
828 | #endif | 789 | #endif |
829 | 790 | ||
@@ -882,9 +843,7 @@ ENTRY_CFI(purge_dcache_page_asm) | |||
882 | #ifdef CONFIG_PA20 | 843 | #ifdef CONFIG_PA20 |
883 | pdtlb,l %r0(%r28) | 844 | pdtlb,l %r0(%r28) |
884 | #else | 845 | #else |
885 | tlb_lock %r20,%r21,%r22 | ||
886 | 0: pdtlb %r0(%r28) | 846 | 0: pdtlb %r0(%r28) |
887 | tlb_unlock %r20,%r21,%r22 | ||
888 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) | 847 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) |
889 | #endif | 848 | #endif |
890 | 849 | ||
@@ -948,10 +907,8 @@ ENTRY_CFI(flush_icache_page_asm) | |||
948 | 1: pitlb,l %r0(%sr4,%r28) | 907 | 1: pitlb,l %r0(%sr4,%r28) |
949 | ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP) | 908 | ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP) |
950 | #else | 909 | #else |
951 | tlb_lock %r20,%r21,%r22 | ||
952 | 0: pdtlb %r0(%r28) | 910 | 0: pdtlb %r0(%r28) |
953 | 1: pitlb %r0(%sr4,%r28) | 911 | 1: pitlb %r0(%sr4,%r28) |
954 | tlb_unlock %r20,%r21,%r22 | ||
955 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) | 912 | ALTERNATIVE(0b, 0b+4, ALT_COND_NO_SMP, INSN_PxTLB) |
956 | ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB) | 913 | ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SMP, INSN_PxTLB) |
957 | ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP) | 914 | ALTERNATIVE(1b, 1b+4, ALT_COND_NO_SPLIT_TLB, INSN_NOP) |
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 7baa2265d439..174213b1716e 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c | |||
@@ -138,12 +138,6 @@ extern void $$dyncall(void); | |||
138 | EXPORT_SYMBOL($$dyncall); | 138 | EXPORT_SYMBOL($$dyncall); |
139 | #endif | 139 | #endif |
140 | 140 | ||
141 | #ifdef CONFIG_DISCONTIGMEM | ||
142 | #include <asm/mmzone.h> | ||
143 | EXPORT_SYMBOL(node_data); | ||
144 | EXPORT_SYMBOL(pfnnid_map); | ||
145 | #endif | ||
146 | |||
147 | #ifdef CONFIG_FUNCTION_TRACER | 141 | #ifdef CONFIG_FUNCTION_TRACER |
148 | extern void _mcount(void); | 142 | extern void _mcount(void); |
149 | EXPORT_SYMBOL(_mcount); | 143 | EXPORT_SYMBOL(_mcount); |
diff --git a/arch/parisc/kernel/patch.c b/arch/parisc/kernel/patch.c new file mode 100644 index 000000000000..cdcd981278b3 --- /dev/null +++ b/arch/parisc/kernel/patch.c | |||
@@ -0,0 +1,77 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * functions to patch RO kernel text during runtime | ||
4 | * | ||
5 | * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/spinlock.h> | ||
10 | #include <linux/kprobes.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/stop_machine.h> | ||
13 | |||
14 | #include <asm/cacheflush.h> | ||
15 | #include <asm/fixmap.h> | ||
16 | #include <asm/patch.h> | ||
17 | |||
18 | struct patch { | ||
19 | void *addr; | ||
20 | unsigned int insn; | ||
21 | }; | ||
22 | |||
23 | static void __kprobes *patch_map(void *addr, int fixmap) | ||
24 | { | ||
25 | unsigned long uintaddr = (uintptr_t) addr; | ||
26 | bool module = !core_kernel_text(uintaddr); | ||
27 | struct page *page; | ||
28 | |||
29 | if (module && IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) | ||
30 | page = vmalloc_to_page(addr); | ||
31 | else if (!module && IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) | ||
32 | page = virt_to_page(addr); | ||
33 | else | ||
34 | return addr; | ||
35 | |||
36 | set_fixmap(fixmap, page_to_phys(page)); | ||
37 | |||
38 | return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK)); | ||
39 | } | ||
40 | |||
41 | static void __kprobes patch_unmap(int fixmap) | ||
42 | { | ||
43 | clear_fixmap(fixmap); | ||
44 | } | ||
45 | |||
46 | void __kprobes __patch_text(void *addr, unsigned int insn) | ||
47 | { | ||
48 | void *waddr = addr; | ||
49 | int size; | ||
50 | |||
51 | waddr = patch_map(addr, FIX_TEXT_POKE0); | ||
52 | *(u32 *)waddr = insn; | ||
53 | size = sizeof(u32); | ||
54 | flush_kernel_vmap_range(waddr, size); | ||
55 | patch_unmap(FIX_TEXT_POKE0); | ||
56 | flush_icache_range((uintptr_t)(addr), | ||
57 | (uintptr_t)(addr) + size); | ||
58 | } | ||
59 | |||
60 | static int __kprobes patch_text_stop_machine(void *data) | ||
61 | { | ||
62 | struct patch *patch = data; | ||
63 | |||
64 | __patch_text(patch->addr, patch->insn); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | void __kprobes patch_text(void *addr, unsigned int insn) | ||
70 | { | ||
71 | struct patch patch = { | ||
72 | .addr = addr, | ||
73 | .insn = insn, | ||
74 | }; | ||
75 | |||
76 | stop_machine_cpuslocked(patch_text_stop_machine, &patch, NULL); | ||
77 | } | ||
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 841db71958cd..97c206734e24 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
@@ -193,6 +193,7 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r) | |||
193 | */ | 193 | */ |
194 | 194 | ||
195 | int running_on_qemu __read_mostly; | 195 | int running_on_qemu __read_mostly; |
196 | EXPORT_SYMBOL(running_on_qemu); | ||
196 | 197 | ||
197 | void __cpuidle arch_cpu_idle_dead(void) | 198 | void __cpuidle arch_cpu_idle_dead(void) |
198 | { | 199 | { |
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 7f4d042856b5..e0a81dedc366 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c | |||
@@ -305,7 +305,8 @@ void __init collect_boot_cpu_data(void) | |||
305 | 305 | ||
306 | if (pdc_model_platform_info(orig_prod_num, current_prod_num, serial_no) == PDC_OK) { | 306 | if (pdc_model_platform_info(orig_prod_num, current_prod_num, serial_no) == PDC_OK) { |
307 | printk(KERN_INFO "product %s, original product %s, S/N: %s\n", | 307 | printk(KERN_INFO "product %s, original product %s, S/N: %s\n", |
308 | current_prod_num, orig_prod_num, serial_no); | 308 | current_prod_num[0] ? current_prod_num : "n/a", |
309 | orig_prod_num, serial_no); | ||
309 | add_device_randomness(orig_prod_num, strlen(orig_prod_num)); | 310 | add_device_randomness(orig_prod_num, strlen(orig_prod_num)); |
310 | add_device_randomness(current_prod_num, strlen(current_prod_num)); | 311 | add_device_randomness(current_prod_num, strlen(current_prod_num)); |
311 | add_device_randomness(serial_no, strlen(serial_no)); | 312 | add_device_randomness(serial_no, strlen(serial_no)); |
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 0964c236e3e5..a3d2fb4e6dd2 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c | |||
@@ -789,3 +789,38 @@ const char *regs_query_register_name(unsigned int offset) | |||
789 | return roff->name; | 789 | return roff->name; |
790 | return NULL; | 790 | return NULL; |
791 | } | 791 | } |
792 | |||
793 | /** | ||
794 | * regs_within_kernel_stack() - check the address in the stack | ||
795 | * @regs: pt_regs which contains kernel stack pointer. | ||
796 | * @addr: address which is checked. | ||
797 | * | ||
798 | * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). | ||
799 | * If @addr is within the kernel stack, it returns true. If not, returns false. | ||
800 | */ | ||
801 | int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) | ||
802 | { | ||
803 | return ((addr & ~(THREAD_SIZE - 1)) == | ||
804 | (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); | ||
805 | } | ||
806 | |||
807 | /** | ||
808 | * regs_get_kernel_stack_nth() - get Nth entry of the stack | ||
809 | * @regs: pt_regs which contains kernel stack pointer. | ||
810 | * @n: stack entry number. | ||
811 | * | ||
812 | * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which | ||
813 | * is specified by @regs. If the @n th entry is NOT in the kernel stack, | ||
814 | * this returns 0. | ||
815 | */ | ||
816 | unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) | ||
817 | { | ||
818 | unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); | ||
819 | |||
820 | addr -= n; | ||
821 | |||
822 | if (!regs_within_kernel_stack(regs, (unsigned long)addr)) | ||
823 | return 0; | ||
824 | |||
825 | return *addr; | ||
826 | } | ||
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index d908058d05c1..e05cb2a5c16d 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c | |||
@@ -343,6 +343,12 @@ static int __init parisc_init(void) | |||
343 | boot_cpu_data.cpu_hz / 1000000, | 343 | boot_cpu_data.cpu_hz / 1000000, |
344 | boot_cpu_data.cpu_hz % 1000000 ); | 344 | boot_cpu_data.cpu_hz % 1000000 ); |
345 | 345 | ||
346 | #if defined(CONFIG_64BIT) && defined(CONFIG_SMP) | ||
347 | /* Don't serialize TLB flushes if we run on one CPU only. */ | ||
348 | if (num_online_cpus() == 1) | ||
349 | pa_serialize_tlb_flushes = 0; | ||
350 | #endif | ||
351 | |||
346 | apply_alternatives_all(); | 352 | apply_alternatives_all(); |
347 | parisc_setup_cache_timing(); | 353 | parisc_setup_cache_timing(); |
348 | 354 | ||
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 376ea0d1b275..4407ac4c1d84 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c | |||
@@ -86,7 +86,8 @@ static unsigned long mmap_upper_limit(struct rlimit *rlim_stack) | |||
86 | stack_base = STACK_SIZE_MAX; | 86 | stack_base = STACK_SIZE_MAX; |
87 | 87 | ||
88 | /* Add space for stack randomization. */ | 88 | /* Add space for stack randomization. */ |
89 | stack_base += (STACK_RND_MASK << PAGE_SHIFT); | 89 | if (current->flags & PF_RANDOMIZE) |
90 | stack_base += (STACK_RND_MASK << PAGE_SHIFT); | ||
90 | 91 | ||
91 | return PAGE_ALIGN(STACK_TOP - stack_base); | 92 | return PAGE_ALIGN(STACK_TOP - stack_base); |
92 | } | 93 | } |
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 4f77bd9be66b..e54d5e4d3489 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S | |||
@@ -48,7 +48,7 @@ registers). | |||
48 | */ | 48 | */ |
49 | #define KILL_INSN break 0,0 | 49 | #define KILL_INSN break 0,0 |
50 | 50 | ||
51 | .level LEVEL | 51 | .level PA_ASM_LEVEL |
52 | 52 | ||
53 | .text | 53 | .text |
54 | 54 | ||
@@ -640,7 +640,9 @@ cas_action: | |||
640 | sub,<> %r28, %r25, %r0 | 640 | sub,<> %r28, %r25, %r0 |
641 | 2: stw %r24, 0(%r26) | 641 | 2: stw %r24, 0(%r26) |
642 | /* Free lock */ | 642 | /* Free lock */ |
643 | sync | 643 | #ifdef CONFIG_SMP |
644 | LDCW 0(%sr2,%r20), %r1 /* Barrier */ | ||
645 | #endif | ||
644 | stw %r20, 0(%sr2,%r20) | 646 | stw %r20, 0(%sr2,%r20) |
645 | #if ENABLE_LWS_DEBUG | 647 | #if ENABLE_LWS_DEBUG |
646 | /* Clear thread register indicator */ | 648 | /* Clear thread register indicator */ |
@@ -655,7 +657,9 @@ cas_action: | |||
655 | 3: | 657 | 3: |
656 | /* Error occurred on load or store */ | 658 | /* Error occurred on load or store */ |
657 | /* Free lock */ | 659 | /* Free lock */ |
658 | sync | 660 | #ifdef CONFIG_SMP |
661 | LDCW 0(%sr2,%r20), %r1 /* Barrier */ | ||
662 | #endif | ||
659 | stw %r20, 0(%sr2,%r20) | 663 | stw %r20, 0(%sr2,%r20) |
660 | #if ENABLE_LWS_DEBUG | 664 | #if ENABLE_LWS_DEBUG |
661 | stw %r0, 4(%sr2,%r20) | 665 | stw %r0, 4(%sr2,%r20) |
@@ -857,7 +861,9 @@ cas2_action: | |||
857 | 861 | ||
858 | cas2_end: | 862 | cas2_end: |
859 | /* Free lock */ | 863 | /* Free lock */ |
860 | sync | 864 | #ifdef CONFIG_SMP |
865 | LDCW 0(%sr2,%r20), %r1 /* Barrier */ | ||
866 | #endif | ||
861 | stw %r20, 0(%sr2,%r20) | 867 | stw %r20, 0(%sr2,%r20) |
862 | /* Enable interrupts */ | 868 | /* Enable interrupts */ |
863 | ssm PSW_SM_I, %r0 | 869 | ssm PSW_SM_I, %r0 |
@@ -868,7 +874,9 @@ cas2_end: | |||
868 | 22: | 874 | 22: |
869 | /* Error occurred on load or store */ | 875 | /* Error occurred on load or store */ |
870 | /* Free lock */ | 876 | /* Free lock */ |
871 | sync | 877 | #ifdef CONFIG_SMP |
878 | LDCW 0(%sr2,%r20), %r1 /* Barrier */ | ||
879 | #endif | ||
872 | stw %r20, 0(%sr2,%r20) | 880 | stw %r20, 0(%sr2,%r20) |
873 | ssm PSW_SM_I, %r0 | 881 | ssm PSW_SM_I, %r0 |
874 | ldo 1(%r0),%r28 | 882 | ldo 1(%r0),%r28 |
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 7e1ccafadf57..096e319adeb3 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c | |||
@@ -42,6 +42,8 @@ | |||
42 | #include <asm/unwind.h> | 42 | #include <asm/unwind.h> |
43 | #include <asm/tlbflush.h> | 43 | #include <asm/tlbflush.h> |
44 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
45 | #include <linux/kgdb.h> | ||
46 | #include <linux/kprobes.h> | ||
45 | 47 | ||
46 | #include "../math-emu/math-emu.h" /* for handle_fpe() */ | 48 | #include "../math-emu/math-emu.h" /* for handle_fpe() */ |
47 | 49 | ||
@@ -293,6 +295,22 @@ static void handle_break(struct pt_regs *regs) | |||
293 | (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0); | 295 | (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0); |
294 | } | 296 | } |
295 | 297 | ||
298 | #ifdef CONFIG_KPROBES | ||
299 | if (unlikely(iir == PARISC_KPROBES_BREAK_INSN)) { | ||
300 | parisc_kprobe_break_handler(regs); | ||
301 | return; | ||
302 | } | ||
303 | |||
304 | #endif | ||
305 | |||
306 | #ifdef CONFIG_KGDB | ||
307 | if (unlikely(iir == PARISC_KGDB_COMPILED_BREAK_INSN || | ||
308 | iir == PARISC_KGDB_BREAK_INSN)) { | ||
309 | kgdb_handle_exception(9, SIGTRAP, 0, regs); | ||
310 | return; | ||
311 | } | ||
312 | #endif | ||
313 | |||
296 | if (unlikely(iir != GDB_BREAK_INSN)) | 314 | if (unlikely(iir != GDB_BREAK_INSN)) |
297 | parisc_printk_ratelimited(0, regs, | 315 | parisc_printk_ratelimited(0, regs, |
298 | KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", | 316 | KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", |
@@ -518,6 +536,19 @@ void notrace handle_interruption(int code, struct pt_regs *regs) | |||
518 | case 3: | 536 | case 3: |
519 | /* Recovery counter trap */ | 537 | /* Recovery counter trap */ |
520 | regs->gr[0] &= ~PSW_R; | 538 | regs->gr[0] &= ~PSW_R; |
539 | |||
540 | #ifdef CONFIG_KPROBES | ||
541 | if (parisc_kprobe_ss_handler(regs)) | ||
542 | return; | ||
543 | #endif | ||
544 | |||
545 | #ifdef CONFIG_KGDB | ||
546 | if (kgdb_single_step) { | ||
547 | kgdb_handle_exception(0, SIGTRAP, 0, regs); | ||
548 | return; | ||
549 | } | ||
550 | #endif | ||
551 | |||
521 | if (user_space(regs)) | 552 | if (user_space(regs)) |
522 | handle_gdb_break(regs, TRAP_TRACE); | 553 | handle_gdb_break(regs, TRAP_TRACE); |
523 | /* else this must be the start of a syscall - just let it run */ | 554 | /* else this must be the start of a syscall - just let it run */ |
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index c3b1b9c24ede..a8be7a47fcc0 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S | |||
@@ -18,6 +18,9 @@ | |||
18 | *(.data..vm0.pgd) \ | 18 | *(.data..vm0.pgd) \ |
19 | *(.data..vm0.pte) | 19 | *(.data..vm0.pte) |
20 | 20 | ||
21 | /* No __ro_after_init data in the .rodata section - which will always be ro */ | ||
22 | #define RO_AFTER_INIT_DATA | ||
23 | |||
21 | #include <asm-generic/vmlinux.lds.h> | 24 | #include <asm-generic/vmlinux.lds.h> |
22 | 25 | ||
23 | /* needed for the processor specific cache alignment size */ | 26 | /* needed for the processor specific cache alignment size */ |
diff --git a/arch/parisc/mm/Makefile b/arch/parisc/mm/Makefile index 134393de69d2..20e39b043a60 100644 --- a/arch/parisc/mm/Makefile +++ b/arch/parisc/mm/Makefile | |||
@@ -2,5 +2,5 @@ | |||
2 | # Makefile for arch/parisc/mm | 2 | # Makefile for arch/parisc/mm |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := init.o fault.o ioremap.o | 5 | obj-y := init.o fault.o ioremap.o fixmap.o |
6 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 6 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
diff --git a/arch/parisc/mm/fixmap.c b/arch/parisc/mm/fixmap.c new file mode 100644 index 000000000000..c8d41b54fb19 --- /dev/null +++ b/arch/parisc/mm/fixmap.c | |||
@@ -0,0 +1,41 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * fixmaps for parisc | ||
4 | * | ||
5 | * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> | ||
6 | */ | ||
7 | |||
8 | #include <linux/kprobes.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <asm/cacheflush.h> | ||
11 | #include <asm/fixmap.h> | ||
12 | |||
13 | void set_fixmap(enum fixed_addresses idx, phys_addr_t phys) | ||
14 | { | ||
15 | unsigned long vaddr = __fix_to_virt(idx); | ||
16 | pgd_t *pgd = pgd_offset_k(vaddr); | ||
17 | pmd_t *pmd = pmd_offset(pgd, vaddr); | ||
18 | pte_t *pte; | ||
19 | |||
20 | if (pmd_none(*pmd)) | ||
21 | pmd = pmd_alloc(NULL, pgd, vaddr); | ||
22 | |||
23 | pte = pte_offset_kernel(pmd, vaddr); | ||
24 | if (pte_none(*pte)) | ||
25 | pte = pte_alloc_kernel(pmd, vaddr); | ||
26 | |||
27 | set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX)); | ||
28 | flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); | ||
29 | } | ||
30 | |||
31 | void clear_fixmap(enum fixed_addresses idx) | ||
32 | { | ||
33 | unsigned long vaddr = __fix_to_virt(idx); | ||
34 | pgd_t *pgd = pgd_offset_k(vaddr); | ||
35 | pmd_t *pmd = pmd_offset(pgd, vaddr); | ||
36 | pte_t *pte = pte_offset_kernel(pmd, vaddr); | ||
37 | |||
38 | pte_clear(&init_mm, vaddr, pte); | ||
39 | |||
40 | flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); | ||
41 | } | ||
diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c index d77479ae3af2..d578809e55cf 100644 --- a/arch/parisc/mm/hugetlbpage.c +++ b/arch/parisc/mm/hugetlbpage.c | |||
@@ -139,9 +139,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |||
139 | { | 139 | { |
140 | unsigned long flags; | 140 | unsigned long flags; |
141 | 141 | ||
142 | purge_tlb_start(flags); | 142 | spin_lock_irqsave(pgd_spinlock((mm)->pgd), flags); |
143 | __set_huge_pte_at(mm, addr, ptep, entry); | 143 | __set_huge_pte_at(mm, addr, ptep, entry); |
144 | purge_tlb_end(flags); | 144 | spin_unlock_irqrestore(pgd_spinlock((mm)->pgd), flags); |
145 | } | 145 | } |
146 | 146 | ||
147 | 147 | ||
@@ -151,10 +151,10 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
151 | unsigned long flags; | 151 | unsigned long flags; |
152 | pte_t entry; | 152 | pte_t entry; |
153 | 153 | ||
154 | purge_tlb_start(flags); | 154 | spin_lock_irqsave(pgd_spinlock((mm)->pgd), flags); |
155 | entry = *ptep; | 155 | entry = *ptep; |
156 | __set_huge_pte_at(mm, addr, ptep, __pte(0)); | 156 | __set_huge_pte_at(mm, addr, ptep, __pte(0)); |
157 | purge_tlb_end(flags); | 157 | spin_unlock_irqrestore(pgd_spinlock((mm)->pgd), flags); |
158 | 158 | ||
159 | return entry; | 159 | return entry; |
160 | } | 160 | } |
@@ -166,10 +166,10 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm, | |||
166 | unsigned long flags; | 166 | unsigned long flags; |
167 | pte_t old_pte; | 167 | pte_t old_pte; |
168 | 168 | ||
169 | purge_tlb_start(flags); | 169 | spin_lock_irqsave(pgd_spinlock((mm)->pgd), flags); |
170 | old_pte = *ptep; | 170 | old_pte = *ptep; |
171 | __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); | 171 | __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); |
172 | purge_tlb_end(flags); | 172 | spin_unlock_irqrestore(pgd_spinlock((mm)->pgd), flags); |
173 | } | 173 | } |
174 | 174 | ||
175 | int huge_ptep_set_access_flags(struct vm_area_struct *vma, | 175 | int huge_ptep_set_access_flags(struct vm_area_struct *vma, |
@@ -178,13 +178,14 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, | |||
178 | { | 178 | { |
179 | unsigned long flags; | 179 | unsigned long flags; |
180 | int changed; | 180 | int changed; |
181 | struct mm_struct *mm = vma->vm_mm; | ||
181 | 182 | ||
182 | purge_tlb_start(flags); | 183 | spin_lock_irqsave(pgd_spinlock((mm)->pgd), flags); |
183 | changed = !pte_same(*ptep, pte); | 184 | changed = !pte_same(*ptep, pte); |
184 | if (changed) { | 185 | if (changed) { |
185 | __set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | 186 | __set_huge_pte_at(mm, addr, ptep, pte); |
186 | } | 187 | } |
187 | purge_tlb_end(flags); | 188 | spin_unlock_irqrestore(pgd_spinlock((mm)->pgd), flags); |
188 | return changed; | 189 | return changed; |
189 | } | 190 | } |
190 | 191 | ||
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index d0b166256f1a..3b0f9eab7f2c 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/mmzone.h> | 32 | #include <asm/mmzone.h> |
33 | #include <asm/sections.h> | 33 | #include <asm/sections.h> |
34 | #include <asm/msgbuf.h> | 34 | #include <asm/msgbuf.h> |
35 | #include <asm/sparsemem.h> | ||
35 | 36 | ||
36 | extern int data_start; | 37 | extern int data_start; |
37 | extern void parisc_kernel_start(void); /* Kernel entry point in head.S */ | 38 | extern void parisc_kernel_start(void); /* Kernel entry point in head.S */ |
@@ -48,11 +49,6 @@ pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((__section__ (".data..vm0.pmd"), aligned | |||
48 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data..vm0.pgd"), aligned(PAGE_SIZE))); | 49 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((__section__ (".data..vm0.pgd"), aligned(PAGE_SIZE))); |
49 | pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data..vm0.pte"), aligned(PAGE_SIZE))); | 50 | pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((__section__ (".data..vm0.pte"), aligned(PAGE_SIZE))); |
50 | 51 | ||
51 | #ifdef CONFIG_DISCONTIGMEM | ||
52 | struct node_map_data node_data[MAX_NUMNODES] __read_mostly; | ||
53 | signed char pfnnid_map[PFNNID_MAP_MAX] __read_mostly; | ||
54 | #endif | ||
55 | |||
56 | static struct resource data_resource = { | 52 | static struct resource data_resource = { |
57 | .name = "Kernel data", | 53 | .name = "Kernel data", |
58 | .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, | 54 | .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, |
@@ -76,11 +72,11 @@ static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly; | |||
76 | * information retrieved in kernel/inventory.c. | 72 | * information retrieved in kernel/inventory.c. |
77 | */ | 73 | */ |
78 | 74 | ||
79 | physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __read_mostly; | 75 | physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __initdata; |
80 | int npmem_ranges __read_mostly; | 76 | int npmem_ranges __initdata; |
81 | 77 | ||
82 | #ifdef CONFIG_64BIT | 78 | #ifdef CONFIG_64BIT |
83 | #define MAX_MEM (~0UL) | 79 | #define MAX_MEM (1UL << MAX_PHYSMEM_BITS) |
84 | #else /* !CONFIG_64BIT */ | 80 | #else /* !CONFIG_64BIT */ |
85 | #define MAX_MEM (3584U*1024U*1024U) | 81 | #define MAX_MEM (3584U*1024U*1024U) |
86 | #endif /* !CONFIG_64BIT */ | 82 | #endif /* !CONFIG_64BIT */ |
@@ -119,7 +115,7 @@ static void __init mem_limit_func(void) | |||
119 | static void __init setup_bootmem(void) | 115 | static void __init setup_bootmem(void) |
120 | { | 116 | { |
121 | unsigned long mem_max; | 117 | unsigned long mem_max; |
122 | #ifndef CONFIG_DISCONTIGMEM | 118 | #ifndef CONFIG_SPARSEMEM |
123 | physmem_range_t pmem_holes[MAX_PHYSMEM_RANGES - 1]; | 119 | physmem_range_t pmem_holes[MAX_PHYSMEM_RANGES - 1]; |
124 | int npmem_holes; | 120 | int npmem_holes; |
125 | #endif | 121 | #endif |
@@ -137,23 +133,20 @@ static void __init setup_bootmem(void) | |||
137 | int j; | 133 | int j; |
138 | 134 | ||
139 | for (j = i; j > 0; j--) { | 135 | for (j = i; j > 0; j--) { |
140 | unsigned long tmp; | 136 | physmem_range_t tmp; |
141 | 137 | ||
142 | if (pmem_ranges[j-1].start_pfn < | 138 | if (pmem_ranges[j-1].start_pfn < |
143 | pmem_ranges[j].start_pfn) { | 139 | pmem_ranges[j].start_pfn) { |
144 | 140 | ||
145 | break; | 141 | break; |
146 | } | 142 | } |
147 | tmp = pmem_ranges[j-1].start_pfn; | 143 | tmp = pmem_ranges[j-1]; |
148 | pmem_ranges[j-1].start_pfn = pmem_ranges[j].start_pfn; | 144 | pmem_ranges[j-1] = pmem_ranges[j]; |
149 | pmem_ranges[j].start_pfn = tmp; | 145 | pmem_ranges[j] = tmp; |
150 | tmp = pmem_ranges[j-1].pages; | ||
151 | pmem_ranges[j-1].pages = pmem_ranges[j].pages; | ||
152 | pmem_ranges[j].pages = tmp; | ||
153 | } | 146 | } |
154 | } | 147 | } |
155 | 148 | ||
156 | #ifndef CONFIG_DISCONTIGMEM | 149 | #ifndef CONFIG_SPARSEMEM |
157 | /* | 150 | /* |
158 | * Throw out ranges that are too far apart (controlled by | 151 | * Throw out ranges that are too far apart (controlled by |
159 | * MAX_GAP). | 152 | * MAX_GAP). |
@@ -165,7 +158,7 @@ static void __init setup_bootmem(void) | |||
165 | pmem_ranges[i-1].pages) > MAX_GAP) { | 158 | pmem_ranges[i-1].pages) > MAX_GAP) { |
166 | npmem_ranges = i; | 159 | npmem_ranges = i; |
167 | printk("Large gap in memory detected (%ld pages). " | 160 | printk("Large gap in memory detected (%ld pages). " |
168 | "Consider turning on CONFIG_DISCONTIGMEM\n", | 161 | "Consider turning on CONFIG_SPARSEMEM\n", |
169 | pmem_ranges[i].start_pfn - | 162 | pmem_ranges[i].start_pfn - |
170 | (pmem_ranges[i-1].start_pfn + | 163 | (pmem_ranges[i-1].start_pfn + |
171 | pmem_ranges[i-1].pages)); | 164 | pmem_ranges[i-1].pages)); |
@@ -230,9 +223,8 @@ static void __init setup_bootmem(void) | |||
230 | 223 | ||
231 | printk(KERN_INFO "Total Memory: %ld MB\n",mem_max >> 20); | 224 | printk(KERN_INFO "Total Memory: %ld MB\n",mem_max >> 20); |
232 | 225 | ||
233 | #ifndef CONFIG_DISCONTIGMEM | 226 | #ifndef CONFIG_SPARSEMEM |
234 | /* Merge the ranges, keeping track of the holes */ | 227 | /* Merge the ranges, keeping track of the holes */ |
235 | |||
236 | { | 228 | { |
237 | unsigned long end_pfn; | 229 | unsigned long end_pfn; |
238 | unsigned long hole_pages; | 230 | unsigned long hole_pages; |
@@ -255,18 +247,6 @@ static void __init setup_bootmem(void) | |||
255 | } | 247 | } |
256 | #endif | 248 | #endif |
257 | 249 | ||
258 | #ifdef CONFIG_DISCONTIGMEM | ||
259 | for (i = 0; i < MAX_PHYSMEM_RANGES; i++) { | ||
260 | memset(NODE_DATA(i), 0, sizeof(pg_data_t)); | ||
261 | } | ||
262 | memset(pfnnid_map, 0xff, sizeof(pfnnid_map)); | ||
263 | |||
264 | for (i = 0; i < npmem_ranges; i++) { | ||
265 | node_set_state(i, N_NORMAL_MEMORY); | ||
266 | node_set_online(i); | ||
267 | } | ||
268 | #endif | ||
269 | |||
270 | /* | 250 | /* |
271 | * Initialize and free the full range of memory in each range. | 251 | * Initialize and free the full range of memory in each range. |
272 | */ | 252 | */ |
@@ -314,7 +294,7 @@ static void __init setup_bootmem(void) | |||
314 | memblock_reserve(__pa(KERNEL_BINARY_TEXT_START), | 294 | memblock_reserve(__pa(KERNEL_BINARY_TEXT_START), |
315 | (unsigned long)(_end - KERNEL_BINARY_TEXT_START)); | 295 | (unsigned long)(_end - KERNEL_BINARY_TEXT_START)); |
316 | 296 | ||
317 | #ifndef CONFIG_DISCONTIGMEM | 297 | #ifndef CONFIG_SPARSEMEM |
318 | 298 | ||
319 | /* reserve the holes */ | 299 | /* reserve the holes */ |
320 | 300 | ||
@@ -360,6 +340,9 @@ static void __init setup_bootmem(void) | |||
360 | 340 | ||
361 | /* Initialize Page Deallocation Table (PDT) and check for bad memory. */ | 341 | /* Initialize Page Deallocation Table (PDT) and check for bad memory. */ |
362 | pdc_pdt_init(); | 342 | pdc_pdt_init(); |
343 | |||
344 | memblock_allow_resize(); | ||
345 | memblock_dump_all(); | ||
363 | } | 346 | } |
364 | 347 | ||
365 | static int __init parisc_text_address(unsigned long vaddr) | 348 | static int __init parisc_text_address(unsigned long vaddr) |
@@ -495,7 +478,7 @@ static void __init map_pages(unsigned long start_vaddr, | |||
495 | 478 | ||
496 | void __init set_kernel_text_rw(int enable_read_write) | 479 | void __init set_kernel_text_rw(int enable_read_write) |
497 | { | 480 | { |
498 | unsigned long start = (unsigned long) _text; | 481 | unsigned long start = (unsigned long) __init_begin; |
499 | unsigned long end = (unsigned long) &data_start; | 482 | unsigned long end = (unsigned long) &data_start; |
500 | 483 | ||
501 | map_pages(start, __pa(start), end-start, | 484 | map_pages(start, __pa(start), end-start, |
@@ -622,15 +605,19 @@ void __init mem_init(void) | |||
622 | * But keep code for debugging purposes. | 605 | * But keep code for debugging purposes. |
623 | */ | 606 | */ |
624 | printk("virtual kernel memory layout:\n" | 607 | printk("virtual kernel memory layout:\n" |
625 | " vmalloc : 0x%px - 0x%px (%4ld MB)\n" | 608 | " vmalloc : 0x%px - 0x%px (%4ld MB)\n" |
626 | " memory : 0x%px - 0x%px (%4ld MB)\n" | 609 | " fixmap : 0x%px - 0x%px (%4ld kB)\n" |
627 | " .init : 0x%px - 0x%px (%4ld kB)\n" | 610 | " memory : 0x%px - 0x%px (%4ld MB)\n" |
628 | " .data : 0x%px - 0x%px (%4ld kB)\n" | 611 | " .init : 0x%px - 0x%px (%4ld kB)\n" |
629 | " .text : 0x%px - 0x%px (%4ld kB)\n", | 612 | " .data : 0x%px - 0x%px (%4ld kB)\n" |
613 | " .text : 0x%px - 0x%px (%4ld kB)\n", | ||
630 | 614 | ||
631 | (void*)VMALLOC_START, (void*)VMALLOC_END, | 615 | (void*)VMALLOC_START, (void*)VMALLOC_END, |
632 | (VMALLOC_END - VMALLOC_START) >> 20, | 616 | (VMALLOC_END - VMALLOC_START) >> 20, |
633 | 617 | ||
618 | (void *)FIXMAP_START, (void *)(FIXMAP_START + FIXMAP_SIZE), | ||
619 | (unsigned long)(FIXMAP_SIZE / 1024), | ||
620 | |||
634 | __va(0), high_memory, | 621 | __va(0), high_memory, |
635 | ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20, | 622 | ((unsigned long)high_memory - (unsigned long)__va(0)) >> 20, |
636 | 623 | ||
@@ -709,37 +696,46 @@ static void __init gateway_init(void) | |||
709 | PAGE_SIZE, PAGE_GATEWAY, 1); | 696 | PAGE_SIZE, PAGE_GATEWAY, 1); |
710 | } | 697 | } |
711 | 698 | ||
712 | void __init paging_init(void) | 699 | static void __init parisc_bootmem_free(void) |
713 | { | 700 | { |
701 | unsigned long zones_size[MAX_NR_ZONES] = { 0, }; | ||
702 | unsigned long holes_size[MAX_NR_ZONES] = { 0, }; | ||
703 | unsigned long mem_start_pfn = ~0UL, mem_end_pfn = 0, mem_size_pfn = 0; | ||
714 | int i; | 704 | int i; |
715 | 705 | ||
706 | for (i = 0; i < npmem_ranges; i++) { | ||
707 | unsigned long start = pmem_ranges[i].start_pfn; | ||
708 | unsigned long size = pmem_ranges[i].pages; | ||
709 | unsigned long end = start + size; | ||
710 | |||
711 | if (mem_start_pfn > start) | ||
712 | mem_start_pfn = start; | ||
713 | if (mem_end_pfn < end) | ||
714 | mem_end_pfn = end; | ||
715 | mem_size_pfn += size; | ||
716 | } | ||
717 | |||
718 | zones_size[0] = mem_end_pfn - mem_start_pfn; | ||
719 | holes_size[0] = zones_size[0] - mem_size_pfn; | ||
720 | |||
721 | free_area_init_node(0, zones_size, mem_start_pfn, holes_size); | ||
722 | } | ||
723 | |||
724 | void __init paging_init(void) | ||
725 | { | ||
716 | setup_bootmem(); | 726 | setup_bootmem(); |
717 | pagetable_init(); | 727 | pagetable_init(); |
718 | gateway_init(); | 728 | gateway_init(); |
719 | flush_cache_all_local(); /* start with known state */ | 729 | flush_cache_all_local(); /* start with known state */ |
720 | flush_tlb_all_local(NULL); | 730 | flush_tlb_all_local(NULL); |
721 | 731 | ||
722 | for (i = 0; i < npmem_ranges; i++) { | 732 | /* |
723 | unsigned long zones_size[MAX_NR_ZONES] = { 0, }; | 733 | * Mark all memblocks as present for sparsemem using |
724 | 734 | * memory_present() and then initialize sparsemem. | |
725 | zones_size[ZONE_NORMAL] = pmem_ranges[i].pages; | 735 | */ |
726 | 736 | memblocks_present(); | |
727 | #ifdef CONFIG_DISCONTIGMEM | 737 | sparse_init(); |
728 | /* Need to initialize the pfnnid_map before we can initialize | 738 | parisc_bootmem_free(); |
729 | the zone */ | ||
730 | { | ||
731 | int j; | ||
732 | for (j = (pmem_ranges[i].start_pfn >> PFNNID_SHIFT); | ||
733 | j <= ((pmem_ranges[i].start_pfn + pmem_ranges[i].pages) >> PFNNID_SHIFT); | ||
734 | j++) { | ||
735 | pfnnid_map[j] = i; | ||
736 | } | ||
737 | } | ||
738 | #endif | ||
739 | |||
740 | free_area_init_node(i, zones_size, | ||
741 | pmem_ranges[i].start_pfn, NULL); | ||
742 | } | ||
743 | } | 739 | } |
744 | 740 | ||
745 | #ifdef CONFIG_PA20 | 741 | #ifdef CONFIG_PA20 |
diff --git a/drivers/net/ethernet/i825xx/lasi_82596.c b/drivers/net/ethernet/i825xx/lasi_82596.c index b69c622ba8b2..211c5f74b4c8 100644 --- a/drivers/net/ethernet/i825xx/lasi_82596.c +++ b/drivers/net/ethernet/i825xx/lasi_82596.c | |||
@@ -105,7 +105,7 @@ | |||
105 | #define DMA_WBACK_INV(ndev, addr, len) \ | 105 | #define DMA_WBACK_INV(ndev, addr, len) \ |
106 | do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0) | 106 | do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0) |
107 | 107 | ||
108 | #define SYSBUS 0x0000006c; | 108 | #define SYSBUS 0x0000006c |
109 | 109 | ||
110 | /* big endian CPU, 82596 "big" endian mode */ | 110 | /* big endian CPU, 82596 "big" endian mode */ |
111 | #define SWAP32(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) | 111 | #define SWAP32(x) (((u32)(x)<<16) | ((((u32)(x)))>>16)) |
@@ -141,7 +141,8 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x) | |||
141 | } | 141 | } |
142 | 142 | ||
143 | gsc_writel(a, dev->base_addr + PA_CPU_PORT_L_ACCESS); | 143 | gsc_writel(a, dev->base_addr + PA_CPU_PORT_L_ACCESS); |
144 | udelay(1); | 144 | if (!running_on_qemu) |
145 | udelay(1); | ||
145 | gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS); | 146 | gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS); |
146 | } | 147 | } |
147 | 148 | ||
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 0c6e8b44b4ed..c60b465f6fe4 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c | |||
@@ -568,6 +568,9 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d | |||
568 | break; | 568 | break; |
569 | 569 | ||
570 | case DISPLAY_MODEL_LASI: | 570 | case DISPLAY_MODEL_LASI: |
571 | /* Skip to register LED in QEMU */ | ||
572 | if (running_on_qemu) | ||
573 | return 1; | ||
571 | LED_DATA_REG = data_reg; | 574 | LED_DATA_REG = data_reg; |
572 | led_func_ptr = led_LASI_driver; | 575 | led_func_ptr = led_LASI_driver; |
573 | printk(KERN_INFO "LED display at %lx registered\n", LED_DATA_REG); | 576 | printk(KERN_INFO "LED display at %lx registered\n", LED_DATA_REG); |