diff options
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); |
