parisc architecture updates for kernel v6.18-rc1:

Minor enhancements and fixes, specifically:
 - report emulation and alignment faults via perf
 - add initial kernel-side support for perf_events
 - small initialization fixes in the parisc firmware layer
 - adjust TC* constants and avoid referencing termio structs to avoid
   userspace build errors.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCaOjZoAAKCRD3ErUQojoP
 X3cJAQCoSmeEmrWePAQQg/OkUntwkqxb7JEkmzJ6jqR7Cr9ncAD+NKlOiFSRkAvl
 FSGG3YZ/oqDSVvjkIGbhCDp16H/pGg4=
 =EHkQ
 -----END PGP SIGNATURE-----

Merge tag 'parisc-for-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc updates from Helge Deller:
 "Minor enhancements and fixes, specifically:

   - report emulation and alignment faults via perf

   - add initial kernel-side support for perf_events

   - small initialization fixes in the parisc firmware layer

   - adjust TC* constants and avoid referencing termio structs to avoid
     userspace build errors"

* tag 'parisc-for-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: Fix iodc and device path return values on old machines
  parisc: Firmware: Fix returned path for PDC_MODULE_FIND on older machines
  parisc: Add initial kernel-side perf_event support
  parisc: Report software alignment faults via perf
  parisc: Report emulation faults via perf
  parisc: don't reference obsolete termio struct for TC* constants
  parisc: Remove spurious if statement from raw_copy_from_user()
This commit is contained in:
Linus Torvalds 2025-10-10 10:01:55 -07:00
commit 8cc8ea228c
12 changed files with 178 additions and 7 deletions

View File

@ -31,6 +31,9 @@ config PARISC
select HAVE_KERNEL_UNCOMPRESSED
select HAVE_PCI
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select PERF_USE_VMALLOC
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZ4

View File

@ -1,6 +1,12 @@
#ifndef __ASM_PARISC_PERF_EVENT_H
#define __ASM_PARISC_PERF_EVENT_H
/* Empty, just to avoid compiling error */
#include <asm/psw.h>
#define perf_arch_fetch_caller_regs(regs, __ip) { \
(regs)->gr[0] = KERNEL_PSW; \
(regs)->iaoq[0] = (__ip); \
asm volatile("copy %%sp, %0\n":"=r"((regs)->gr[30])); \
}
#endif /* __ASM_PARISC_PERF_EVENT_H */

View File

@ -10,10 +10,10 @@
#define TCSETS _IOW('T', 17, struct termios) /* TCSETATTR */
#define TCSETSW _IOW('T', 18, struct termios) /* TCSETATTRD */
#define TCSETSF _IOW('T', 19, struct termios) /* TCSETATTRF */
#define TCGETA _IOR('T', 1, struct termio)
#define TCSETA _IOW('T', 2, struct termio)
#define TCSETAW _IOW('T', 3, struct termio)
#define TCSETAF _IOW('T', 4, struct termio)
#define TCGETA 0x40125401
#define TCSETA 0x80125402
#define TCSETAW 0x80125403
#define TCSETAF 0x80125404
#define TCSBRK _IO('T', 5)
#define TCXONC _IO('T', 6)
#define TCFLSH _IO('T', 7)

View File

@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_ASM_PARISC_PERF_REGS_H
#define _UAPI_ASM_PARISC_PERF_REGS_H
/* see struct user_regs_struct */
enum perf_event_parisc_regs {
PERF_REG_PARISC_R0, /* PSW is in gr[0] */
PERF_REG_PARISC_R1,
PERF_REG_PARISC_R2,
PERF_REG_PARISC_R3,
PERF_REG_PARISC_R4,
PERF_REG_PARISC_R5,
PERF_REG_PARISC_R6,
PERF_REG_PARISC_R7,
PERF_REG_PARISC_R8,
PERF_REG_PARISC_R9,
PERF_REG_PARISC_R10,
PERF_REG_PARISC_R11,
PERF_REG_PARISC_R12,
PERF_REG_PARISC_R13,
PERF_REG_PARISC_R14,
PERF_REG_PARISC_R15,
PERF_REG_PARISC_R16,
PERF_REG_PARISC_R17,
PERF_REG_PARISC_R18,
PERF_REG_PARISC_R19,
PERF_REG_PARISC_R20,
PERF_REG_PARISC_R21,
PERF_REG_PARISC_R22,
PERF_REG_PARISC_R23,
PERF_REG_PARISC_R24,
PERF_REG_PARISC_R25,
PERF_REG_PARISC_R26,
PERF_REG_PARISC_R27,
PERF_REG_PARISC_R28,
PERF_REG_PARISC_R29,
PERF_REG_PARISC_R30,
PERF_REG_PARISC_R31,
PERF_REG_PARISC_SR0,
PERF_REG_PARISC_SR1,
PERF_REG_PARISC_SR2,
PERF_REG_PARISC_SR3,
PERF_REG_PARISC_SR4,
PERF_REG_PARISC_SR5,
PERF_REG_PARISC_SR6,
PERF_REG_PARISC_SR7,
PERF_REG_PARISC_IAOQ0,
PERF_REG_PARISC_IAOQ1,
PERF_REG_PARISC_IASQ0,
PERF_REG_PARISC_IASQ1,
PERF_REG_PARISC_SAR, /* CR11 */
PERF_REG_PARISC_IIR, /* CR19 */
PERF_REG_PARISC_ISR, /* CR20 */
PERF_REG_PARISC_IOR, /* CR21 */
PERF_REG_PARISC_IPSW, /* CR22 */
PERF_REG_PARISC_MAX
};
#endif /* _UAPI_ASM_PARISC_PERF_REGS_H */

