mirror of https://github.com/torvalds/linux.git
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:
commit
8cc8ea228c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue