Skip to content

Commit 8cc8ea2

Browse files
committed
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()
2 parents fdfa38e + f4edb5c commit 8cc8ea2

File tree

12 files changed

+178
-7
lines changed

12 files changed

+178
-7
lines changed

arch/parisc/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ config PARISC
3131
select HAVE_KERNEL_UNCOMPRESSED
3232
select HAVE_PCI
3333
select HAVE_PERF_EVENTS
34+
select HAVE_PERF_REGS
35+
select HAVE_PERF_USER_STACK_DUMP
36+
select PERF_USE_VMALLOC
3437
select HAVE_KERNEL_BZIP2
3538
select HAVE_KERNEL_GZIP
3639
select HAVE_KERNEL_LZ4
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
#ifndef __ASM_PARISC_PERF_EVENT_H
22
#define __ASM_PARISC_PERF_EVENT_H
33

4-
/* Empty, just to avoid compiling error */
4+
#include <asm/psw.h>
5+
6+
#define perf_arch_fetch_caller_regs(regs, __ip) { \
7+
(regs)->gr[0] = KERNEL_PSW; \
8+
(regs)->iaoq[0] = (__ip); \
9+
asm volatile("copy %%sp, %0\n":"=r"((regs)->gr[30])); \
10+
}
511

612
#endif /* __ASM_PARISC_PERF_EVENT_H */

arch/parisc/include/uapi/asm/ioctls.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
#define TCSETS _IOW('T', 17, struct termios) /* TCSETATTR */
1111
#define TCSETSW _IOW('T', 18, struct termios) /* TCSETATTRD */
1212
#define TCSETSF _IOW('T', 19, struct termios) /* TCSETATTRF */
13-
#define TCGETA _IOR('T', 1, struct termio)
14-
#define TCSETA _IOW('T', 2, struct termio)
15-
#define TCSETAW _IOW('T', 3, struct termio)
16-
#define TCSETAF _IOW('T', 4, struct termio)
13+
#define TCGETA 0x40125401
14+
#define TCSETA 0x80125402
15+
#define TCSETAW 0x80125403
16+
#define TCSETAF 0x80125404
1717
#define TCSBRK _IO('T', 5)
1818
#define TCXONC _IO('T', 6)
1919
#define TCFLSH _IO('T', 7)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2+
#ifndef _UAPI_ASM_PARISC_PERF_REGS_H
3+
#define _UAPI_ASM_PARISC_PERF_REGS_H
4+
5+
/* see struct user_regs_struct */
6+
enum perf_event_parisc_regs {
7+
PERF_REG_PARISC_R0, /* PSW is in gr[0] */
8+
PERF_REG_PARISC_R1,
9+
PERF_REG_PARISC_R2,
10+
PERF_REG_PARISC_R3,
11+
PERF_REG_PARISC_R4,
12+
PERF_REG_PARISC_R5,
13+
PERF_REG_PARISC_R6,
14+
PERF_REG_PARISC_R7,
15+
PERF_REG_PARISC_R8,
16+
PERF_REG_PARISC_R9,
17+
PERF_REG_PARISC_R10,
18+
PERF_REG_PARISC_R11,
19+
PERF_REG_PARISC_R12,
20+
PERF_REG_PARISC_R13,
21+
PERF_REG_PARISC_R14,
22+
PERF_REG_PARISC_R15,
23+
PERF_REG_PARISC_R16,
24+
PERF_REG_PARISC_R17,
25+
PERF_REG_PARISC_R18,
26+
PERF_REG_PARISC_R19,
27+
PERF_REG_PARISC_R20,
28+
PERF_REG_PARISC_R21,
29+
PERF_REG_PARISC_R22,
30+
PERF_REG_PARISC_R23,
31+
PERF_REG_PARISC_R24,
32+
PERF_REG_PARISC_R25,
33+
PERF_REG_PARISC_R26,
34+
PERF_REG_PARISC_R27,
35+
PERF_REG_PARISC_R28,
36+
PERF_REG_PARISC_R29,
37+
PERF_REG_PARISC_R30,
38+
PERF_REG_PARISC_R31,
39+
40+
PERF_REG_PARISC_SR0,
41+
PERF_REG_PARISC_SR1,
42+
PERF_REG_PARISC_SR2,
43+
PERF_REG_PARISC_SR3,
44+
PERF_REG_PARISC_SR4,
45+
PERF_REG_PARISC_SR5,
46+
PERF_REG_PARISC_SR6,
47+
PERF_REG_PARISC_SR7,
48+
49+
PERF_REG_PARISC_IAOQ0,
50+
PERF_REG_PARISC_IAOQ1,
51+
PERF_REG_PARISC_IASQ0,
52+
PERF_REG_PARISC_IASQ1,
53+
54+
PERF_REG_PARISC_SAR, /* CR11 */
55+
PERF_REG_PARISC_IIR, /* CR19 */
56+
PERF_REG_PARISC_ISR, /* CR20 */
57+
PERF_REG_PARISC_IOR, /* CR21 */
58+
PERF_REG_PARISC_IPSW, /* CR22 */
59+
60+
PERF_REG_PARISC_MAX
61+
};
62+
63+
#endif /* _UAPI_ASM_PARISC_PERF_REGS_H */

arch/parisc/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += topology.o
3838
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
3939
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
4040
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
41+
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_regs.o
4142
obj-$(CONFIG_KGDB) += kgdb.o
4243
obj-$(CONFIG_KPROBES) += kprobes.o
4344
obj-$(CONFIG_KEXEC_CORE) += kexec.o relocate_kernel.o