View File

@ -38,6 +38,7 @@ obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += topology.o
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_regs.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_KEXEC_CORE) += kexec.o relocate_kernel.o

View File

@ -995,6 +995,7 @@ static __init int qemu_print_iodc_data(struct device *lin_dev, void *data)
struct pdc_system_map_mod_info pdc_mod_info;
struct pdc_module_path mod_path;
memset(&iodc_data, 0, sizeof(iodc_data));
status = pdc_iodc_read(&count, hpa, 0,
&iodc_data, sizeof(iodc_data));
if (status != PDC_OK) {
@ -1012,6 +1013,11 @@ static __init int qemu_print_iodc_data(struct device *lin_dev, void *data)
mod_index = 0;
do {
/* initialize device path for old machines */
memset(&mod_path, 0xff, sizeof(mod_path));
get_node_path(dev->dev.parent, &mod_path.path);
mod_path.path.mod = dev->hw_path;
memset(&pdc_mod_info, 0, sizeof(pdc_mod_info));
status = pdc_system_map_find_mods(&pdc_mod_info,
&mod_path, mod_index++);
} while (status == PDC_OK && pdc_mod_info.mod_addr != hpa);

View File

@ -464,7 +464,8 @@ int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
unsigned long flags;
spin_lock_irqsave(&pdc_lock, flags);
retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
memcpy(pdc_result2, mod_path, sizeof(*mod_path));
retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
__pa(pdc_result2), mod_index);
convert_to_wide(pdc_result);
memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info));

View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Performance event support for parisc
*
* Copyright (C) 2025 by Helge Deller <deller@gmx.de>
*/
#include <linux/kernel.h>
#include <linux/perf_event.h>
#include <asm/unwind.h>
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
{
struct unwind_frame_info info;
unwind_frame_init_task(&info, current, NULL);
while (1) {
if (unwind_once(&info) < 0 || info.ip == 0)
break;
if (!__kernel_text_address(info.ip) ||
perf_callchain_store(entry, info.ip))
return;
}
}

View File

@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2025 by Helge Deller <deller@gmx.de> */
#include <linux/perf_event.h>
#include <linux/perf_regs.h>
#include <asm/ptrace.h>
u64 perf_reg_value(struct pt_regs *regs, int idx)
{
switch (idx) {
case PERF_REG_PARISC_R0 ... PERF_REG_PARISC_R31:
return regs->gr[idx - PERF_REG_PARISC_R0];
case PERF_REG_PARISC_SR0 ... PERF_REG_PARISC_SR7:
return regs->sr[idx - PERF_REG_PARISC_SR0];
case PERF_REG_PARISC_IASQ0 ... PERF_REG_PARISC_IASQ1:
return regs->iasq[idx - PERF_REG_PARISC_IASQ0];
case PERF_REG_PARISC_IAOQ0 ... PERF_REG_PARISC_IAOQ1:
return regs->iasq[idx - PERF_REG_PARISC_IAOQ0];
case PERF_REG_PARISC_SAR: /* CR11 */
return regs->sar;
case PERF_REG_PARISC_IIR: /* CR19 */
return regs->iir;
case PERF_REG_PARISC_ISR: /* CR20 */
return regs->isr;
case PERF_REG_PARISC_IOR: /* CR21 */
return regs->ior;
case PERF_REG_PARISC_IPSW: /* CR22 */
return regs->ipsw;
};
WARN_ON_ONCE((u32)idx >= PERF_REG_PARISC_MAX);
return 0;
}
#define REG_RESERVED (~((1ULL << PERF_REG_PARISC_MAX) - 1))
int perf_reg_validate(u64 mask)
{
if (!mask || mask & REG_RESERVED)
return -EINVAL;
return 0;
}
u64 perf_reg_abi(struct task_struct *task)
{
if (!IS_ENABLED(CONFIG_64BIT))
return PERF_SAMPLE_REGS_ABI_32;
if (test_tsk_thread_flag(task, TIF_32BIT))
return PERF_SAMPLE_REGS_ABI_32;
return PERF_SAMPLE_REGS_ABI_64;
}
void perf_get_regs_user(struct perf_regs *regs_user,
struct pt_regs *regs)
{
regs_user->regs = task_pt_regs(current);
regs_user->abi = perf_reg_abi(current);
}

View File

@ -31,6 +31,7 @@
#include <linux/uaccess.h>
#include <linux/kdebug.h>
#include <linux/kfence.h>
#include <linux/perf_event.h>
#include <asm/assembly.h>
#include <asm/io.h>
@ -633,6 +634,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
/* Assist Exception Trap, i.e. floating point exception. */
die_if_kernel("Floating point exception", regs, 0); /* quiet */
__inc_irq_stat(irq_fpassist_count);
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
handle_fpe(regs);
return;

View File

@ -13,6 +13,7 @@
#include <linux/uaccess.h>
#include <linux/sysctl.h>
#include <linux/unaligned.h>
#include <linux/perf_event.h>
#include <asm/hardirq.h>
#include <asm/traps.h>
#include "unaligned.h"
@ -378,6 +379,7 @@ void handle_unaligned(struct pt_regs *regs)
int ret = ERR_NOTHANDLED;
__inc_irq_stat(irq_unaligned_count);
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->ior);
/* log a message with pacing */
if (user_mode(regs)) {

View File

@ -41,7 +41,6 @@ unsigned long raw_copy_from_user(void *dst, const void __user *src,
mtsp(get_kernel_space(), SR_TEMP2);
/* Check region is user accessible */
if (start)
while (start < end) {
if (!prober_user(SR_TEMP1, start)) {
newlen = (start - (unsigned long) src);