From 77ed045e88e5cba6d8dec3c5c7cd52105c46b50b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 8 Dec 2023 13:50:35 +0100 Subject: s390/compat: change default for CONFIG_COMPAT to "n" 31 bit support has been removed from the kernel more than eight years ago. The last 31 bit distribution is many years older. There shouldn't be any 31 bit code around anymore. Therefore avoid providing an unused and only partially tested user space interface and change the default for CONFIG_COMPAT from "yes" to "no". Acked-by: Christian Borntraeger Signed-off-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/Kconfig | 6 ++++-- arch/s390/configs/zfcpdump_defconfig | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 8f39f0424796..3408b48423ad 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -443,7 +443,7 @@ config COMMAND_LINE_SIZE line. config COMPAT - def_bool y + def_bool n prompt "Kernel support for 31 bit emulation" select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION @@ -454,7 +454,9 @@ config COMPAT Select this option if you want to enable your system kernel to handle system-calls from ELF binaries for 31 bit ESA. This option (and some other stuff like libraries and such) is needed for - executing 31 bit applications. It is safe to say "Y". + executing 31 bit applications. + + If unsure say N. config SMP def_bool y diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig index 47028450eee1..30d2a1687665 100644 --- a/arch/s390/configs/zfcpdump_defconfig +++ b/arch/s390/configs/zfcpdump_defconfig @@ -10,7 +10,6 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CRASH_DUMP=y CONFIG_MARCH_Z13=y -# CONFIG_COMPAT is not set CONFIG_NR_CPUS=2 CONFIG_HZ_100=y # CONFIG_CHSC_SCH is not set -- cgit From 0130a0d3a61889060e912a533e996201c4d9a2e5 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Tue, 12 Dec 2023 13:59:42 +0100 Subject: s390/kexec: do not automatically select KEXEC option Following commit dccf78d39f10 ("kernel/Kconfig.kexec: drop select of KEXEC for CRASH_DUMP") also drop automatic KEXEC selection for s390 while set CONFIG_KEXEC=y explicitly for defconfig and debug_defconfig targets. zfcpdump_defconfig target gets CONFIG_KEXEC unset as result, which is right and consistent with CONFIG_KEXEC_FILE besides. Acked-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/Kconfig | 1 - arch/s390/configs/debug_defconfig | 1 + arch/s390/configs/defconfig | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/s390') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 3408b48423ad..fe565f3a3a91 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -216,7 +216,6 @@ config S390 select HAVE_VIRT_CPU_ACCOUNTING_IDLE select IOMMU_HELPER if PCI select IOMMU_SUPPORT if PCI - select KEXEC select MMU_GATHER_MERGE_VMAS select MMU_GATHER_NO_GATHER select MMU_GATHER_RCU_TABLE_FREE diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 6de44ede4e14..689970baf7ac 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -40,6 +40,7 @@ CONFIG_SCHED_AUTOGROUP=y CONFIG_EXPERT=y # CONFIG_SYSFS_SYSCALL is not set CONFIG_PROFILING=y +CONFIG_KEXEC=y CONFIG_KEXEC_FILE=y CONFIG_KEXEC_SIG=y CONFIG_CRASH_DUMP=y diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index bcae47da6b7c..229be2965e6a 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -38,6 +38,7 @@ CONFIG_SCHED_AUTOGROUP=y CONFIG_EXPERT=y # CONFIG_SYSFS_SYSCALL is not set CONFIG_PROFILING=y +CONFIG_KEXEC=y CONFIG_KEXEC_FILE=y CONFIG_KEXEC_SIG=y CONFIG_CRASH_DUMP=y -- cgit From 80df7d6af7f6d229b34cf237b2cc9024c07111cd Mon Sep 17 00:00:00 2001 From: Niklas Schnelle Date: Tue, 28 Nov 2023 16:22:49 +0100 Subject: s390/pci: fix max size calculation in zpci_memcpy_toio() The zpci_get_max_write_size() helper is used to determine the maximum size a PCI store or load can use at a given __iomem address. For the PCI block store the following restrictions apply: 1. The dst + len must not cross a 4K boundary in the (pseudo-)MMIO space 2. len must not exceed ZPCI_MAX_WRITE_SIZE 3. len must be a multiple of 8 bytes 4. The src address must be double word (8 byte) aligned 5. The dst address must be double word (8 byte) aligned Otherwise only a normal PCI store which takes its src value from a register can be used. For these PCI store restriction 1 still applies. Similarly 1 also applies to PCI loads. It turns out zpci_max_write_size() instead implements stricter conditions which prevents PCI block stores from being used where they can and should be used. In particular instead of conditions 4 and 5 it wrongly enforces both dst and src to be size aligned. This indirectly covers condition 1 but also prevents many legal PCI block stores. On top of the functional shortcomings the zpci_get_max_write_size() is misnamed as it is used for both read and write size calculations. Rename it to zpci_get_max_io_size() and implement the listed conditions explicitly. Reviewed-by: Matthew Rosato Fixes: cd24834130ac ("s390/pci: base support") Signed-off-by: Niklas Schnelle [agordeev@linux.ibm.com replaced spaces with tabs] Signed-off-by: Alexander Gordeev --- arch/s390/include/asm/pci_io.h | 32 ++++++++++++++++++-------------- arch/s390/pci/pci_mmio.c | 12 ++++++------ 2 files changed, 24 insertions(+), 20 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h index 287bb88f7698..2686bee800e3 100644 --- a/arch/s390/include/asm/pci_io.h +++ b/arch/s390/include/asm/pci_io.h @@ -11,6 +11,8 @@ /* I/O size constraints */ #define ZPCI_MAX_READ_SIZE 8 #define ZPCI_MAX_WRITE_SIZE 128 +#define ZPCI_BOUNDARY_SIZE (1 << 12) +#define ZPCI_BOUNDARY_MASK (ZPCI_BOUNDARY_SIZE - 1) /* I/O Map */ #define ZPCI_IOMAP_SHIFT 48 @@ -125,16 +127,18 @@ out: int zpci_write_block(volatile void __iomem *dst, const void *src, unsigned long len); -static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max) +static inline int zpci_get_max_io_size(u64 src, u64 dst, int len, int max) { - int count = len > max ? max : len, size = 1; + int offset = dst & ZPCI_BOUNDARY_MASK; + int size; - while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) { - dst = dst >> 1; - src = src >> 1; - size = size << 1; - } - return size; + size = min3(len, ZPCI_BOUNDARY_SIZE - offset, max); + if (IS_ALIGNED(src, 8) && IS_ALIGNED(dst, 8) && IS_ALIGNED(size, 8)) + return size; + + if (size >= 8) + return 8; + return rounddown_pow_of_two(size); } static inline int zpci_memcpy_fromio(void *dst, @@ -144,9 +148,9 @@ static inline int zpci_memcpy_fromio(void *dst, int size, rc = 0; while (n > 0) { - size = zpci_get_max_write_size((u64 __force) src, - (u64) dst, n, - ZPCI_MAX_READ_SIZE); + size = zpci_get_max_io_size((u64 __force) src, + (u64) dst, n, + ZPCI_MAX_READ_SIZE); rc = zpci_read_single(dst, src, size); if (rc) break; @@ -166,9 +170,9 @@ static inline int zpci_memcpy_toio(volatile void __iomem *dst, return -EINVAL; while (n > 0) { - size = zpci_get_max_write_size((u64 __force) dst, - (u64) src, n, - ZPCI_MAX_WRITE_SIZE); + size = zpci_get_max_io_size((u64 __force) dst, + (u64) src, n, + ZPCI_MAX_WRITE_SIZE); if (size > 8) /* main path */ rc = zpci_write_block(dst, src, size); else diff --git a/arch/s390/pci/pci_mmio.c b/arch/s390/pci/pci_mmio.c index 588089332931..a90499c087f0 100644 --- a/arch/s390/pci/pci_mmio.c +++ b/arch/s390/pci/pci_mmio.c @@ -97,9 +97,9 @@ static inline int __memcpy_toio_inuser(void __iomem *dst, return -EINVAL; while (n > 0) { - size = zpci_get_max_write_size((u64 __force) dst, - (u64 __force) src, n, - ZPCI_MAX_WRITE_SIZE); + size = zpci_get_max_io_size((u64 __force) dst, + (u64 __force) src, n, + ZPCI_MAX_WRITE_SIZE); if (size > 8) /* main path */ rc = __pcistb_mio_inuser(dst, src, size, &status); else @@ -242,9 +242,9 @@ static inline int __memcpy_fromio_inuser(void __user *dst, u8 status; while (n > 0) { - size = zpci_get_max_write_size((u64 __force) src, - (u64 __force) dst, n, - ZPCI_MAX_READ_SIZE); + size = zpci_get_max_io_size((u64 __force) src, + (u64 __force) dst, n, + ZPCI_MAX_READ_SIZE); rc = __pcilg_mio_inuser(dst, src, size, &status); if (rc) break; -- cgit From d124e484691a737e174474d230dc6a4b385ba3db Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 3 Jan 2024 13:15:13 +0100 Subject: s390/mm,fault: remove not needed tsk variable tsk is only used as an intermediate variable for current. Remove tsk and use current directly instead at the only place where it is used. Signed-off-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/mm/fault.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index ab4098886e56..ac4c78546d97 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -280,7 +280,6 @@ static void do_sigbus(struct pt_regs *regs) static void do_exception(struct pt_regs *regs, int access) { struct vm_area_struct *vma; - struct task_struct *tsk; unsigned long address; struct mm_struct *mm; enum fault_type type; @@ -289,7 +288,6 @@ static void do_exception(struct pt_regs *regs, int access) vm_fault_t fault; bool is_write; - tsk = current; /* * The instruction that caused the program check has * been nullified. Don't signal single step via SIGTRAP. @@ -297,7 +295,7 @@ static void do_exception(struct pt_regs *regs, int access) clear_thread_flag(TIF_PER_TRAP); if (kprobe_page_fault(regs, 14)) return; - mm = tsk->mm; + mm = current->mm; address = get_fault_address(regs); is_write = fault_is_write(regs); type = get_fault_type(regs); -- cgit From 74ca896113531c4a3bba278fd7991da743b7e63b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 5 Jan 2024 15:28:47 +0100 Subject: s390/fpu: remove __load_fpu_regs() export __load_fpu_regs() is only called from core kernel code. Therefore remove the not needed export. Signed-off-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/kernel/fpu.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/fpu.c b/arch/s390/kernel/fpu.c index 9e7c15fccfea..a4f3449cc814 100644 --- a/arch/s390/kernel/fpu.c +++ b/arch/s390/kernel/fpu.c @@ -208,7 +208,6 @@ void __load_fpu_regs(void) } clear_cpu_flag(CIF_FPU); } -EXPORT_SYMBOL(__load_fpu_regs); void load_fpu_regs(void) { -- cgit From ba69655fffdb8ada391494cfb8ddfe6e96784b79 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 9 Jan 2024 11:59:47 +0100 Subject: s390/ptrace: remove leftover comment The code which validates floating point control register contents was reworked with commit 702644249d3e ("s390/fpu: get rid of test_fp_ctl()"). There is still a comment which refers to the old implementation - remove it in order to avoid confusion. Signed-off-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/kernel/ptrace.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 2e6754b62b20..f1897a8bb221 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -917,7 +917,6 @@ static int s390_fpregs_set(struct task_struct *target, else memcpy(&fprs, target->thread.fpu.fprs, sizeof(fprs)); - /* If setting FPC, must validate it first. */ if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) { u32 ufpc[2] = { target->thread.fpu.fpc, 0 }; rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ufpc, -- cgit From 8d0e8a8aa3a1e844b7a969e9fe80937667507c6c Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Tue, 14 Nov 2023 10:53:22 +0100 Subject: s390/pai: rework paixxxx_getctr interface Simplify the interface for functions paicrypt_getctr() and paiext_getctr(). Change the first parameter from a pointer to a structure to a pointer to a structure member. The other members of the structure are not needed. No functional change. Signed-off-by: Thomas Richter Acked-by: Mete Durlu Signed-off-by: Alexander Gordeev --- arch/s390/kernel/perf_pai_crypto.c | 12 ++++++------ arch/s390/kernel/perf_pai_ext.c | 11 ++++++----- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c index 39a91b00438a..92156e14fc6f 100644 --- a/arch/s390/kernel/perf_pai_crypto.c +++ b/arch/s390/kernel/perf_pai_crypto.c @@ -111,11 +111,11 @@ static void paicrypt_event_destroy(struct perf_event *event) mutex_unlock(&pai_reserve_mutex); } -static u64 paicrypt_getctr(struct paicrypt_map *cpump, int nr, bool kernel) +static u64 paicrypt_getctr(unsigned long *page, int nr, bool kernel) { if (kernel) nr += PAI_CRYPTO_MAXCTR; - return cpump->page[nr]; + return page[nr]; } /* Read the counter values. Return value from location in CMP. For event @@ -129,13 +129,13 @@ static u64 paicrypt_getdata(struct perf_event *event, bool kernel) int i; if (event->attr.config != PAI_CRYPTO_BASE) { - return paicrypt_getctr(cpump, + return paicrypt_getctr(cpump->page, event->attr.config - PAI_CRYPTO_BASE, kernel); } for (i = 1; i <= paicrypt_cnt; i++) { - u64 val = paicrypt_getctr(cpump, i, kernel); + u64 val = paicrypt_getctr(cpump->page, i, kernel); if (!val) continue; @@ -383,9 +383,9 @@ static size_t paicrypt_copy(struct pai_userdata *userdata, u64 val = 0; if (!exclude_kernel) - val += paicrypt_getctr(cpump, i, true); + val += paicrypt_getctr(cpump->page, i, true); if (!exclude_user) - val += paicrypt_getctr(cpump, i, false); + val += paicrypt_getctr(cpump->page, i, false); if (val) { userdata[outidx].num = i; userdata[outidx].value = val; diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c index e7013a2e8960..9452205e6feb 100644 --- a/arch/s390/kernel/perf_pai_ext.c +++ b/arch/s390/kernel/perf_pai_ext.c @@ -276,9 +276,9 @@ static int paiext_event_init(struct perf_event *event) return 0; } -static u64 paiext_getctr(struct paiext_map *cpump, int nr) +static u64 paiext_getctr(unsigned long *area, int nr) { - return cpump->area[nr]; + return area[nr]; } /* Read the counter values. Return value from location in buffer. For event @@ -292,10 +292,11 @@ static u64 paiext_getdata(struct perf_event *event) int i; if (event->attr.config != PAI_NNPA_BASE) - return paiext_getctr(cpump, event->attr.config - PAI_NNPA_BASE); + return paiext_getctr(cpump->area, + event->attr.config - PAI_NNPA_BASE); for (i = 1; i <= paiext_cnt; i++) - sum += paiext_getctr(cpump, i); + sum += paiext_getctr(cpump->area, i); return sum; } @@ -392,7 +393,7 @@ static size_t paiext_copy(struct paiext_map *cpump) int i, outidx = 0; for (i = 1; i <= paiext_cnt; i++) { - u64 val = paiext_getctr(cpump, i); + u64 val = paiext_getctr(cpump->area, i); if (val) { userdata[outidx].num = i; -- cgit From 0578a54110ff28dc2b3830e90ad2dd9c1e065e90 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Tue, 14 Nov 2023 12:00:38 +0100 Subject: s390/pai_crypto: split function paicrypt_push_sample Split function paicrypt_push_sample() into two parts. The first part determines the number of bytes to store as raw data in the perf sample record. The second part stores the raw data in the perf event's ring buffer. No functional change. Signed-off-by: Thomas Richter Acked-by: Mete Durlu Signed-off-by: Alexander Gordeev --- arch/s390/kernel/perf_pai_crypto.c | 43 ++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c index 92156e14fc6f..ee8a011c46e9 100644 --- a/arch/s390/kernel/perf_pai_crypto.c +++ b/arch/s390/kernel/perf_pai_crypto.c @@ -373,8 +373,7 @@ static void paicrypt_del(struct perf_event *event, int flags) * 2 bytes: Number of counter * 8 bytes: Value of counter */ -static size_t paicrypt_copy(struct pai_userdata *userdata, - struct paicrypt_map *cpump, +static size_t paicrypt_copy(struct pai_userdata *userdata, unsigned long *page, bool exclude_user, bool exclude_kernel) { int i, outidx = 0; @@ -383,9 +382,9 @@ static size_t paicrypt_copy(struct pai_userdata *userdata, u64 val = 0; if (!exclude_kernel) - val += paicrypt_getctr(cpump->page, i, true); + val += paicrypt_getctr(page, i, true); if (!exclude_user) - val += paicrypt_getctr(cpump->page, i, false); + val += paicrypt_getctr(page, i, false); if (val) { userdata[outidx].num = i; userdata[outidx].value = val; @@ -395,25 +394,14 @@ static size_t paicrypt_copy(struct pai_userdata *userdata, return outidx * sizeof(struct pai_userdata); } -static int paicrypt_push_sample(void) +static int paicrypt_push_sample(size_t rawsize, struct paicrypt_map *cpump, + struct perf_event *event) { - struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); - struct paicrypt_map *cpump = mp->mapptr; - struct perf_event *event = cpump->event; struct perf_sample_data data; struct perf_raw_record raw; struct pt_regs regs; - size_t rawsize; int overflow; - if (!cpump->event) /* No event active */ - return 0; - rawsize = paicrypt_copy(cpump->save, cpump, - cpump->event->attr.exclude_user, - cpump->event->attr.exclude_kernel); - if (!rawsize) /* No incremented counters */ - return 0; - /* Setup perf sample */ memset(®s, 0, sizeof(regs)); memset(&raw, 0, sizeof(raw)); @@ -444,6 +432,25 @@ static int paicrypt_push_sample(void) return overflow; } +/* Check if there is data to be saved on schedule out of a task. */ +static int paicrypt_have_sample(void) +{ + struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); + struct paicrypt_map *cpump = mp->mapptr; + struct perf_event *event = cpump->event; + size_t rawsize; + int rc = 0; + + if (!event) /* No event active */ + return 0; + rawsize = paicrypt_copy(cpump->save, cpump->page, + cpump->event->attr.exclude_user, + cpump->event->attr.exclude_kernel); + if (rawsize) /* No incremented counters */ + rc = paicrypt_push_sample(rawsize, cpump, event); + return rc; +} + /* Called on schedule-in and schedule-out. No access to event structure, * but for sampling only event CRYPTO_ALL is allowed. */ @@ -453,7 +460,7 @@ static void paicrypt_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sch * results on schedule_out and if page was dirty, clear values. */ if (!sched_in) - paicrypt_push_sample(); + paicrypt_have_sample(); } /* Attribute definitions for paicrypt interface. As with other CPU -- cgit From cb1259b7b574bd90ef22dac2c6282327cdae31c6 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Wed, 15 Nov 2023 11:04:25 +0100 Subject: s390/pai: rework paiXXX_start and paiXXX_stop functions The PAI crypto counter and PAI NNPA counters start and stop functions are streamlined. Move the conditions to invoke start and stop functions to its respective function body and call them unconditionally. The start and stop functions now determine how to proceed. No functional change. Signed-off-by: Thomas Richter Acked-by: Mete Durlu Signed-off-by: Alexander Gordeev --- arch/s390/kernel/perf_pai_crypto.c | 29 ++++++++++++++--------------- arch/s390/kernel/perf_pai_ext.c | 35 ++++++++++++++++------------------- 2 files changed, 30 insertions(+), 34 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c index ee8a011c46e9..bf8a672b15a4 100644 --- a/arch/s390/kernel/perf_pai_crypto.c +++ b/arch/s390/kernel/perf_pai_crypto.c @@ -317,10 +317,14 @@ static void paicrypt_start(struct perf_event *event, int flags) * Events are added, deleted and re-added when 2 or more events * are active at the same time. */ - if (!event->hw.last_tag) { - event->hw.last_tag = 1; - sum = paicrypt_getall(event); /* Get current value */ - local64_set(&event->hw.prev_count, sum); + if (!event->attr.sample_period) { /* Counting */ + if (!event->hw.last_tag) { + event->hw.last_tag = 1; + sum = paicrypt_getall(event); /* Get current value */ + local64_set(&event->hw.prev_count, sum); + } + } else { /* Sampling */ + perf_sched_cb_inc(event->pmu); } } @@ -336,19 +340,18 @@ static int paicrypt_add(struct perf_event *event, int flags) local_ctl_set_bit(0, CR0_CRYPTOGRAPHY_COUNTER_BIT); } cpump->event = event; - if (flags & PERF_EF_START && !event->attr.sample_period) { - /* Only counting needs initial counter value */ + if (flags & PERF_EF_START) paicrypt_start(event, PERF_EF_RELOAD); - } event->hw.state = 0; - if (event->attr.sample_period) - perf_sched_cb_inc(event->pmu); return 0; } static void paicrypt_stop(struct perf_event *event, int flags) { - paicrypt_read(event); + if (!event->attr.sample_period) /* Counting */ + paicrypt_read(event); + else /* Sampling */ + perf_sched_cb_dec(event->pmu); event->hw.state = PERF_HES_STOPPED; } @@ -357,11 +360,7 @@ static void paicrypt_del(struct perf_event *event, int flags) struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); struct paicrypt_map *cpump = mp->mapptr; - if (event->attr.sample_period) - perf_sched_cb_dec(event->pmu); - if (!event->attr.sample_period) - /* Only counting needs to read counter */ - paicrypt_stop(event, PERF_EF_UPDATE); + paicrypt_stop(event, PERF_EF_UPDATE); if (--cpump->active_events == 0) { local_ctl_clear_bit(0, CR0_CRYPTOGRAPHY_COUNTER_BIT); WRITE_ONCE(S390_lowcore.ccd, 0); diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c index 9452205e6feb..275d4fd3fe38 100644 --- a/arch/s390/kernel/perf_pai_ext.c +++ b/arch/s390/kernel/perf_pai_ext.c @@ -321,11 +321,15 @@ static void paiext_start(struct perf_event *event, int flags) { u64 sum; - if (event->hw.last_tag) - return; - event->hw.last_tag = 1; - sum = paiext_getall(event); /* Get current value */ - local64_set(&event->hw.prev_count, sum); + if (!event->attr.sample_period) { /* Counting */ + if (!event->hw.last_tag) { + event->hw.last_tag = 1; + sum = paiext_getall(event); /* Get current value */ + local64_set(&event->hw.prev_count, sum); + } + } else { /* Sampling */ + perf_sched_cb_inc(event->pmu); + } } static int paiext_add(struct perf_event *event, int flags) @@ -342,21 +346,19 @@ static int paiext_add(struct perf_event *event, int flags) debug_sprintf_event(paiext_dbg, 4, "%s 1508 %llx acc %llx\n", __func__, S390_lowcore.aicd, pcb->acc); } - if (flags & PERF_EF_START && !event->attr.sample_period) { - /* Only counting needs initial counter value */ + cpump->event = event; + if (flags & PERF_EF_START) paiext_start(event, PERF_EF_RELOAD); - } event->hw.state = 0; - if (event->attr.sample_period) { - cpump->event = event; - perf_sched_cb_inc(event->pmu); - } return 0; } static void paiext_stop(struct perf_event *event, int flags) { - paiext_read(event); + if (!event->attr.sample_period) /* Counting */ + paiext_read(event); + else /* Sampling */ + perf_sched_cb_dec(event->pmu); event->hw.state = PERF_HES_STOPPED; } @@ -366,12 +368,7 @@ static void paiext_del(struct perf_event *event, int flags) struct paiext_map *cpump = mp->mapptr; struct paiext_cb *pcb = cpump->paiext_cb; - if (event->attr.sample_period) - perf_sched_cb_dec(event->pmu); - if (!event->attr.sample_period) { - /* Only counting needs to read counter */ - paiext_stop(event, PERF_EF_UPDATE); - } + paiext_stop(event, PERF_EF_UPDATE); if (--cpump->active_events == 0) { /* Disable CPU instruction lookup for PAIE1 control block */ local_ctl_clear_bit(0, CR0_PAI_EXTENSION_BIT); -- cgit From 0dade41d16132ac11ac9e3ac0b0313d438037224 Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Thu, 16 Nov 2023 10:43:14 +0100 Subject: s390/pai_ext: rework function paiext_copy argments Change the function paiext_copy() parameter from a pointer to a structure to two pointers to memory areas referenced. The other members of that structure are not needed. Signed-off-by: Thomas Richter Acked-by: Mete Durlu Signed-off-by: Alexander Gordeev --- arch/s390/kernel/perf_pai_ext.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c index 275d4fd3fe38..e2e1ce2de695 100644 --- a/arch/s390/kernel/perf_pai_ext.c +++ b/arch/s390/kernel/perf_pai_ext.c @@ -384,13 +384,12 @@ static void paiext_del(struct perf_event *event, int flags) * 2 bytes: Number of counter * 8 bytes: Value of counter */ -static size_t paiext_copy(struct paiext_map *cpump) +static size_t paiext_copy(struct pai_userdata *userdata, unsigned long *area) { - struct pai_userdata *userdata = cpump->save; int i, outidx = 0; for (i = 1; i <= paiext_cnt; i++) { - u64 val = paiext_getctr(cpump->area, i); + u64 val = paiext_getctr(area, i); if (val) { userdata[outidx].num = i; @@ -427,7 +426,7 @@ static int paiext_push_sample(void) size_t rawsize; int overflow; - rawsize = paiext_copy(cpump); + rawsize = paiext_copy(cpump->save, cpump->area); if (!rawsize) /* No incremented counters */ return 0; -- cgit From 3046a1091137f55de473262b7f3a04c45f87873a Mon Sep 17 00:00:00 2001 From: Thomas Richter Date: Thu, 16 Nov 2023 12:12:12 +0100 Subject: s390/pai_ext: split function paiext_push_sample Split function paiext_push_sample() into two parts. The first part determines the number of bytes to store as raw data in the perf sample record. This is now function paiext_have_sample(). The second part stores the raw data in the perf event's ring buffer. No functional change. Signed-off-by: Thomas Richter Reviewed-by: Mete Durlu Signed-off-by: Alexander Gordeev --- arch/s390/kernel/perf_pai_ext.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c index e2e1ce2de695..af7f2b538c8f 100644 --- a/arch/s390/kernel/perf_pai_ext.c +++ b/arch/s390/kernel/perf_pai_ext.c @@ -415,21 +415,14 @@ static size_t paiext_copy(struct pai_userdata *userdata, unsigned long *area) * sched_task() callback. That callback is not active after paiext_del() * returns and has deleted the event on that CPU. */ -static int paiext_push_sample(void) +static int paiext_push_sample(size_t rawsize, struct paiext_map *cpump, + struct perf_event *event) { - struct paiext_mapptr *mp = this_cpu_ptr(paiext_root.mapptr); - struct paiext_map *cpump = mp->mapptr; - struct perf_event *event = cpump->event; struct perf_sample_data data; struct perf_raw_record raw; struct pt_regs regs; - size_t rawsize; int overflow; - rawsize = paiext_copy(cpump->save, cpump->area); - if (!rawsize) /* No incremented counters */ - return 0; - /* Setup perf sample */ memset(®s, 0, sizeof(regs)); memset(&raw, 0, sizeof(raw)); @@ -458,6 +451,23 @@ static int paiext_push_sample(void) return overflow; } +/* Check if there is data to be saved on schedule out of a task. */ +static int paiext_have_sample(void) +{ + struct paiext_mapptr *mp = this_cpu_ptr(paiext_root.mapptr); + struct paiext_map *cpump = mp->mapptr; + struct perf_event *event = cpump->event; + size_t rawsize; + int rc = 0; + + if (!event) + return 0; + rawsize = paiext_copy(cpump->save, cpump->area); + if (rawsize) /* Incremented counters */ + rc = paiext_push_sample(rawsize, cpump, event); + return rc; +} + /* Called on schedule-in and schedule-out. No access to event structure, * but for sampling only event NNPA_ALL is allowed. */ @@ -467,7 +477,7 @@ static void paiext_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched * results on schedule_out and if page was dirty, clear values. */ if (!sched_in) - paiext_push_sample(); + paiext_have_sample(); } /* Attribute definitions for pai extension1 interface. As with other CPU -- cgit