diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-01 16:51:13 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-01 16:51:13 -0700 |
commit | 552ebfe022ec67aca4ff2bda0722ed0e28fc90d5 (patch) | |
tree | 3bb6c2318f8f66a04fa98400591b970a77e8c6bd | |
parent | 46f876322820c189ab525cfcba2519a17dbc0a6f (diff) | |
parent | 6e866a462867b60841202e900f10936a0478608c (diff) |
Merge tag 'for-5.16/parisc-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc updates from Helge Deller:
"Lots of new features and fixes:
- Added TOC (table of content) support, which is a debugging feature
which is either initiated by pressing the TOC button or via command
in the BMC. If pressed the Linux built-in KDB/KGDB will be called
(Sven Schnelle)
- Fix CONFIG_PREEMPT (Sven)
- Fix unwinder on 64-bit kernels (Sven)
- Various kgdb fixes (Sven)
- Added KFENCE support (me)
- Switch to ARCH_STACKWALK implementation (me)
- Fix ptrace check on syscall return (me)
- Fix kernel crash with fixmaps on PA1.x machines (me)
- Move thread_info into task struct, aka CONFIG_THREAD_INFO_IN_TASK
(me)
- Updated defconfigs
- Smaller cleanups, including Makefile cleanups (Masahiro Yamada),
use kthread_run() macro (Cai Huoqing), use swap() macro (Yihao
Han)"
* tag 'for-5.16/parisc-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: (36 commits)
parisc: Fix set_fixmap() on PA1.x CPUs
parisc: Use swap() to swap values in setup_bootmem()
parisc: Update defconfigs
parisc: decompressor: clean up Makefile
parisc: decompressor: remove repeated depenency of misc.o
parisc: Remove unused constants from asm-offsets.c
parisc/ftrace: use static key to enable/disable function graph tracer
parisc/ftrace: set function trace function
parisc: Make use of the helper macro kthread_run()
parisc: mark xchg functions notrace
parisc: enhance warning regarding usage of O_NONBLOCK
parisc: Drop ifdef __KERNEL__ from non-uapi kernel headers
parisc: Use PRIV_USER and PRIV_KERNEL in ptrace.h
parisc: Use PRIV_USER in syscall.S
parisc/kgdb: add kgdb_roundup() to make kgdb work with idle polling
parisc: Move thread_info into task struct
parisc: add support for TOC (transfer of control)
parisc/firmware: add functions to retrieve TOC data
parisc: add PIM TOC data structures
parisc: move virt_map macro to assembly.h
...
44 files changed, 622 insertions, 321 deletions
diff --git a/Documentation/features/core/thread-info-in-task/arch-support.txt b/Documentation/features/core/thread-info-in-task/arch-support.txt index 9f0259bbd7df..3361e86b0958 100644 --- a/Documentation/features/core/thread-info-in-task/arch-support.txt +++ b/Documentation/features/core/thread-info-in-task/arch-support.txt @@ -20,7 +20,7 @@ | nds32: | ok | | nios2: | TODO | | openrisc: | TODO | - | parisc: | TODO | + | parisc: | ok | | powerpc: | ok | | riscv: | ok | | s390: | ok | diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 27a8b49af11f..b2188da09c73 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -13,6 +13,8 @@ config PARISC select ARCH_NO_SG_CHAIN select ARCH_SUPPORTS_HUGETLBFS if PA20 select ARCH_SUPPORTS_MEMORY_FAILURE + select ARCH_STACKWALK + select HAVE_RELIABLE_STACKTRACE select DMA_OPS select RTC_CLASS select RTC_DRV_GENERIC @@ -46,6 +48,7 @@ config PARISC select HAVE_ARCH_HASH select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL_RELATIVE + select HAVE_ARCH_KFENCE select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_REGS_AND_STACK_ACCESS_API @@ -53,6 +56,7 @@ config PARISC select HAVE_UNSTABLE_SCHED_CLOCK if SMP select LEGACY_TIMER_TICK select CPU_NO_EFFICIENT_FFS + select THREAD_INFO_IN_TASK select NEED_DMA_MAP_STATE select NEED_SG_DMA_LENGTH select HAVE_ARCH_KGDB @@ -252,11 +256,11 @@ config PARISC_PAGE_SIZE_4KB config PARISC_PAGE_SIZE_16KB bool "16KB" - depends on PA8X00 && BROKEN + depends on PA8X00 && BROKEN && !KFENCE config PARISC_PAGE_SIZE_64KB bool "64KB" - depends on PA8X00 && BROKEN + depends on PA8X00 && BROKEN && !KFENCE endchoice @@ -288,6 +292,20 @@ config SMP If you don't know what to do here, say N. +config TOC + bool "Support TOC switch" + default y if 64BIT || !SMP + help + Most PA-RISC machines have either a switch at the back of the machine + or a command in BMC to trigger a TOC interrupt. If you say Y here a + handler will be installed which will either show a backtrace on all + CPUs, or enter a possible configured debugger like kgdb/kdb. + + Note that with this option enabled, the kernel will use an additional 16KB + per possible CPU as a special stack for the TOC handler. + + If you don't want to debug the Kernel, say N. + config PARISC_CPU_TOPOLOGY bool "Support cpu topology definition" depends on SMP diff --git a/arch/parisc/boot/compressed/Makefile b/arch/parisc/boot/compressed/Makefile index 9fe54878167d..bf4f2891d0b7 100644 --- a/arch/parisc/boot/compressed/Makefile +++ b/arch/parisc/boot/compressed/Makefile @@ -9,9 +9,10 @@ KCOV_INSTRUMENT := n GCOV_PROFILE := n UBSAN_SANITIZE := n +OBJECTS := head.o real2.o firmware.o misc.o piggy.o targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4 -targets += misc.o piggy.o sizes.h head.o real2.o firmware.o +targets += $(OBJECTS) sizes.h targets += real2.S firmware.c KBUILD_CFLAGS := -D__KERNEL__ -O2 -DBOOTLOADER @@ -23,10 +24,8 @@ ifndef CONFIG_64BIT KBUILD_CFLAGS += -mfast-indirect-calls endif -OBJECTS += $(obj)/head.o $(obj)/real2.o $(obj)/firmware.o $(obj)/misc.o $(obj)/piggy.o - LDFLAGS_vmlinux := -X -e startup --as-needed -T -$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(LIBGCC) FORCE +$(obj)/vmlinux: $(obj)/vmlinux.lds $(addprefix $(obj)/, $(OBJECTS)) $(LIBGCC) FORCE $(call if_changed,ld) sed-sizes := -e 's/^\([0-9a-fA-F]*\) . \(__bss_start\|_end\|parisc_kernel_start\)$$/\#define SZ\2 0x\1/p' @@ -52,8 +51,6 @@ $(obj)/real2.o: $(obj)/real2.S $(obj)/real2.S: $(srctree)/arch/$(SRCARCH)/kernel/real2.S $(call cmd,shipped) -$(obj)/misc.o: $(obj)/sizes.h - CPPFLAGS_vmlinux.lds += -I$(objtree)/$(obj) -DBOOTLOADER $(obj)/vmlinux.lds: $(obj)/sizes.h diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig index dd14e3131325..d6fd8fa7ed8c 100644 --- a/arch/parisc/configs/generic-32bit_defconfig +++ b/arch/parisc/configs/generic-32bit_defconfig @@ -22,7 +22,6 @@ CONFIG_PCI_LBA=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_BLK_DEV_BSG is not set # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m CONFIG_NET=y @@ -55,13 +54,14 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y CONFIG_CHR_DEV_SG=y +# CONFIG_BLK_DEV_BSG is not set CONFIG_SCSI_LASI700=y CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_ZALON=y CONFIG_SCSI_DH=y CONFIG_ATA=y -CONFIG_ATA_GENERIC=y CONFIG_PATA_NS87415=y +CONFIG_ATA_GENERIC=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m @@ -212,7 +212,6 @@ CONFIG_NFS_FS=m CONFIG_NFSD=m CONFIG_NFSD_V3=y CONFIG_CIFS=m -CONFIG_CIFS_WEAK_PW_HASH=y CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y # CONFIG_CIFS_DEBUG is not set @@ -221,16 +220,12 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_ANUBIS=m CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRC_CCITT=m diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig index 53054b81461a..d2daeac2b217 100644 --- a/arch/parisc/configs/generic-64bit_defconfig +++ b/arch/parisc/configs/generic-64bit_defconfig @@ -8,9 +8,10 @@ CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y CONFIG_MEMCG=y -CONFIG_MEMCG_SWAP=y CONFIG_CGROUP_PIDS=y CONFIG_CPUSETS=y CONFIG_RELAY=y @@ -124,14 +125,13 @@ CONFIG_QLCNIC=m # CONFIG_NET_VENDOR_TI is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set -CONFIG_MDIO_BITBANG=m CONFIG_PHYLIB=y CONFIG_BROADCOM_PHY=m CONFIG_CICADA_PHY=m CONFIG_DAVICOM_PHY=m CONFIG_ICPLUS_PHY=m -CONFIG_LSI_ET1011C_PHY=m CONFIG_LXT_PHY=m +CONFIG_LSI_ET1011C_PHY=m CONFIG_MARVELL_PHY=m CONFIG_NATIONAL_PHY=m CONFIG_QSEMI_PHY=m @@ -139,6 +139,7 @@ CONFIG_REALTEK_PHY=m CONFIG_SMSC_PHY=m CONFIG_STE10XP=m CONFIG_VITESSE_PHY=m +CONFIG_MDIO_BITBANG=m CONFIG_SLIP=m # CONFIG_WLAN is not set CONFIG_INPUT_EVDEV=y @@ -150,7 +151,6 @@ CONFIG_SERIO_SERPORT=m # CONFIG_HP_SDC is not set CONFIG_SERIO_RAW=m # CONFIG_LEGACY_PTYS is not set -CONFIG_NOZOMI=m CONFIG_SERIAL_8250=y # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set CONFIG_SERIAL_8250_CONSOLE=y @@ -160,6 +160,7 @@ CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_JSM=m +CONFIG_NOZOMI=m CONFIG_IPMI_HANDLER=y CONFIG_IPMI_DEVICE_INTERFACE=y CONFIG_IPMI_SI=y @@ -188,9 +189,13 @@ CONFIG_AGP=y CONFIG_AGP_PARISC=y CONFIG_DRM=y CONFIG_DRM_RADEON=y -CONFIG_FIRMWARE_EDID=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FB=y +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=y +CONFIG_FB_MATROX_MAVEN=y +CONFIG_FB_RADEON=y CONFIG_HIDRAW=y CONFIG_HID_PID=y CONFIG_USB_HIDDEV=y @@ -202,7 +207,6 @@ CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m CONFIG_STAGING=y CONFIG_QLGE=m -CONFIG_HP100=m CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_SECURITY=y @@ -245,7 +249,6 @@ CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_FCRYPT=m CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_HW is not set diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h index a39250cb7dfc..7085df079702 100644 --- a/arch/parisc/include/asm/assembly.h +++ b/arch/parisc/include/asm/assembly.h @@ -42,6 +42,9 @@ #define ASM_ULONG_INSN .word #endif +/* Frame alignment for 32- and 64-bit */ +#define FRAME_ALIGN 64 + #define CALLEE_SAVE_FRAME_SIZE (CALLEE_REG_FRAME_SIZE + CALLEE_FLOAT_FRAME_SIZE) #ifdef CONFIG_PA20 @@ -58,6 +61,10 @@ #define PA_ASM_LEVEL 1.1 #endif +/* Privilege level field in the rightmost two bits of the IA queues */ +#define PRIV_USER 3 +#define PRIV_KERNEL 0 + #ifdef __ASSEMBLY__ #ifdef CONFIG_64BIT @@ -71,6 +78,7 @@ #include <asm/types.h> #include <asm/asmregs.h> +#include <asm/psw.h> sp = 30 gp = 27 @@ -497,6 +505,30 @@ nop /* 7 */ .endm + /* Switch to virtual mapping, trashing only %r1 */ + .macro virt_map + /* pcxt_ssm_bug */ + rsm PSW_SM_I, %r0 /* barrier for "Relied upon Translation */ + mtsp %r0, %sr4 + mtsp %r0, %sr5 + mtsp %r0, %sr6 + tovirt_r1 %r29 + load32 KERNEL_PSW, %r1 + + rsm PSW_SM_QUIET,%r0 /* second "heavy weight" ctl op */ + mtctl %r0, %cr17 /* Clear IIASQ tail */ + mtctl %r0, %cr17 /* Clear IIASQ head */ + mtctl %r1, %ipsw + load32 4f, %r1 + mtctl %r1, %cr18 /* Set IIAOQ tail */ + ldo 4(%r1), %r1 + mtctl %r1, %cr18 /* Set IIAOQ head */ + rfir + nop +4: + .endm + + /* * ASM_EXCEPTIONTABLE_ENTRY * diff --git a/arch/parisc/include/asm/bitops.h b/arch/parisc/include/asm/bitops.h index aa4e883431c1..daa2afd974fb 100644 --- a/arch/parisc/include/asm/bitops.h +++ b/arch/parisc/include/asm/bitops.h @@ -104,8 +104,6 @@ static __inline__ int test_and_change_bit(int nr, volatile unsigned long * addr) #include <asm-generic/bitops/non-atomic.h> -#ifdef __KERNEL__ - /** * __ffs - find first bit in word. returns 0 to "BITS_PER_LONG-1". * @word: The word to search @@ -205,16 +203,8 @@ static __inline__ int fls(unsigned int x) #include <asm-generic/bitops/hweight.h> #include <asm-generic/bitops/lock.h> #include <asm-generic/bitops/sched.h> - -#endif /* __KERNEL__ */ - #include <asm-generic/bitops/find.h> - -#ifdef __KERNEL__ - #include <asm-generic/bitops/le.h> #include <asm-generic/bitops/ext2-atomic-setbit.h> -#endif /* __KERNEL__ */ - #endif /* _PARISC_BITOPS_H */ diff --git a/arch/parisc/include/asm/current.h b/arch/parisc/include/asm/current.h new file mode 100644 index 000000000000..568b739e42af --- /dev/null +++ b/arch/parisc/include/asm/current.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_PARISC_CURRENT_H +#define _ASM_PARISC_CURRENT_H + +#include <asm/special_insns.h> + +#ifndef __ASSEMBLY__ +struct task_struct; + +static __always_inline struct task_struct *get_current(void) +{ + return (struct task_struct *) mfctl(30); +} + +#define current get_current() + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_PARISC_CURRENT_H */ diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h index fceb9cf02fb3..e38a118cf65d 100644 --- a/arch/parisc/include/asm/futex.h +++ b/arch/parisc/include/asm/futex.h @@ -2,8 +2,6 @@ #ifndef _ASM_PARISC_FUTEX_H #define _ASM_PARISC_FUTEX_H -#ifdef __KERNEL__ - #include <linux/futex.h> #include <linux/uaccess.h> #include <asm/atomic.h> @@ -119,5 +117,4 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, return 0; } -#endif /*__KERNEL__*/ #endif /*_ASM_PARISC_FUTEX_H*/ diff --git a/arch/parisc/include/asm/ide.h b/arch/parisc/include/asm/ide.h index 34cdac01ed35..7aa75b93a1b6 100644 --- a/arch/parisc/include/asm/ide.h +++ b/arch/parisc/include/asm/ide.h @@ -12,8 +12,6 @@ #ifndef __ASM_PARISC_IDE_H #define __ASM_PARISC_IDE_H -#ifdef __KERNEL__ - /* Generic I/O and MEMIO string operations. */ #define __ide_insw insw @@ -53,6 +51,4 @@ static __inline__ void __ide_mm_outsl(void __iomem *port, void *addr, u32 count) } } -#endif /* __KERNEL__ */ - #endif /* __ASM_PARISC_IDE_H */ diff --git a/arch/parisc/include/asm/kfence.h b/arch/parisc/include/asm/kfence.h new file mode 100644 index 000000000000..6259e5ac1fea --- /dev/null +++ b/arch/parisc/include/asm/kfence.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PA-RISC KFENCE support. + * + * Copyright (C) 2021, Helge Deller <deller@gmx.de> + */ + +#ifndef _ASM_PARISC_KFENCE_H +#define _ASM_PARISC_KFENCE_H + +#include <linux/kfence.h> + +#include <asm/pgtable.h> +#include <asm/tlbflush.h> + +static inline bool arch_kfence_init_pool(void) +{ + return true; +} + +/* Protect the given page and flush TLB. */ +static inline bool kfence_protect_page(unsigned long addr, bool protect) +{ + pte_t *pte = virt_to_kpte(addr); + + if (WARN_ON(!pte)) + return false; + + /* + * We need to avoid IPIs, as we may get KFENCE allocations or faults + * with interrupts disabled. + */ + + if (protect) + set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT)); + else + set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT)); + + flush_tlb_kernel_range(addr, addr + PAGE_SIZE); + + return true; +} + +#endif /* _ASM_PARISC_KFENCE_H */ diff --git a/arch/parisc/include/asm/mckinley.h b/arch/parisc/include/asm/mckinley.h index eb84dbeb7fd9..1314390b9034 100644 --- a/arch/parisc/include/asm/mckinley.h +++ b/arch/parisc/include/asm/mckinley.h @@ -1,10 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef ASM_PARISC_MCKINLEY_H #define ASM_PARISC_MCKINLEY_H -#ifdef __KERNEL__ /* declared in arch/parisc/kernel/setup.c */ extern struct proc_dir_entry * proc_mckinley_root; -#endif /*__KERNEL__*/ #endif /*ASM_PARISC_MCKINLEY_H*/ diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h index b388d8176588..18b957a8630d 100644 --- a/arch/parisc/include/asm/pdc.h +++ b/arch/parisc/include/asm/pdc.h @@ -51,6 +51,8 @@ int pdc_spaceid_bits(unsigned long *space_bits); int pdc_btlb_info(struct pdc_btlb_info *btlb); int pdc_mem_map_hpa(struct pdc_memory_map *r_addr, struct pdc_module_path *mod_path); #endif /* !CONFIG_PA20 */ +int pdc_pim_toc11(struct pdc_toc_pim_11 *ret); +int pdc_pim_toc20(struct pdc_toc_pim_20 *ret); int pdc_lan_station_id(char *lan_addr, unsigned long net_hpa); int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count); diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 85a2dbfe5278..b669f4b9040b 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -12,6 +12,7 @@ #ifndef __ASSEMBLY__ #include <linux/threads.h> +#include <asm/assembly.h> #include <asm/prefetch.h> #include <asm/hardware.h> #include <asm/pdc.h> @@ -37,16 +38,12 @@ #define DEFAULT_MAP_BASE DEFAULT_MAP_BASE32 #endif -#ifdef __KERNEL__ - /* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc. * prumpf */ #define STACK_TOP TASK_SIZE #define STACK_TOP_MAX DEFAULT_TASK_SIZE -#endif - #ifndef __ASSEMBLY__ unsigned long calc_max_stack_size(unsigned long stack_max); @@ -101,8 +98,6 @@ DECLARE_PER_CPU(struct cpuinfo_parisc, cpu_data); #define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF) -#define ARCH_MIN_TASKALIGN 8 - struct thread_struct { struct pt_regs regs; unsigned long task_size; @@ -294,6 +289,10 @@ extern int _parisc_requires_coherency; extern int running_on_qemu; +extern void toc_handler(void); +extern unsigned int toc_handler_size; +extern unsigned int toc_handler_csum; + #endif /* __ASSEMBLY__ */ #endif /* __ASM_PARISC_PROCESSOR_H */ diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h index 143fb2a89dd8..eea3f3df0823 100644 --- a/arch/parisc/include/asm/ptrace.h +++ b/arch/parisc/include/asm/ptrace.h @@ -5,17 +5,17 @@ #ifndef _PARISC_PTRACE_H #define _PARISC_PTRACE_H +#include <asm/assembly.h> #include <uapi/asm/ptrace.h> - #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) #define arch_has_single_step() 1 #define arch_has_block_step() 1 /* XXX should we use iaoq[1] or iaoq[0] ? */ -#define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0) -#define user_space(regs) (((regs)->iasq[1] != 0) ? 1 : 0) +#define user_mode(regs) (((regs)->iaoq[0] & 3) != PRIV_KERNEL) +#define user_space(regs) ((regs)->iasq[1] != PRIV_KERNEL) #define instruction_pointer(regs) ((regs)->iaoq[0] & ~3) #define user_stack_pointer(regs) ((regs)->gr[30]) unsigned long profile_pc(struct pt_regs *); diff --git a/arch/parisc/include/asm/runway.h b/arch/parisc/include/asm/runway.h index f3cfe69439f6..5cf061376ddb 100644 --- a/arch/parisc/include/asm/runway.h +++ b/arch/parisc/include/asm/runway.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef ASM_PARISC_RUNWAY_H #define ASM_PARISC_RUNWAY_H -#ifdef __KERNEL__ /* declared in arch/parisc/kernel/setup.c */ extern struct proc_dir_entry * proc_runway_root; @@ -9,5 +8,4 @@ extern struct proc_dir_entry * proc_runway_root; #define RUNWAY_STATUS 0x10 #define RUNWAY_DEBUG 0x40 -#endif /* __KERNEL__ */ #endif /* ASM_PARISC_RUNWAY_H */ diff --git a/arch/parisc/include/asm/smp.h b/arch/parisc/include/asm/smp.h index b9a18db4b05a..16d41127500e 100644 --- a/arch/parisc/include/asm/smp.h +++ b/arch/parisc/include/asm/smp.h @@ -34,8 +34,23 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); #endif /* !ASSEMBLY */ -#define raw_smp_processor_id() (current_thread_info()->cpu) - +/* + * This is particularly ugly: it appears we can't actually get the definition + * of task_struct here, but we need access to the CPU this task is running on. + * Instead of using task_struct we're using TASK_CPU which is extracted from + * asm-offsets.h by kbuild to get the current processor ID. + * + * This also needs to be safeguarded when building asm-offsets.s because at + * that time TASK_CPU is not defined yet. It could have been guarded by + * TASK_CPU itself, but we want the build to fail if TASK_CPU is missing + * when building something else than asm-offsets.s + */ +#ifdef GENERATING_ASM_OFFSETS +#define raw_smp_processor_id() (0) +#else +#include <asm/asm-offsets.h> +#define raw_smp_processor_id() (*(unsigned int *)((void *)current + TASK_CPU)) +#endif #else /* CONFIG_SMP */ static inline void smp_send_all_nop(void) { return; } diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h index 00ad50fef769..75657c2c54e1 100644 --- a/arch/parisc/include/asm/thread_info.h +++ b/arch/parisc/include/asm/thread_info.h @@ -2,30 +2,21 @@ #ifndef _ASM_PARISC_THREAD_INFO_H #define _ASM_PARISC_THREAD_INFO_H -#ifdef __KERNEL__ - #ifndef __ASSEMBLY__ #include <asm/processor.h> #include <asm/special_insns.h> struct thread_info { - struct task_struct *task; /* main task structure */ unsigned long flags; /* thread_info flags (see TIF_*) */ - __u32 cpu; /* current CPU */ int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ }; #define INIT_THREAD_INFO(tsk) \ { \ - .task = &tsk, \ .flags = 0, \ - .cpu = 0, \ .preempt_count = INIT_PREEMPT_COUNT, \ } -/* how to get the thread information struct from C */ -#define current_thread_info() ((struct thread_info *)mfctl(30)) - #endif /* !__ASSEMBLY */ /* thread information allocation */ @@ -57,6 +48,7 @@ struct thread_info { #define TIF_BLOCKSTEP 10 /* branch stepping? */ #define TIF_SECCOMP 11 /* secure computing */ #define TIF_SYSCALL_TRACEPOINT 12 /* syscall tracepoint instrumentation */ +#define TIF_NONBLOCK_WARNING 13 /* warned about wrong O_NONBLOCK usage */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) @@ -87,6 +79,4 @@ struct thread_info { # define is_32bit_task() (1) #endif -#endif /* __KERNEL__ */ - #endif /* _ASM_PARISC_THREAD_INFO_H */ diff --git a/arch/parisc/include/asm/traps.h b/arch/parisc/include/asm/traps.h index 8ecc1f0c0483..34619f010c63 100644 --- a/arch/parisc/include/asm/traps.h +++ b/arch/parisc/include/asm/traps.h @@ -14,6 +14,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, void die_if_kernel(char *str, struct pt_regs *regs, long err); /* mm/fault.c */ +unsigned long parisc_acctyp(unsigned long code, unsigned int inst); const char *trap_name(unsigned long code); void do_page_fault(struct pt_regs *regs, unsigned long code, unsigned long address); diff --git a/arch/parisc/include/asm/unaligned.h b/arch/parisc/include/asm/unaligned.h index 3bda16773ba6..c0621295100d 100644 --- a/arch/parisc/include/asm/unaligned.h +++ b/arch/parisc/include/asm/unaligned.h @@ -4,10 +4,8 @@ #include <asm-generic/unaligned.h> -#ifdef __KERNEL__ struct pt_regs; void handle_unaligned(struct pt_regs *regs); int check_unaligned(struct pt_regs *regs); -#endif #endif /* _ASM_PARISC_UNALIGNED_H */ diff --git a/arch/parisc/include/uapi/asm/pdc.h b/arch/parisc/include/uapi/asm/pdc.h index 15211723ebf5..acc633c15722 100644 --- a/arch/parisc/include/uapi/asm/pdc.h +++ b/arch/parisc/include/uapi/asm/pdc.h @@ -398,8 +398,10 @@ struct zeropage { /* int (*vec_rendz)(void); */ unsigned int vec_rendz; int vec_pow_fail_flen; - int vec_pad[10]; - + int vec_pad0[3]; + unsigned int vec_toc_hi; + int vec_pad1[6]; + /* [0x040] reserved processor dependent */ int pad0[112]; @@ -689,6 +691,28 @@ struct pdc_hpmc_pim_20 { /* PDC_PIM */ unsigned long long fr[32]; }; +struct pdc_toc_pim_11 { + unsigned int gr[32]; + unsigned int cr[32]; + unsigned int sr[8]; + unsigned int iasq_back; + unsigned int iaoq_back; + unsigned int check_type; + unsigned int hversion; + unsigned int cpu_state; +}; + +struct pdc_toc_pim_20 { + unsigned long long gr[32]; + unsigned long long cr[32]; + unsigned long long sr[8]; + unsigned long long iasq_back; + unsigned long long iaoq_back; + unsigned int check_type; + unsigned int hversion; + unsigned int cpu_state; +}; + #endif /* !defined(__ASSEMBLY__) */ #endif /* _UAPI_PARISC_PDC_H */ diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index 068d90950d93..ed0b87908d71 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_KEXEC_CORE) += kexec.o relocate_kernel.o obj-$(CONFIG_KEXEC_FILE) += kexec_file.o +obj-$(CONFIG_TOC) += toc.o toc_asm.o diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c index 22924a3f1728..e35154035441 100644 --- a/arch/parisc/kernel/asm-offsets.c +++ b/arch/parisc/kernel/asm-offsets.c @@ -14,6 +14,8 @@ * Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org> */ +#define GENERATING_ASM_OFFSETS /* asm/smp.h */ + #include <linux/types.h> #include <linux/sched.h> #include <linux/thread_info.h> @@ -22,18 +24,12 @@ #include <linux/kbuild.h> #include <linux/pgtable.h> +#include <asm/assembly.h> #include <asm/ptrace.h> #include <asm/processor.h> #include <asm/pdc.h> #include <linux/uaccess.h> -#ifdef CONFIG_64BIT -#define FRAME_SIZE 128 -#else -#define FRAME_SIZE 64 -#endif -#define FRAME_ALIGN 64 - /* Add FRAME_SIZE to the size x and align it to y. All definitions * that use align_frame will include space for a frame. */ @@ -41,13 +37,11 @@ int main(void) { - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); - DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); - DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending)); - DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); - DEFINE(TASK_MM, offsetof(struct task_struct, mm)); - DEFINE(TASK_PERSONALITY, offsetof(struct task_struct, personality)); - DEFINE(TASK_PID, offsetof(struct task_struct, pid)); + DEFINE(TASK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags)); + DEFINE(TASK_STACK, offsetof(struct task_struct, stack)); +#ifdef CONFIG_SMP + DEFINE(TASK_CPU, offsetof(struct task_struct, cpu)); +#endif BLANK(); DEFINE(TASK_REGS, offsetof(struct task_struct, thread.regs)); DEFINE(TASK_PT_PSW, offsetof(struct task_struct, thread.regs.gr[ 0])); @@ -135,10 +129,6 @@ int main(void) DEFINE(TASK_PT_ISR, offsetof(struct task_struct, thread.regs.isr)); DEFINE(TASK_PT_IOR, offsetof(struct task_struct, thread.regs.ior)); BLANK(); - DEFINE(TASK_SZ, sizeof(struct task_struct)); - /* TASK_SZ_ALGN includes space for a stack frame. */ - DEFINE(TASK_SZ_ALGN, align_frame(sizeof(struct task_struct), FRAME_ALIGN)); - BLANK(); DEFINE(PT_PSW, offsetof(struct pt_regs, gr[ 0])); DEFINE(PT_GR1, offsetof(struct pt_regs, gr[ 1])); DEFINE(PT_GR2, offsetof(struct pt_regs, gr[ 2])); @@ -223,17 +213,11 @@ int main(void) DEFINE(PT_IIR, offsetof(struct pt_regs, iir)); DEFINE(PT_ISR, offsetof(struct pt_regs, isr)); DEFINE(PT_IOR, offsetof(struct pt_regs, ior)); - DEFINE(PT_SIZE, sizeof(struct pt_regs)); /* PT_SZ_ALGN includes space for a stack frame. */ DEFINE(PT_SZ_ALGN, align_frame(sizeof(struct pt_regs), FRAME_ALIGN)); BLANK(); - DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); - DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); - DEFINE(THREAD_SZ, sizeof(struct thread_info)); - /* THREAD_SZ_ALGN includes space for a stack frame. */ - DEFINE(THREAD_SZ_ALGN, align_frame(sizeof(struct thread_info), FRAME_ALIGN)); + DEFINE(TI_PRE_COUNT, offsetof(struct task_struct, thread_info.preempt_count)); BLANK(); DEFINE(ICACHE_BASE, offsetof(struct pdc_cache_info, ic_base)); DEFINE(ICACHE_STRIDE, offsetof(struct pdc_cache_info, ic_stride)); diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 39e02227e231..c61827e4928a 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -543,10 +543,33 @@ static inline pte_t *get_ptep(pgd_t *pgd, unsigned long addr) return ptep; } +static void flush_cache_pages(struct vm_area_struct *vma, struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + unsigned long addr, pfn; + pte_t *ptep; + + for (addr = start; addr < end; addr += PAGE_SIZE) { + ptep = get_ptep(mm->pgd, addr); + if (ptep) { + pfn = pte_pfn(*ptep); + flush_cache_page(vma, addr, pfn); + } + } +} + +static void flush_user_cache_tlb(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + flush_user_dcache_range_asm(start, end); + if (vma->vm_flags & VM_EXEC) + flush_user_icache_range_asm(start, end); + flush_tlb_range(vma, start, end); +} + void flush_cache_mm(struct mm_struct *mm) { struct vm_area_struct *vma; - pgd_t *pgd; /* Flushing the whole cache on each cpu takes forever on rp3440, etc. So, avoid it if the mm isn't too big. */ @@ -558,45 +581,22 @@ void flush_cache_mm(struct mm_struct *mm) return; } + preempt_disable(); if (mm->context == mfsp(3)) { - for (vma = mm->mmap; vma; vma = vma->vm_next) { - flush_user_dcache_range_asm(vma->vm_start, vma->vm_end); - if (vma->vm_flags & VM_EXEC) - flush_user_icache_range_asm(vma->vm_start, vma->vm_end); - flush_tlb_range(vma, vma->vm_start, vma->vm_end); - } + for (vma = mm->mmap; vma; vma = vma->vm_next) + flush_user_cache_tlb(vma, vma->vm_start, vma->vm_end); + preempt_enable(); return; } - pgd = mm->pgd; - for (vma = mm->mmap; vma; vma = vma->vm_next) { - unsigned long addr; - - for (addr = vma->vm_start; addr < vma->vm_end; - addr += PAGE_SIZE) { - unsigned long pfn; - pte_t *ptep = get_ptep(pgd, addr); - if (!ptep) - continue; - pfn = pte_pfn(*ptep); - if (!pfn_valid(pfn)) - continue; - if (unlikely(mm->context)) { - flush_tlb_page(vma, addr); - __flush_cache_page(vma, addr, PFN_PHYS(pfn)); - } else { - __purge_cache_page(vma, addr, PFN_PHYS(pfn)); - } - } - } + for (vma = mm->mmap; vma; vma = vma->vm_next) + flush_cache_pages(vma, mm, vma->vm_start, vma->vm_end); + preempt_enable(); } void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - pgd_t *pgd; - unsigned long addr; - if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) && end - start >= parisc_cache_flush_threshold) { if (vma->vm_mm->context) @@ -605,30 +605,15 @@ void flush_cache_range(struct vm_area_struct *vma, return; } + preempt_disable(); if (vma->vm_mm->context == mfsp(3)) { - flush_user_dcache_range_asm(start, end); - if (vma->vm_flags & VM_EXEC) - flush_user_icache_range_asm(start, end); - flush_tlb_range(vma, start, end); + flush_user_cache_tlb(vma, start, end); + preempt_enable(); return; } - pgd = vma->vm_mm->pgd; - for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) { - unsigned long pfn; - pte_t *ptep = get_ptep(pgd, addr); - if (!ptep) - continue; - pfn = pte_pfn(*ptep); - if (pfn_valid(pfn)) { - if (unlikely(vma->vm_mm->context)) { - flush_tlb_page(vma, addr); - __flush_cache_page(vma, addr, PFN_PHYS(pfn)); - } else { - __purge_cache_page(vma, addr, PFN_PHYS(pfn)); - } - } - } + flush_cache_pages(vma, vma->vm_mm, vma->vm_start, vma->vm_end); + preempt_enable(); } void diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 9f939afe6b88..57944d6f9ebb 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -51,30 +51,6 @@ extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot .endm #endif - - /* Switch to virtual mapping, trashing only %r1 */ - .macro virt_map - /* pcxt_ssm_bug */ - rsm PSW_SM_I, %r0 /* barrier for "Relied upon Translation */ - mtsp %r0, %sr4 - mtsp %r0, %sr5 - mtsp %r0, %sr6 - tovirt_r1 %r29 - load32 KERNEL_PSW, %r1 - - rsm PSW_SM_QUIET,%r0 /* second "heavy weight" ctl op */ - mtctl %r0, %cr17 /* Clear IIASQ tail */ - mtctl %r0, %cr17 /* Clear IIASQ head */ - mtctl %r1, %ipsw - load32 4f, %r1 - mtctl %r1, %cr18 /* Set IIAOQ tail */ - ldo 4(%r1), %r1 - mtctl %r1, %cr18 /* Set IIAOQ head */ - rfir - nop -4: - .endm - /* * The "get_stack" macros are responsible for determining the * kernel stack value. @@ -87,8 +63,8 @@ * Need to set up a kernel stack, so call the * get_stack_use_cr30 macro to set up a pointer * to the pt_regs structure contained within the - * task pointer pointed to by cr30. Set the stack - * pointer to point to the end of the task structure. + * task pointer pointed to by cr30. Load the stack + * pointer from the task structure. * * Note that we use shadowed registers for temps until * we can save %r26 and %r29. %r26 is used to preserve @@ -100,8 +76,6 @@ * or handle_interruption. %r29 is used to hold a pointer * the register save area, and once again, it needs to * be a non-shadowed register so that it survives the rfir. - * - * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame. */ .macro get_stack_use_cr30 @@ -110,12 +84,11 @@ copy %r30, %r17 mfctl %cr30, %r1 - ldo THREAD_SZ_ALGN(%r1), %r30 - mtsp %r0,%sr7 + tophys %r1,%r9 /* task_struct */ + LDREG TASK_STACK(%r9),%r30 + ldo PT_SZ_ALGN(%r30),%r30 + mtsp %r0,%sr7 /* clear sr7 after kernel stack was set! */ mtsp %r16,%sr3 - tophys %r1,%r9 - LDREG TI_TASK(%r9), %r1 /* thread_info -> task_struct */ - tophys %r1,%r9 ldo TASK_REGS(%r9),%r9 STREG %r17,PT_GR30(%r9) STREG %r29,PT_GR29(%r9) @@ -757,7 +730,7 @@ ENTRY(ret_from_kernel_thread) BL schedule_tail, %r2 nop - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 + mfctl %cr30,%r1 /* task_struct */ LDREG TASK_PT_GR25(%r1), %r26 #ifdef CONFIG_64BIT LDREG TASK_PT_GR27(%r1), %r27 @@ -788,7 +761,6 @@ ENTRY_CFI(_switch_to) STREG %r30, TASK_PT_KSP(%r26) LDREG TASK_PT_KSP(%r25), %r30 - LDREG TASK_THREAD_INFO(%r25), %r25 bv %r0(%r2) mtctl %r25,%cr30 @@ -819,17 +791,16 @@ ENDPROC_CFI(_switch_to) .align PAGE_SIZE ENTRY_CFI(syscall_exit_rfi) - mfctl %cr30,%r16 - LDREG TI_TASK(%r16), %r16 /* thread_info -> task_struct */ + mfctl %cr30,%r16 /* task_struct */ ldo TASK_REGS(%r16),%r16 /* Force iaoq to userspace, as the user has had access to our current * context via sigcontext. Also Filter the PSW for the same reason. */ LDREG PT_IAOQ0(%r16),%r19 - depi 3,31,2,%r19 + depi PRIV_USER,31,2,%r19 STREG %r19,PT_IAOQ0(%r16) LDREG PT_IAOQ1(%r16),%r19 - depi 3,31,2,%r19 + depi PRIV_USER,31,2,%r19 STREG %r19,PT_IAOQ1(%r16) LDREG PT_PSW(%r16),%r19 load32 USER_PSW_MASK,%r1 @@ -865,14 +836,14 @@ ENTRY_CFI(syscall_exit_rfi) ENTRY(intr_return) /* check for reschedule */ mfctl %cr30,%r1 - LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ + LDREG TASK_TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */ .import do_notify_resume,code intr_check_sig: /* As above */ mfctl %cr30,%r1 - LDREG TI_FLAGS(%r1),%r19 + LDREG TASK_TI_FLAGS(%r1),%r19 ldi (_TIF_USER_WORK_MASK & ~_TIF_NEED_RESCHED), %r20 and,COND(<>) %r19, %r20, %r0 b,n intr_restore /* skip past if we've nothing to do */ @@ -974,8 +945,8 @@ intr_do_preempt: /* current_thread_info()->preempt_count */ mfctl %cr30, %r1 - LDREG TI_PRE_COUNT(%r1), %r19 - cmpib,COND(<>) 0, %r19, intr_restore /* if preempt_count > 0 */ + ldw TI_PRE_COUNT(%r1), %r19 + cmpib,<> 0, %r19, intr_restore /* if preempt_count > 0 */ nop /* prev insn branched backwards */ /* check if we interrupted a critical path */ @@ -1716,7 +1687,7 @@ dtlb_fault: .macro fork_like name ENTRY_CFI(sys_\name\()_wrapper) - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 + mfctl %cr30,%r1 ldo TASK_REGS(%r1),%r1 reg_save %r1 mfctl %cr27, %r28 @@ -1736,7 +1707,7 @@ ENTRY(child_return) BL schedule_tail, %r2 nop finish_child_return: - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 + mfctl %cr30,%r1 ldo TASK_REGS(%r1),%r1 /* get pt regs */ LDREG PT_CR27(%r1), %r3 @@ -1747,7 +1718,7 @@ finish_child_return: END(child_return) ENTRY_CFI(sys_rt_sigreturn_wrapper) - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 + mfctl %cr30,%r26 ldo TASK_REGS(%r26),%r26 /* get pt regs */ /* Don't save regs, we are going to restore them from sigcontext. */ STREG %r2, -RP_OFFSET(%r30) @@ -1764,7 +1735,7 @@ ENTRY_CFI(sys_rt_sigreturn_wrapper) LDREG -RP_OFFSET(%r30), %r2 /* FIXME: I think we need to restore a few more things here. */ - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 + mfctl %cr30,%r1 ldo TASK_REGS(%r1),%r1 /* get pt regs */ reg_restore %r1 @@ -1783,9 +1754,7 @@ ENTRY(syscall_exit) */ /* save return value now */ - mfctl %cr30, %r1 - LDREG TI_TASK(%r1),%r1 STREG %r28,TASK_PT_GR28(%r1) /* Seems to me that dp could be wrong here, if the syscall involved @@ -1796,13 +1765,14 @@ ENTRY(syscall_exit) syscall_check_resched: /* check for reschedule */ - - LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */ + mfctl %cr30,%r19 + LDREG TASK_TI_FLAGS(%r19),%r19 /* long */ bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */ .import do_signal,code syscall_check_sig: - LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 + mfctl %cr30,%r19 + LDREG TASK_TI_FLAGS(%r19),%r19 ldi (_TIF_USER_WORK_MASK & ~_TIF_NEED_RESCHED), %r26 and,COND(<>) %r19, %r26, %r0 b,n syscall_restore /* skip past if we've nothing to do */ @@ -1813,7 +1783,7 @@ syscall_do_signal: * consistent with all the relevant state of the process * before the syscall. We need to verify this. */ - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 + mfctl %cr30,%r1 ldo TASK_REGS(%r1), %r26 /* struct pt_regs *regs */ reg_save %r26 @@ -1824,17 +1794,17 @@ syscall_do_signal: BL do_notify_resume,%r2 ldi 1, %r25 /* long in_syscall = 1 */ - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 + mfctl %cr30,%r1 ldo TASK_REGS(%r1), %r20 /* reload pt_regs */ reg_restore %r20 b,n syscall_check_sig syscall_restore: - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 + mfctl %cr30,%r1 /* Are we being ptraced? */ - ldw TASK_FLAGS(%r1),%r19 + LDREG TASK_TI_FLAGS(%r1),%r19 ldi _TIF_SYSCALL_TRACE_MASK,%r2 and,COND(=) %r19,%r2,%r0 b,n syscall_restore_rfi @@ -1873,7 +1843,7 @@ syscall_restore: mtsp %r1,%sr5 /* Restore sr5 */ mtsp %r1,%sr6 /* Restore sr6 */ - depi 3,31,2,%r31 /* ensure return to user mode. */ + depi PRIV_USER,31,2,%r31 /* ensure return to user mode. */ #ifdef CONFIG_64BIT /* decide whether to reset the wide mode bit @@ -1949,7 +1919,7 @@ syscall_restore_rfi: STREG %r0,TASK_PT_SR2(%r1) LDREG TASK_PT_GR31(%r1),%r2 - depi 3,31,2,%r2 /* ensure return to user mode. */ + depi PRIV_USER,31,2,%r2 /* ensure return to user mode. */ STREG %r2,TASK_PT_IAOQ0(%r1) ldo 4(%r2),%r2 STREG %r2,TASK_PT_IAOQ1(%r1) @@ -1958,10 +1928,10 @@ syscall_restore_rfi: pt_regs_ok: LDREG TASK_PT_IAOQ0(%r1),%r2 - depi 3,31,2,%r2 /* ensure return to user mode. */ + depi PRIV_USER,31,2,%r2 /* ensure return to user mode. */ STREG %r2,TASK_PT_IAOQ0(%r1) LDREG TASK_PT_IAOQ1(%r1),%r2 - depi 3,31,2,%r2 + depi PRIV_USER,31,2,%r2 STREG %r2,TASK_PT_IAOQ1(%r1) b intr_restore copy %r25,%r16 diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index 7034227dbdf3..3370e347dde3 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -1062,6 +1062,38 @@ int pdc_mem_pdt_read_entries(struct pdc_mem_read_pdt *pret, } /** + * pdc_pim_toc11 - Fetch TOC PIM 1.1 data from firmware. + * @ret: pointer to return buffer + */ +int pdc_pim_toc11(struct pdc_toc_pim_11 *ret) +{ + int retval; + unsigned long flags; + + spin_lock_irqsave(&pdc_lock, flags); + retval = mem_pdc_call(PDC_PIM, PDC_PIM_TOC, __pa(pdc_result), + __pa(ret), sizeof(*ret)); + spin_unlock_irqrestore(&pdc_lock, flags); + return retval; +} + +/** + * pdc_pim_toc20 - Fetch TOC PIM 2.0 data from firmware. + * @ret: pointer to return buffer + */ +int pdc_pim_toc20(struct pdc_toc_pim_20 *ret) +{ + int retval; + unsigned long flags; + + spin_lock_irqsave(&pdc_lock, flags); + retval = mem_pdc_call(PDC_PIM, PDC_PIM_TOC, __pa(pdc_result), + __pa(ret), sizeof(*ret)); + spin_unlock_irqrestore(&pdc_lock, flags); + return retval; +} + +/** * pdc_tod_set - Set the Time-Of-Day clock. * @sec: The number of seconds since epoch. * @usec: The number of micro seconds. diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c index 0a1e75af5382..2a1f826b3def 100644 --- a/arch/parisc/kernel/ftrace.c +++ b/arch/parisc/kernel/ftrace.c @@ -15,6 +15,7 @@ #include <linux/uaccess.h> #include <linux/kprobes.h> #include <linux/ptrace.h> +#include <linux/jump_label.h> #include <asm/assembly.h> #include <asm/sections.h> @@ -24,6 +25,8 @@ #define __hot __section(".text.hot") #ifdef CONFIG_FUNCTION_GRAPH_TRACER +static DEFINE_STATIC_KEY_FALSE(ftrace_graph_enable); + /* * Hook the return address and push it in the stack of return addrs * in current thread info. @@ -48,25 +51,19 @@ static void __hot prepare_ftrace_return(unsigned long *parent, } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +static ftrace_func_t ftrace_func; + void notrace __hot ftrace_function_trampoline(unsigned long parent, unsigned long self_addr, unsigned long org_sp_gr3, struct ftrace_regs *fregs) { -#ifndef CONFIG_DYNAMIC_FTRACE - extern ftrace_func_t ftrace_trace_function; -#endif extern struct ftrace_ops *function_trace_op; - if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED && - ftrace_trace_function != ftrace_stub) - ftrace_trace_function(self_addr, parent, - function_trace_op, fregs); + ftrace_func(self_addr, parent, function_trace_op, fregs); #ifdef CONFIG_FUNCTION_GRAPH_TRACER - if (dereference_function_descriptor(ftrace_graph_return) != - dereference_function_descriptor(ftrace_stub) || - ftrace_graph_entry != ftrace_graph_entry_stub) { + if (static_branch_unlikely(&ftrace_graph_enable)) { unsigned long *parent_rp; /* calculate pointer to %rp in stack */ @@ -84,11 +81,13 @@ void notrace __hot ftrace_function_trampoline(unsigned long parent, #ifdef CONFIG_FUNCTION_GRAPH_TRACER int ftrace_enable_ftrace_graph_caller(void) { + static_key_enable(&ftrace_graph_enable.key); return 0; } int ftrace_disable_ftrace_graph_caller(void) { + static_key_enable(&ftrace_graph_enable.key); return 0; } #endif @@ -99,8 +98,10 @@ int __init ftrace_dyn_arch_init(void) { return 0; } + int ftrace_update_ftrace_func(ftrace_func_t func) { + ftrace_func = func; return 0; } diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index aa93d775c34d..b24f77748c22 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S @@ -35,7 +35,8 @@ END(boot_args) __HEAD .align 4 - .import init_thread_union,data + .import init_task,data + .import init_stack,data .import fault_vector_20,code /* IVA parisc 2.0 32 bit */ #ifndef CONFIG_64BIT .import fault_vector_11,code /* IVA parisc 1.1 32 bit */ @@ -123,12 +124,12 @@ $pgt_fill_loop: load32 start_parisc,%r11 /* And the initial task pointer */ - load32 init_thread_union,%r6 + load32 init_task,%r6 mtctl %r6,%cr30 /* And the stack pointer too */ - ldo THREAD_SZ_ALGN(%r6),%sp - + load32 init_stack,%sp + tophys_r1 %sp #if defined(CONFIG_64BIT) && defined(CONFIG_FUNCTION_TRACER) .import _mcount,data /* initialize mcount FPTR */ @@ -186,12 +187,11 @@ common_stext: #endif /*CONFIG_SMP*/ #ifdef CONFIG_64BIT - tophys_r1 %sp + mfctl %cr30,%r6 /* PCX-W2 firmware bug */ + tophys_r1 %r6 /* Save the rfi target address */ - ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 - tophys_r1 %r10 - std %r11, TASK_PT_GR11(%r10) + STREG %r11, TASK_PT_GR11(%r6) /* Switch to wide mode Superdome doesn't support narrow PDC ** calls. */ @@ -206,7 +206,6 @@ common_stext: ** Someday, palo might not do this for the Monarch either. */ 2: - mfctl %cr30,%r6 /* PCX-W2 firmware bug */ ldo PDC_PSW(%r0),%arg0 /* 21 */ ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */ @@ -216,13 +215,9 @@ common_stext: copy %r0,%arg3 stext_pdc_ret: + LDREG TASK_PT_GR11(%r6), %r11 + tovirt_r1 %r6 mtctl %r6,%cr30 /* restore task thread info */ - - /* restore rfi target address*/ - ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 - tophys_r1 %r10 - ldd TASK_PT_GR11(%r10), %r11 - tovirt_r1 %sp #endif /* PARANOID: clear user scratch/user space SR's */ @@ -287,7 +282,9 @@ aligned_rfi: load32 KERNEL_PSW,%r10 mtctl %r10,%ipsw - + + tovirt_r1 %sp + /* Jump through hyperspace to Virt Mode */ rfi nop @@ -343,12 +340,13 @@ smp_slave_stext: #endif /* Initialize the SP - monarch sets up smp_init_current_idle_task */ - load32 PA(smp_init_current_idle_task),%sp - LDREG 0(%sp),%sp /* load task address */ + load32 PA(smp_init_current_idle_task),%r6 + LDREG 0(%r6),%r6 + mtctl %r6,%cr30 + tophys_r1 %r6 + LDREG TASK_STACK(%r6),%sp tophys_r1 %sp - LDREG TASK_THREAD_INFO(%sp),%sp - mtctl %sp,%cr30 /* store in cr30 */ - ldo THREAD_SZ_ALGN(%sp),%sp + ldo FRAME_SIZE(%sp),%sp /* point CPU to kernel page tables */ load32 PA(swapper_pg_dir),%r4 diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 0d46b19dc4d3..eb18e16362f6 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -15,6 +15,7 @@ #include <linux/kernel_stat.h> #include <linux/seq_file.h> #include <linux/types.h> +#include <linux/sched/task_stack.h> #include <asm/io.h> #include <asm/softirq_stack.h> @@ -399,8 +400,7 @@ static inline void stack_overflow_check(struct pt_regs *regs) #ifdef CONFIG_DEBUG_STACKOVERFLOW #define STACK_MARGIN (256*6) - /* Our stack starts directly behind the thread_info struct. */ - unsigned long stack_start = (unsigned long) current_thread_info(); + unsigned long stack_start = (unsigned long) task_stack_page(current); unsigned long sp = regs->gr[30]; unsigned long stack_usage; unsigned int *last_usage; @@ -476,7 +476,7 @@ static void execute_on_irq_stack(void *func, unsigned long param1) union_ptr = &per_cpu(irq_stack_union, smp_processor_id()); irq_stack = (unsigned long) &union_ptr->stack; irq_stack = ALIGN(irq_stack + sizeof(irq_stack_union.slock), - 64); /* align for stack frame usage */ + FRAME_ALIGN); /* align for stack frame usage */ /* We may be called recursive. If we are already using the irq stack, * just continue to use it. Use spinlocks to serialize diff --git a/arch/parisc/kernel/pdt.c b/arch/parisc/kernel/pdt.c index fcc761b0e11b..e391b175f5ec 100644 --- a/arch/parisc/kernel/pdt.c +++ b/arch/parisc/kernel/pdt.c @@ -352,12 +352,10 @@ static int __init pdt_initcall(void) if (pdt_type == PDT_NONE) return -ENODEV; - kpdtd_task = kthread_create(pdt_mainloop, NULL, "kpdtd"); + kpdtd_task = kthread_run(pdt_mainloop, NULL, "kpdtd"); if (IS_ERR(kpdtd_task)) return PTR_ERR(kpdtd_task); - wake_up_process(kpdtd_task); - return 0; } diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 4f562dee65a2..ea3d83b6fb62 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -205,7 +205,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, /* Must exit via ret_from_kernel_thread in order * to call schedule_tail() */ - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; + cregs->ksp = (unsigned long) stack + FRAME_SIZE + PT_SZ_ALGN; cregs->kpc = (unsigned long) &ret_from_kernel_thread; /* * Copy function and argument to be called from @@ -228,7 +228,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, if (likely(usp)) cregs->gr[30] = usp; } - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; + cregs->ksp = (unsigned long) stack + FRAME_SIZE; cregs->kpc = (unsigned long) &child_return; /* Setup thread TLS area */ diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 1405b603b91b..171925285f3e 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -29,6 +29,7 @@ #include <linux/bitops.h> #include <linux/ftrace.h> #include <linux/cpu.h> +#include <linux/kgdb.h> #include <linux/atomic.h> #include <asm/current.h> @@ -69,7 +70,10 @@ enum ipi_message_type { IPI_CALL_FUNC, IPI_CPU_START, IPI_CPU_STOP, - IPI_CPU_TEST + IPI_CPU_TEST, +#ifdef CONFIG_KGDB + IPI_ENTER_KGDB, +#endif }; @@ -167,7 +171,12 @@ ipi_interrupt(int irq, void *dev_id) case IPI_CPU_TEST: smp_debug(100, KERN_DEBUG "CPU%d is alive!\n", this_cpu); break; - +#ifdef CONFIG_KGDB + case IPI_ENTER_KGDB: + smp_debug(100, KERN_DEBUG "CPU%d ENTER_KGDB\n", this_cpu); + kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); + break; +#endif default: printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n", this_cpu, which); @@ -219,13 +228,21 @@ static inline void send_IPI_allbutself(enum ipi_message_type op) { int i; - + + preempt_disable(); for_each_online_cpu(i) { if (i != smp_processor_id()) send_IPI_single(i, op); } + preempt_enable(); } +#ifdef CONFIG_KGDB +void kgdb_roundup_cpus(void) +{ + send_IPI_allbutself(IPI_ENTER_KGDB); +} +#endif inline void smp_send_stop(void) { send_IPI_allbutself(IPI_CPU_STOP); } @@ -322,7 +339,7 @@ int smp_boot_one_cpu(int cpuid, struct task_struct *idle) const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid); long timeout; - task_thread_info(idle)->cpu = cpuid; + idle->cpu = cpuid; /* Let _start know what logical CPU we're booting ** (offset into init_tasks[],cpu_data[]) diff --git a/arch/parisc/kernel/stacktrace.c b/arch/parisc/kernel/stacktrace.c index 34bf6d6bf6e8..6b4ca91932cf 100644 --- a/arch/parisc/kernel/stacktrace.c +++ b/arch/parisc/kernel/stacktrace.c @@ -2,45 +2,41 @@ /* * Stack trace management functions * - * Copyright (C) 2009 Helge Deller <deller@gmx.de> + * Copyright (C) 2009-2021 Helge Deller <deller@gmx.de> * based on arch/x86/kernel/stacktrace.c by Ingo Molnar <mingo@redhat.com> * and parisc unwind functions by Randolph Chung <tausq@debian.org> * * TODO: Userspace stacktrace (CONFIG_USER_STACKTRACE_SUPPORT) */ -#include <linux/module.h> #include <linux/stacktrace.h> #include <asm/unwind.h> -static void dump_trace(struct task_struct *task, struct stack_trace *trace) +static void notrace walk_stackframe(struct task_struct *task, + struct pt_regs *regs, bool (*fn)(void *, unsigned long), void *cookie) { struct unwind_frame_info info; unwind_frame_init_task(&info, task, NULL); - - /* unwind stack and save entries in stack_trace struct */ - trace->nr_entries = 0; - while (trace->nr_entries < trace->max_entries) { + while (1) { if (unwind_once(&info) < 0 || info.ip == 0) break; if (__kernel_text_address(info.ip)) - trace->entries[trace->nr_entries++] = info.ip; + if (!fn(cookie, info.ip)) + break; } } -/* - * Save stack-backtrace addresses into a stack_trace buffer. - */ -void save_stack_trace(struct stack_trace *trace) +void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie, + struct task_struct *task, struct pt_regs *regs) { - dump_trace(current, trace); + walk_stackframe(task, regs, consume_entry, cookie); } -EXPORT_SYMBOL_GPL(save_stack_trace); -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry, void *cookie, + struct task_struct *task) { - dump_trace(tsk, trace); + walk_stackframe(task, NULL, consume_entry, cookie); + return 1; } -EXPORT_SYMBOL_GPL(save_stack_trace_tsk); diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 5f12537318ab..2b34294517a1 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -409,10 +409,12 @@ long parisc_personality(unsigned long personality) static int FIX_O_NONBLOCK(int flags) { - if (flags & O_NONBLOCK_MASK_OUT) { - struct task_struct *tsk = current; - pr_warn_once("%s(%d) uses a deprecated O_NONBLOCK value.\n", - tsk->comm, tsk->pid); + if ((flags & O_NONBLOCK_MASK_OUT) && + !test_thread_flag(TIF_NONBLOCK_WARNING)) { + set_thread_flag(TIF_NONBLOCK_WARNING); + pr_warn("%s(%d) uses a deprecated O_NONBLOCK value." + " Please recompile with newer glibc.\n", + current->comm, current->pid); } return flags & ~O_NONBLOCK_MASK_OUT; } diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 3f24a0af1e04..ec9675f58435 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -78,7 +78,7 @@ ENTRY(linux_gateway_page) lws_entry: gate lws_start, %r0 /* increase privilege */ - depi 3, 31, 2, %r31 /* Ensure we return into user mode. */ + depi PRIV_USER, 31, 2, %r31 /* Ensure we return into user mode. */ /* Fill from 0xb8 to 0xe0 */ .rept 10 @@ -89,7 +89,7 @@ lws_entry: mechanism to work. DO NOT MOVE THIS CODE EVER! */ set_thread_pointer: gate .+8, %r0 /* increase privilege */ - depi 3, 31, 2, %r31 /* Ensure we return into user mode. */ + depi PRIV_USER, 31, 2, %r31 /* Ensure we return into user mode. */ be 0(%sr7,%r31) /* return to user space */ mtctl %r26, %cr27 /* move arg0 to the control register */ @@ -139,9 +139,9 @@ linux_gateway_entry: xor %r1,%r30,%r30 /* ye olde xor trick */ xor %r1,%r30,%r1 xor %r1,%r30,%r30 - - ldo THREAD_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */ + LDREG TASK_STACK(%r30),%r30 /* set up kernel stack */ + ldo FRAME_SIZE(%r30),%r30 /* N.B.: It is critical that we don't set sr7 to 0 until r30 * contains a valid kernel stack pointer. It is also * critical that we don't start using the kernel stack @@ -152,7 +152,6 @@ linux_gateway_entry: ssm PSW_SM_I, %r0 /* enable interrupts */ STREGM %r1,FRAME_SIZE(%r30) /* save r1 (usp) here for now */ mfctl %cr30,%r1 /* get task ptr in %r1 */ - LDREG TI_TASK(%r1),%r1 /* Save some registers for sigcontext and potential task switch (see entry.S for the details of which ones are @@ -207,7 +206,7 @@ linux_gateway_entry: /* Are we being ptraced? */ mfctl %cr30, %r1 - LDREG TI_FLAGS(%r1),%r1 + LDREG TASK_TI_FLAGS(%r1),%r1 ldi _TIF_SYSCALL_TRACE_MASK, %r19 and,COND(=) %r1, %r19, %r0 b,n .Ltracesys @@ -272,8 +271,7 @@ tracesys: * C bit set, a non-straced syscall entry results in C and D clear * in the saved PSW. */ - ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ - LDREG TI_TASK(%r1), %r1 + mfctl %cr30,%r1 /* get task ptr */ ssm 0,%r2 STREG %r2,TASK_PT_PSW(%r1) /* Lower 8 bits only!! */ mfsp %sr0,%r2 @@ -327,8 +325,7 @@ tracesys_next: */ copy %ret0,%r20 - ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ - LDREG TI_TASK(%r1), %r1 + mfctl %cr30,%r1 /* get task ptr */ LDREG TASK_PT_GR28(%r1), %r28 /* Restore return value */ LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */ LDREG TASK_PT_GR25(%r1), %r25 @@ -385,16 +382,14 @@ tracesys_next: makes a direct call to syscall_trace. */ tracesys_exit: - ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ - LDREG TI_TASK(%r1), %r1 + mfctl %cr30,%r1 /* get task ptr */ #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #endif ldo TASK_REGS(%r1),%r26 BL do_syscall_trace_exit,%r2 STREG %r28,TASK_PT_GR28(%r1) /* save return value now */ - ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ - LDREG TI_TASK(%r1), %r1 + mfctl %cr30,%r1 /* get task ptr */ LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */ ldil L%syscall_exit,%r1 @@ -407,8 +402,7 @@ tracesys_exit: ldo R%tracesys_sigexit(%r2),%r2 tracesys_sigexit: - ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ - LDREG TI_TASK(%r1), %r1 + mfctl %cr30,%r1 /* get task ptr */ #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #endif diff --git a/arch/parisc/kernel/toc.c b/arch/parisc/kernel/toc.c new file mode 100644 index 000000000000..18327611cf8f --- /dev/null +++ b/arch/parisc/kernel/toc.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/kernel.h> +#include <linux/kgdb.h> +#include <linux/printk.h> +#include <linux/sched/debug.h> +#include <linux/delay.h> +#include <linux/reboot.h> + +#include <asm/pdc.h> +#include <asm/pdc_chassis.h> + +unsigned int __aligned(16) toc_lock = 1; + +static void toc20_to_pt_regs(struct pt_regs *regs, struct pdc_toc_pim_20 *toc) +{ + int i; + + regs->gr[0] = (unsigned long)toc->cr[22]; + + for (i = 1; i < 32; i++) + regs->gr[i] = (unsigned long)toc->gr[i]; + + for (i = 0; i < 8; i++) + regs->sr[i] = (unsigned long)toc->sr[i]; + + regs->iasq[0] = (unsigned long)toc->cr[17]; + regs->iasq[1] = (unsigned long)toc->iasq_back; + regs->iaoq[0] = (unsigned long)toc->cr[18]; + regs->iaoq[1] = (unsigned long)toc->iaoq_back; + + regs->sar = (unsigned long)toc->cr[11]; + regs->iir = (unsigned long)toc->cr[19]; + regs->isr = (unsigned long)toc->cr[20]; + regs->ior = (unsigned long)toc->cr[21]; +} + +static void toc11_to_pt_regs(struct pt_regs *regs, struct pdc_toc_pim_11 *toc) +{ + int i; + + regs->gr[0] = toc->cr[22]; + + for (i = 1; i < 32; i++) + regs->gr[i] = toc->gr[i]; + + for (i = 0; i < 8; i++) + regs->sr[i] = toc->sr[i]; + + regs->iasq[0] = toc->cr[17]; + regs->iasq[1] = toc->iasq_back; + regs->iaoq[0] = toc->cr[18]; + regs->iaoq[1] = toc->iaoq_back; + + regs->sar = toc->cr[11]; + regs->iir = toc->cr[19]; + regs->isr = toc->cr[20]; + regs->ior = toc->cr[21]; +} + +void notrace __noreturn __cold toc_intr(struct pt_regs *regs) +{ + struct pdc_toc_pim_20 pim_data20; + struct pdc_toc_pim_11 pim_data11; + + nmi_enter(); + + if (boot_cpu_data.cpu_type >= pcxu) { + if (pdc_pim_toc20(&pim_data20)) + panic("Failed to get PIM data"); + toc20_to_pt_regs(regs, &pim_data20); + } else { + if (pdc_pim_toc11(&pim_data11)) + panic("Failed to get PIM data"); + toc11_to_pt_regs(regs, &pim_data11); + } + +#ifdef CONFIG_KGDB + if (atomic_read(&kgdb_active) != -1) + kgdb_nmicallback(raw_smp_processor_id(), regs); + kgdb_handle_exception(9, SIGTRAP, 0, regs); +#endif + show_regs(regs); + + /* give other CPUs time to show their backtrace */ + mdelay(2000); + machine_restart("TOC"); + + /* should never reach this */ + panic("TOC"); +} + +static __init int setup_toc(void) +{ + unsigned int csum = 0; + unsigned long toc_code = (unsigned long)dereference_function_descriptor(toc_handler); + int i; + + PAGE0->vec_toc = __pa(toc_code) & 0xffffffff; +#ifdef CONFIG_64BIT + PAGE0->vec_toc_hi = __pa(toc_code) >> 32; +#endif + PAGE0->vec_toclen = toc_handler_size; + + for (i = 0; i < toc_handler_size/4; i++) + csum += ((u32 *)toc_code)[i]; + toc_handler_csum = -csum; + pr_info("TOC handler registered\n"); + return 0; +} +early_initcall(setup_toc); diff --git a/arch/parisc/kernel/toc_asm.S b/arch/parisc/kernel/toc_asm.S new file mode 100644 index 000000000000..e94ba8044190 --- /dev/null +++ b/arch/parisc/kernel/toc_asm.S @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* TOC (Transfer of Control) handler. */ + + .level 1.1 + +#include <asm/assembly.h> +#include <asm/psw.h> +#include <linux/threads.h> +#include <linux/linkage.h> + + .text + .import toc_intr,code + .import toc_lock,data + .align 16 +ENTRY_CFI(toc_handler) + /* + * synchronize CPUs and obtain offset + * for stack setup. + */ + load32 PA(toc_lock),%r1 +0: ldcw,co 0(%r1),%r2 + cmpib,= 0,%r2,0b + nop + addi 1,%r2,%r4 + stw %r4,0(%r1) + addi -1,%r2,%r4 + + load32 PA(toc_stack),%sp + /* + * deposit CPU number into stack address, + * so every CPU will have its own stack. + */ + SHLREG %r4,14,%r4 + add %r4,%sp,%sp + + /* + * setup pt_regs on stack and save the + * floating point registers. PIM_TOC doesn't + * save fp registers, so we're doing it here. + */ + copy %sp,%arg0 + ldo PT_SZ_ALGN(%sp), %sp + + /* clear pt_regs */ + copy %arg0,%r1 +0: cmpb,<<,n %r1,%sp,0b + stw,ma %r0,4(%r1) + + ldo PT_FR0(%arg0),%r25 + save_fp %r25 + + /* go virtual */ + load32 PA(swapper_pg_dir),%r4 + mtctl %r4,%cr24 + mtctl %r4,%cr25 + + /* Clear sr4-sr7 */ + mtsp %r0, %sr4 + mtsp %r0, %sr5 + mtsp %r0, %sr6 + mtsp %r0, %sr7 + + tovirt_r1 %sp + tovirt_r1 %arg0 + virt_map + + loadgp + +#ifdef CONFIG_64BIT + ldo -16(%sp),%r29 +#endif + load32 toc_intr,%r1 + be 0(%sr7,%r1) + nop +ENDPROC_CFI(toc_handler) + + /* + * keep this checksum here, as it is part of the toc_handler + * spanned by toc_handler_size (all words in toc_handler are + * added in PDC and the sum must equal to zero. + */ +SYM_DATA(toc_handler_csum, .long 0) +SYM_DATA(toc_handler_size, .long . - toc_handler) + + __PAGE_ALIGNED_BSS + .align 64 +SYM_DATA(toc_stack, .block 16384*NR_CPUS) diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 747c328fb886..690e6abcaf22 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -30,6 +30,7 @@ #include <linux/ratelimit.h> #include <linux/uaccess.h> #include <linux/kdebug.h> +#include <linux/kfence.h> #include <asm/assembly.h> #include <asm/io.h> @@ -143,7 +144,7 @@ void show_regs(struct pt_regs *regs) printk("%s IIR: %08lx ISR: " RFMT " IOR: " RFMT "\n", level, regs->iir, regs->isr, regs->ior); printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n", - level, current_thread_info()->cpu, cr30, cr31); + level, task_cpu(current), cr30, cr31); printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28); if (user) { @@ -787,6 +788,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs) /* Clean up and return if in exception table. */ if (fixup_exception(regs)) return; + /* Clean up and return if handled by kfence. */ + if (kfence_handle_page_fault(fault_address, + parisc_acctyp(code, regs->iir) == VM_WRITE, regs)) + return; pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); parisc_terminate("Kernel Fault", regs, code, fault_address); } diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index 87ae476d1c4f..42acc3b52017 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -14,6 +14,7 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/sort.h> +#include <linux/sched/task_stack.h> #include <linux/uaccess.h> #include <asm/assembly.h> @@ -21,6 +22,8 @@ #include <asm/ptrace.h> #include <asm/unwind.h> +#include <asm/switch_to.h> +#include <asm/sections.h> /* #define DEBUG 1 */ #ifdef DEBUG @@ -203,6 +206,11 @@ int __init unwind_init(void) return 0; } +static bool pc_is_kernel_fn(unsigned long pc, void *fn) +{ + return (unsigned long)dereference_kernel_function_descriptor(fn) == pc; +} + static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size) { /* @@ -221,7 +229,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int extern void * const _call_on_stack; #endif /* CONFIG_IRQSTACKS */ - if (pc == (unsigned long) &handle_interruption) { + if (pc_is_kernel_fn(pc, handle_interruption)) { struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); dbg("Unwinding through handle_interruption()\n"); info->prev_sp = regs->gr[30]; @@ -229,13 +237,13 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int return 1; } - if (pc == (unsigned long) &ret_from_kernel_thread || - pc == (unsigned long) &syscall_exit) { + if (pc_is_kernel_fn(pc, ret_from_kernel_thread) || + pc_is_kernel_fn(pc, syscall_exit)) { info->prev_sp = info->prev_ip = 0; return 1; } - if (pc == (unsigned long) &intr_return) { + if (pc_is_kernel_fn(pc, intr_return)) { struct pt_regs *regs; dbg("Found intr_return()\n"); @@ -246,20 +254,20 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int return 1; } - if (pc == (unsigned long) &_switch_to_ret) { + if (pc_is_kernel_fn(pc, _switch_to) || + pc_is_kernel_fn(pc, _switch_to_ret)) { info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); return 1; } #ifdef CONFIG_IRQSTACKS - if (pc == (unsigned long) &_call_on_stack) { + if (pc_is_kernel_fn(pc, _call_on_stack)) { info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ); info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET); return 1; } #endif - return 0; } @@ -292,17 +300,15 @@ static void unwind_frame_regs(struct unwind_frame_info *info) info->prev_sp = sp - 64; info->prev_ip = 0; - /* The stack is at the end inside the thread_union - * struct. If we reach data, we have reached the - * beginning of the stack and should stop unwinding. */ - if (info->prev_sp >= (unsigned long) task_thread_info(info->t) && - info->prev_sp < ((unsigned long) task_thread_info(info->t) - + THREAD_SZ_ALGN)) { + /* Check if stack is inside kernel stack area */ + if ((info->prev_sp - (unsigned long) task_stack_page(info->t)) + >= THREAD_SIZE) { info->prev_sp = 0; break; } - if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) + if (copy_from_kernel_nofault(&tmp, + (void *)info->prev_sp - RP_OFFSET, sizeof(tmp))) break; info->prev_ip = tmp; sp = info->prev_sp; diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c index 9ac683bf6ae7..36a314199074 100644 --- a/arch/parisc/lib/bitops.c +++ b/arch/parisc/lib/bitops.c @@ -18,7 +18,7 @@ arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { #endif #ifdef CONFIG_64BIT -unsigned long __xchg64(unsigned long x, volatile unsigned long *ptr) +unsigned long notrace __xchg64(unsigned long x, volatile unsigned long *ptr) { unsigned long temp, flags; @@ -30,7 +30,7 @@ unsigned long __xchg64(unsigned long x, volatile unsigned long *ptr) } #endif -unsigned long __xchg32(int x, volatile int *ptr) +unsigned long notrace __xchg32(int x, volatile int *ptr) { unsigned long flags; long temp; @@ -43,7 +43,7 @@ unsigned long __xchg32(int x, volatile int *ptr) } -unsigned long __xchg8(char x, volatile char *ptr) +unsigned long notrace __xchg8(char x, volatile char *ptr) { unsigned long flags; long temp; @@ -56,7 +56,7 @@ unsigned long __xchg8(char x, volatile char *ptr) } -u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new) +u64 notrace __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new) { unsigned long flags; u64 prev; @@ -68,7 +68,7 @@ u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new) return prev; } -unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new) +unsigned long notrace __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new) { unsigned long flags; unsigned int prev; @@ -80,7 +80,7 @@ unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsign return (unsigned long)prev; } -u8 __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new) +u8 notrace __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new) { unsigned long flags; u8 prev; diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 716960f5d92e..4a6221b869fd 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -48,7 +48,7 @@ int show_unhandled_signals = 1; * VM_WRITE if write operation * VM_EXEC if execute operation */ -static unsigned long +unsigned long parisc_acctyp(unsigned long code, unsigned int inst) { if (code == 6 || code == 16) diff --git a/arch/parisc/mm/fixmap.c b/arch/parisc/mm/fixmap.c index 24426a7e1a5e..cc15d737fda6 100644 --- a/arch/parisc/mm/fixmap.c +++ b/arch/parisc/mm/fixmap.c @@ -20,12 +20,9 @@ void notrace set_fixmap(enum fixed_addresses idx, phys_addr_t phys) pte_t *pte; if (pmd_none(*pmd)) - pmd = pmd_alloc(NULL, pud, vaddr); - - pte = pte_offset_kernel(pmd, vaddr); - if (pte_none(*pte)) pte = pte_alloc_kernel(pmd, vaddr); + pte = pte_offset_kernel(pmd, vaddr); set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX)); flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); } diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 3f7d6d5b56ac..1ae31db9988f 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -127,16 +127,12 @@ static void __init setup_bootmem(void) int j; for (j = i; j > 0; j--) { - physmem_range_t tmp; - if (pmem_ranges[j-1].start_pfn < pmem_ranges[j].start_pfn) { break; } - tmp = pmem_ranges[j-1]; - pmem_ranges[j-1] = pmem_ranges[j]; - pmem_ranges[j] = tmp; + swap(pmem_ranges[j-1], pmem_ranges[j]); } } @@ -842,9 +838,9 @@ void flush_tlb_all(void) { int do_recycle; - __inc_irq_stat(irq_tlb_count); do_recycle = 0; spin_lock(&sid_lock); + __inc_irq_stat(irq_tlb_count); if (dirty_space_ids > RECYCLE_THRESHOLD) { BUG_ON(recycle_inuse); /* FIXME: Use a semaphore/wait queue here */ get_dirty_sids(&recycle_ndirty,recycle_dirty_array); @@ -863,8 +859,8 @@ void flush_tlb_all(void) #else void flush_tlb_all(void) { - __inc_irq_stat(irq_tlb_count); spin_lock(&sid_lock); + __inc_irq_stat(irq_tlb_count); flush_tlb_all_local(NULL); recycle_sids(); spin_unlock(&sid_lock); diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h index 2413427e439c..d10150587d81 100644 --- a/include/linux/sched/task_stack.h +++ b/include/linux/sched/task_stack.h @@ -25,7 +25,11 @@ static inline void *task_stack_page(const struct task_struct *task) static inline unsigned long *end_of_stack(const struct task_struct *task) { +#ifdef CONFIG_STACK_GROWSUP + return (unsigned long *)((unsigned long)task->stack + THREAD_SIZE) - 1; +#else return task->stack; +#endif } #elif !defined(__HAVE_THREAD_FUNCTIONS) |