arch/parisc/kernel/drivers.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,7 @@ static __init int qemu_print_iodc_data(struct device *lin_dev, void *data)
995995
struct pdc_system_map_mod_info pdc_mod_info;
996996
struct pdc_module_path mod_path;
997997

998+
memset(&iodc_data, 0, sizeof(iodc_data));
998999
status = pdc_iodc_read(&count, hpa, 0,
9991000
&iodc_data, sizeof(iodc_data));
10001001
if (status != PDC_OK) {
@@ -1012,6 +1013,11 @@ static __init int qemu_print_iodc_data(struct device *lin_dev, void *data)
10121013

10131014
mod_index = 0;
10141015
do {
1016+
/* initialize device path for old machines */
1017+
memset(&mod_path, 0xff, sizeof(mod_path));
1018+
get_node_path(dev->dev.parent, &mod_path.path);
1019+
mod_path.path.mod = dev->hw_path;
1020+
memset(&pdc_mod_info, 0, sizeof(pdc_mod_info));
10151021
status = pdc_system_map_find_mods(&pdc_mod_info,
10161022
&mod_path, mod_index++);
10171023
} while (status == PDC_OK && pdc_mod_info.mod_addr != hpa);

arch/parisc/kernel/firmware.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,8 @@ int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
464464
unsigned long flags;
465465

466466
spin_lock_irqsave(&pdc_lock, flags);
467-
retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
467+
memcpy(pdc_result2, mod_path, sizeof(*mod_path));
468+
retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
468469
__pa(pdc_result2), mod_index);
469470
convert_to_wide(pdc_result);
470471
memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info));

arch/parisc/kernel/perf_event.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Performance event support for parisc
4+
*
5+
* Copyright (C) 2025 by Helge Deller <[email protected]>
6+
*/
7+
8+
#include <linux/kernel.h>
9+
#include <linux/perf_event.h>
10+
#include <asm/unwind.h>
11+
12+
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
13+
struct pt_regs *regs)
14+
{
15+
16+
struct unwind_frame_info info;
17+
18+
unwind_frame_init_task(&info, current, NULL);
19+
while (1) {
20+
if (unwind_once(&info) < 0 || info.ip == 0)
21+
break;
22+
23+
if (!__kernel_text_address(info.ip) ||
24+
perf_callchain_store(entry, info.ip))
25+
return;
26+
}
27+
}

arch/parisc/kernel/perf_regs.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/* Copyright (C) 2025 by Helge Deller <[email protected]> */
4+
5+
#include <linux/perf_event.h>
6+
#include <linux/perf_regs.h>
7+
#include <asm/ptrace.h>
8+
9+
u64 perf_reg_value(struct pt_regs *regs, int idx)
10+
{
11+
switch (idx) {
12+
case PERF_REG_PARISC_R0 ... PERF_REG_PARISC_R31:
13+
return regs->gr[idx - PERF_REG_PARISC_R0];
14+
case PERF_REG_PARISC_SR0 ... PERF_REG_PARISC_SR7:
15+
return regs->sr[idx - PERF_REG_PARISC_SR0];
16+
case PERF_REG_PARISC_IASQ0 ... PERF_REG_PARISC_IASQ1:
17+
return regs->iasq[idx - PERF_REG_PARISC_IASQ0];
18+
case PERF_REG_PARISC_IAOQ0 ... PERF_REG_PARISC_IAOQ1:
19+
return regs->iasq[idx - PERF_REG_PARISC_IAOQ0];
20+
case PERF_REG_PARISC_SAR: /* CR11 */
21+
return regs->sar;
22+
case PERF_REG_PARISC_IIR: /* CR19 */
23+
return regs->iir;
24+
case PERF_REG_PARISC_ISR: /* CR20 */
25+
return regs->isr;
26+
case PERF_REG_PARISC_IOR: /* CR21 */
27+
return regs->ior;
28+
case PERF_REG_PARISC_IPSW: /* CR22 */
29+
return regs->ipsw;
30+
};
31+
WARN_ON_ONCE((u32)idx >= PERF_REG_PARISC_MAX);
32+
return 0;
33+
}
34+
35+
#define REG_RESERVED (~((1ULL << PERF_REG_PARISC_MAX) - 1))
36+
37+
int perf_reg_validate(u64 mask)
38+
{
39+
if (!mask || mask & REG_RESERVED)
40+
return -EINVAL;
41+
42+
return 0;
43+
}
44+
45+
u64 perf_reg_abi(struct task_struct *task)
46+
{
47+
if (!IS_ENABLED(CONFIG_64BIT))
48+
return PERF_SAMPLE_REGS_ABI_32;
49+
50+
if (test_tsk_thread_flag(task, TIF_32BIT))
51+
return PERF_SAMPLE_REGS_ABI_32;
52+
53+
return PERF_SAMPLE_REGS_ABI_64;
54+
}
55+
56+
void perf_get_regs_user(struct perf_regs *regs_user,
57+
struct pt_regs *regs)
58+
{
59+
regs_user->regs = task_pt_regs(current);
60+
regs_user->abi = perf_reg_abi(current);
61+
}

arch/parisc/kernel/traps.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/uaccess.h>
3232
#include <linux/kdebug.h>
3333
#include <linux/kfence.h>
34+
#include <linux/perf_event.h>
3435

3536
#include <asm/assembly.h>
3637
#include <asm/io.h>
@@ -633,6 +634,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
633634
/* Assist Exception Trap, i.e. floating point exception. */
634635
die_if_kernel("Floating point exception", regs, 0); /* quiet */
635636
__inc_irq_stat(irq_fpassist_count);
637+
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0);
636638
handle_fpe(regs);
637639
return;
638640

0 commit comments

Comments
 (0)