s390 updates for the 5.1 merge window
- A copy of Arnds compat wrapper generation series - Pass information about the KVM guest to the host in form the control program code and the control program version code - Map IOV resources to support PCI physical functions on s390 - Add vector load and store alignment hints to improve performance - Use the "jdd" constraint with gcc 9 to make jump labels working again - Remove amode workaround for old z/VM releases from the DCSS code - Add support for in-kernel performance measurements using the CPU measurement counter facility - Introduce a new PMU device cpum_cf_diag to capture counters and store thenn as event raw data. - Bug fixes and cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABCAAGBQJcfh4QAAoJEDjwexyKj9rgXVAH/RzVbi3vznldujSNfCFTZKPu EmFFAZIfbhifW3szfylyOJL52pFhxjcWzY0hkFEkbs2t90sn8l1BNkDscYZtfNHC XvN3N9LsHyxOeyxvQuWLSio58qm+Lr1L0UrIhbMvqyAVkOLmIHvybFwi83OkMptm djoL8NbuNsAA2s26y2bZLNtU7FmOW5smJIlnt7H4dmK4SFylqZKS/EnUZxGDgn+7 UrrTTOQUir0QZ8vraANsP1M0/LqPcd2YusLmj4jOdZ5Muc2Ch2AA991FofqdKShO /8cGlsIzwHWGgdnP/YDea5gbetvonayYduixKy3EnYpWQ9iogiBjH4G7QNxcncs= =v26J -----END PGP SIGNATURE----- Merge tag 's390-5.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux Pull s390 updates from Martin Schwidefsky: - A copy of Arnds compat wrapper generation series - Pass information about the KVM guest to the host in form the control program code and the control program version code - Map IOV resources to support PCI physical functions on s390 - Add vector load and store alignment hints to improve performance - Use the "jdd" constraint with gcc 9 to make jump labels working again - Remove amode workaround for old z/VM releases from the DCSS code - Add support for in-kernel performance measurements using the CPU measurement counter facility - Introduce a new PMU device cpum_cf_diag to capture counters and store thenn as event raw data. - Bug fixes and cleanups * tag 's390-5.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (54 commits) Revert "s390/cpum_cf: Add kernel message exaplanations" s390/dasd: fix read device characteristic with CONFIG_VMAP_STACK=y s390/suspend: fix prefix register reset in swsusp_arch_resume s390: warn about clearing als implied facilities s390: allow overriding facilities via command line s390: clean up redundant facilities list setup s390/als: remove duplicated in-place implementation of stfle s390/cio: Use cpa range elsewhere within vfio-ccw s390/cio: Fix vfio-ccw handling of recursive TICs s390: vfio_ap: link the vfio_ap devices to the vfio_ap bus subsystem s390/cpum_cf: Handle EBUSY return code from CPU counter facility reservation s390/cpum_cf: Add kernel message exaplanations s390/cpum_cf_diag: Add support for s390 counter facility diagnostic trace s390/cpum_cf: add ctr_stcctm() function s390/cpum_cf: move common functions into a separate file s390/cpum_cf: introduce kernel_cpumcf_avail() function s390/cpu_mf: replace stcctm5() with the stcctm() function s390/cpu_mf: add store cpu counter multiple instruction support s390/cpum_cf: Add minimal in-kernel interface for counter measurements s390/cpum_cf: introduce kernel_cpumcf_alert() to obtain measurement alerts ...
This commit is contained in:
commit
3591b19511
|
@ -75,6 +75,7 @@ config S390
|
|||
select ARCH_HAS_SET_MEMORY
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX
|
||||
select ARCH_HAS_STRICT_MODULE_RWX
|
||||
select ARCH_HAS_SYSCALL_WRAPPER
|
||||
select ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||
select ARCH_INLINE_READ_LOCK
|
||||
|
@ -379,6 +380,7 @@ config COMPAT
|
|||
select COMPAT_BINFMT_ELF if BINFMT_ELF
|
||||
select ARCH_WANT_OLD_COMPAT_IPC
|
||||
select COMPAT_OLD_SIGACTION
|
||||
select HAVE_UID16
|
||||
depends on MULTIUSER
|
||||
help
|
||||
Select this option if you want to enable your system kernel to
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <asm/facility.h>
|
||||
#include <asm/lowcore.h>
|
||||
#include <asm/sclp.h>
|
||||
#include "boot.h"
|
||||
|
||||
/*
|
||||
* The code within this file will be called very early. It may _not_
|
||||
|
@ -58,7 +59,7 @@ static void u16_to_decimal(char *str, u16 val)
|
|||
*str = '\0';
|
||||
}
|
||||
|
||||
static void print_missing_facilities(void)
|
||||
void print_missing_facilities(void)
|
||||
{
|
||||
static char als_str[80] = "Missing facilities: ";
|
||||
unsigned long val;
|
||||
|
@ -90,7 +91,6 @@ static void print_missing_facilities(void)
|
|||
}
|
||||
strcat(als_str, "\n");
|
||||
sclp_early_printk(als_str);
|
||||
sclp_early_printk("See Principles of Operations for facility bits\n");
|
||||
}
|
||||
|
||||
static void facility_mismatch(void)
|
||||
|
@ -98,6 +98,7 @@ static void facility_mismatch(void)
|
|||
sclp_early_printk("The Linux kernel requires more recent processor hardware\n");
|
||||
print_machine_type();
|
||||
print_missing_facilities();
|
||||
sclp_early_printk("See Principles of Operations for facility bits\n");
|
||||
disabled_wait(0x8badcccc);
|
||||
}
|
||||
|
||||
|
@ -105,20 +106,7 @@ void verify_facilities(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(S390_lowcore.stfle_fac_list); i++)
|
||||
S390_lowcore.stfle_fac_list[i] = 0;
|
||||
asm volatile(
|
||||
" stfl 0(0)\n"
|
||||
: "=m" (S390_lowcore.stfl_fac_list));
|
||||
S390_lowcore.stfle_fac_list[0] = (u64)S390_lowcore.stfl_fac_list << 32;
|
||||
if (S390_lowcore.stfl_fac_list & 0x01000000) {
|
||||
register unsigned long reg0 asm("0") = ARRAY_SIZE(als) - 1;
|
||||
|
||||
asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */
|
||||
: "+d" (reg0)
|
||||
: "a" (&S390_lowcore.stfle_fac_list)
|
||||
: "memory", "cc");
|
||||
}
|
||||
__stfle(S390_lowcore.stfle_fac_list, ARRAY_SIZE(S390_lowcore.stfle_fac_list));
|
||||
for (i = 0; i < ARRAY_SIZE(als); i++) {
|
||||
if ((S390_lowcore.stfle_fac_list[i] & als[i]) != als[i])
|
||||
facility_mismatch();
|
||||
|
|
|
@ -6,6 +6,8 @@ void startup_kernel(void);
|
|||
void detect_memory(void);
|
||||
void store_ipl_parmblock(void);
|
||||
void setup_boot_command_line(void);
|
||||
void parse_boot_command_line(void);
|
||||
void setup_memory_end(void);
|
||||
void print_missing_facilities(void);
|
||||
|
||||
#endif /* BOOT_BOOT_H */
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <asm/ebcdic.h>
|
||||
#include <asm/sclp.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/boot_data.h>
|
||||
#include <asm/facility.h>
|
||||
#include "boot.h"
|
||||
|
||||
char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
|
||||
|
@ -143,8 +145,66 @@ void setup_boot_command_line(void)
|
|||
append_ipl_block_parm();
|
||||
}
|
||||
|
||||
static void modify_facility(unsigned long nr, bool clear)
|
||||
{
|
||||
if (clear)
|
||||
__clear_facility(nr, S390_lowcore.stfle_fac_list);
|
||||
else
|
||||
__set_facility(nr, S390_lowcore.stfle_fac_list);
|
||||
}
|
||||
|
||||
static void check_cleared_facilities(void)
|
||||
{
|
||||
unsigned long als[] = { FACILITIES_ALS };
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(als); i++) {
|
||||
if ((S390_lowcore.stfle_fac_list[i] & als[i]) != als[i]) {
|
||||
sclp_early_printk("Warning: The Linux kernel requires facilities cleared via command line option\n");
|
||||
print_missing_facilities();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void modify_fac_list(char *str)
|
||||
{
|
||||
unsigned long val, endval;
|
||||
char *endp;
|
||||
bool clear;
|
||||
|
||||
while (*str) {
|
||||
clear = false;
|
||||
if (*str == '!') {
|
||||
clear = true;
|
||||
str++;
|
||||
}
|
||||
val = simple_strtoull(str, &endp, 0);
|
||||
if (str == endp)
|
||||
break;
|
||||
str = endp;
|
||||
if (*str == '-') {
|
||||
str++;
|
||||
endval = simple_strtoull(str, &endp, 0);
|
||||
if (str == endp)
|
||||
break;
|
||||
str = endp;
|
||||
while (val <= endval) {
|
||||
modify_facility(val, clear);
|
||||
val++;
|
||||
}
|
||||
} else {
|
||||
modify_facility(val, clear);
|
||||
}
|
||||
if (*str != ',')
|
||||
break;
|
||||
str++;
|
||||
}
|
||||
check_cleared_facilities();
|
||||
}
|
||||
|
||||
static char command_line_buf[COMMAND_LINE_SIZE] __section(.data);
|
||||
static void parse_mem_opt(void)
|
||||
void parse_boot_command_line(void)
|
||||
{
|
||||
char *param, *val;
|
||||
bool enabled;
|
||||
|
@ -165,12 +225,14 @@ static void parse_mem_opt(void)
|
|||
if (!rc && !enabled)
|
||||
noexec_disabled = 1;
|
||||
}
|
||||
|
||||
if (!strcmp(param, "facilities"))
|
||||
modify_fac_list(val);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_memory_end(void)
|
||||
{
|
||||
parse_mem_opt();
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
if (!OLDMEM_BASE && early_ipl_block_valid &&
|
||||
early_ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP &&
|
||||
|
|
|
@ -53,6 +53,7 @@ void startup_kernel(void)
|
|||
sclp_early_read_info();
|
||||
store_ipl_parmblock();
|
||||
setup_boot_command_line();
|
||||
parse_boot_command_line();
|
||||
setup_memory_end();
|
||||
detect_memory();
|
||||
if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#undef CONFIG_KASAN
|
||||
#include "../lib/string.c"
|
||||
|
||||
int strncmp(const char *cs, const char *ct, size_t count)
|
||||
|
|
|
@ -43,7 +43,7 @@ int hypfs_diag0c_init(void);
|
|||
void hypfs_diag0c_exit(void);
|
||||
|
||||
/* Set Partition-Resource Parameter */
|
||||
int hypfs_sprp_init(void);
|
||||
void hypfs_sprp_init(void);
|
||||
void hypfs_sprp_exit(void);
|
||||
|
||||
/* debugfs interface */
|
||||
|
@ -69,9 +69,9 @@ struct hypfs_dbfs_file {
|
|||
struct dentry *dentry;
|
||||
};
|
||||
|
||||
extern int hypfs_dbfs_init(void);
|
||||
extern void hypfs_dbfs_init(void);
|
||||
extern void hypfs_dbfs_exit(void);
|
||||
extern int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df);
|
||||
extern void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df);
|
||||
extern void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df);
|
||||
|
||||
#endif /* _HYPFS_H_ */
|
||||
|
|
|
@ -78,14 +78,11 @@ static const struct file_operations dbfs_ops = {
|
|||
.unlocked_ioctl = dbfs_ioctl,
|
||||
};
|
||||
|
||||
int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
|
||||
void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df)
|
||||
{
|
||||
df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df,
|
||||
&dbfs_ops);
|
||||
if (IS_ERR(df->dentry))
|
||||
return PTR_ERR(df->dentry);
|
||||
mutex_init(&df->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
|
||||
|
@ -93,10 +90,9 @@ void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
|
|||
debugfs_remove(df->dentry);
|
||||
}
|
||||
|
||||
int hypfs_dbfs_init(void)
|
||||
void hypfs_dbfs_init(void)
|
||||
{
|
||||
dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
|
||||
return PTR_ERR_OR_ZERO(dbfs_dir);
|
||||
}
|
||||
|
||||
void hypfs_dbfs_exit(void)
|
||||
|
|
|
@ -440,11 +440,10 @@ __init int hypfs_diag_init(void)
|
|||
pr_err("The hardware system does not support hypfs\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
if (diag204_info_type == DIAG204_INFO_EXT) {
|
||||
rc = hypfs_dbfs_create_file(&dbfs_file_d204);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (diag204_info_type == DIAG204_INFO_EXT)
|
||||
hypfs_dbfs_create_file(&dbfs_file_d204);
|
||||
|
||||
if (MACHINE_IS_LPAR) {
|
||||
rc = diag224_get_name_table();
|
||||
if (rc) {
|
||||
|
|
|
@ -54,8 +54,7 @@ static void *diag0c_store(unsigned int *count)
|
|||
if (!cpu_vec)
|
||||
goto fail_put_online_cpus;
|
||||
/* Note: Diag 0c needs 8 byte alignment and real storage */
|
||||
diag0c_data = kzalloc(sizeof(struct hypfs_diag0c_hdr) +
|
||||
cpu_count * sizeof(struct hypfs_diag0c_entry),
|
||||
diag0c_data = kzalloc(struct_size(diag0c_data, entry, cpu_count),
|
||||
GFP_KERNEL | GFP_DMA);
|
||||
if (!diag0c_data)
|
||||
goto fail_kfree_cpu_vec;
|
||||
|
@ -125,7 +124,8 @@ int __init hypfs_diag0c_init(void)
|
|||
{
|
||||
if (!MACHINE_IS_VM)
|
||||
return 0;
|
||||
return hypfs_dbfs_create_file(&dbfs_file_0c);
|
||||
hypfs_dbfs_create_file(&dbfs_file_0c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -137,11 +137,11 @@ static struct hypfs_dbfs_file hypfs_sprp_file = {
|
|||
.unlocked_ioctl = hypfs_sprp_ioctl,
|
||||
};
|
||||
|
||||
int hypfs_sprp_init(void)
|
||||
void hypfs_sprp_init(void)
|
||||
{
|
||||
if (!sclp.has_sprp)
|
||||
return 0;
|
||||
return hypfs_dbfs_create_file(&hypfs_sprp_file);
|
||||
return;
|
||||
hypfs_dbfs_create_file(&hypfs_sprp_file);
|
||||
}
|
||||
|
||||
void hypfs_sprp_exit(void)
|
||||
|
|
|
@ -279,7 +279,8 @@ int hypfs_vm_init(void)
|
|||
guest_query = local_guest;
|
||||
else
|
||||
return -EACCES;
|
||||
return hypfs_dbfs_create_file(&dbfs_file_2fc);
|
||||
hypfs_dbfs_create_file(&dbfs_file_2fc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hypfs_vm_exit(void)
|
||||
|
|
|
@ -456,9 +456,8 @@ static int __init hypfs_init(void)
|
|||
{
|
||||
int rc;
|
||||
|
||||
rc = hypfs_dbfs_init();
|
||||
if (rc)
|
||||
return rc;
|
||||
hypfs_dbfs_init();
|
||||
|
||||
if (hypfs_diag_init()) {
|
||||
rc = -ENODATA;
|
||||
goto fail_dbfs_exit;
|
||||
|
@ -467,10 +466,7 @@ static int __init hypfs_init(void)
|
|||
rc = -ENODATA;
|
||||
goto fail_hypfs_diag_exit;
|
||||
}
|
||||
if (hypfs_sprp_init()) {
|
||||
rc = -ENODATA;
|
||||
goto fail_hypfs_vm_exit;
|
||||
}
|
||||
hypfs_sprp_init();
|
||||
if (hypfs_diag0c_init()) {
|
||||
rc = -ENODATA;
|
||||
goto fail_hypfs_sprp_exit;
|
||||
|
@ -489,7 +485,6 @@ fail_hypfs_diag0c_exit:
|
|||
hypfs_diag0c_exit();
|
||||
fail_hypfs_sprp_exit:
|
||||
hypfs_sprp_exit();
|
||||
fail_hypfs_vm_exit:
|
||||
hypfs_vm_exit();
|
||||
fail_hypfs_diag_exit:
|
||||
hypfs_diag_exit();
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Counter facility support definitions for the Linux perf
|
||||
*
|
||||
* Copyright IBM Corp. 2019
|
||||
* Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
|
||||
*/
|
||||
#ifndef _ASM_S390_CPU_MCF_H
|
||||
#define _ASM_S390_CPU_MCF_H
|
||||
|
||||
#include <linux/perf_event.h>
|
||||
#include <asm/cpu_mf.h>
|
||||
|
||||
enum cpumf_ctr_set {
|
||||
CPUMF_CTR_SET_BASIC = 0, /* Basic Counter Set */
|
||||
CPUMF_CTR_SET_USER = 1, /* Problem-State Counter Set */
|
||||
CPUMF_CTR_SET_CRYPTO = 2, /* Crypto-Activity Counter Set */
|
||||
CPUMF_CTR_SET_EXT = 3, /* Extended Counter Set */
|
||||
CPUMF_CTR_SET_MT_DIAG = 4, /* MT-diagnostic Counter Set */
|
||||
|
||||
/* Maximum number of counter sets */
|
||||
CPUMF_CTR_SET_MAX,
|
||||
};
|
||||
|
||||
#define CPUMF_LCCTL_ENABLE_SHIFT 16
|
||||
#define CPUMF_LCCTL_ACTCTL_SHIFT 0
|
||||
static const u64 cpumf_ctr_ctl[CPUMF_CTR_SET_MAX] = {
|
||||
[CPUMF_CTR_SET_BASIC] = 0x02,
|
||||
[CPUMF_CTR_SET_USER] = 0x04,
|
||||
[CPUMF_CTR_SET_CRYPTO] = 0x08,
|
||||
[CPUMF_CTR_SET_EXT] = 0x01,
|
||||
[CPUMF_CTR_SET_MT_DIAG] = 0x20,
|
||||
};
|
||||
|
||||
static inline void ctr_set_enable(u64 *state, int ctr_set)
|
||||
{
|
||||
*state |= cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT;
|
||||
}
|
||||
static inline void ctr_set_disable(u64 *state, int ctr_set)
|
||||
{
|
||||
*state &= ~(cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT);
|
||||
}
|
||||
static inline void ctr_set_start(u64 *state, int ctr_set)
|
||||
{
|
||||
*state |= cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT;
|
||||
}
|
||||
static inline void ctr_set_stop(u64 *state, int ctr_set)
|
||||
{
|
||||
*state &= ~(cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT);
|
||||
}
|
||||
|
||||
static inline void ctr_set_multiple_enable(u64 *state, u64 ctrsets)
|
||||
{
|
||||
*state |= ctrsets << CPUMF_LCCTL_ENABLE_SHIFT;
|
||||
}
|
||||
|
||||
static inline void ctr_set_multiple_disable(u64 *state, u64 ctrsets)
|
||||
{
|
||||
*state &= ~(ctrsets << CPUMF_LCCTL_ENABLE_SHIFT);
|
||||
}
|
||||
|
||||
static inline void ctr_set_multiple_start(u64 *state, u64 ctrsets)
|
||||
{
|
||||
*state |= ctrsets << CPUMF_LCCTL_ACTCTL_SHIFT;
|
||||
}
|
||||
|
||||
static inline void ctr_set_multiple_stop(u64 *state, u64 ctrsets)
|
||||
{
|
||||
*state &= ~(ctrsets << CPUMF_LCCTL_ACTCTL_SHIFT);
|
||||
}
|
||||
|
||||
static inline int ctr_stcctm(enum cpumf_ctr_set set, u64 range, u64 *dest)
|
||||
{
|
||||
switch (set) {
|
||||
case CPUMF_CTR_SET_BASIC:
|
||||
return stcctm(BASIC, range, dest);
|
||||
case CPUMF_CTR_SET_USER:
|
||||
return stcctm(PROBLEM_STATE, range, dest);
|
||||
case CPUMF_CTR_SET_CRYPTO:
|
||||
return stcctm(CRYPTO_ACTIVITY, range, dest);
|
||||
case CPUMF_CTR_SET_EXT:
|
||||
return stcctm(EXTENDED, range, dest);
|
||||
case CPUMF_CTR_SET_MT_DIAG:
|
||||
return stcctm(MT_DIAG_CLEARING, range, dest);
|
||||
case CPUMF_CTR_SET_MAX:
|
||||
return 3;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
struct cpu_cf_events {
|
||||
struct cpumf_ctr_info info;
|
||||
atomic_t ctr_set[CPUMF_CTR_SET_MAX];
|
||||
atomic64_t alert;
|
||||
u64 state, tx_state;
|
||||
unsigned int flags;
|
||||
unsigned int txn_flags;
|
||||
};
|
||||
DECLARE_PER_CPU(struct cpu_cf_events, cpu_cf_events);
|
||||
|
||||
bool kernel_cpumcf_avail(void);
|
||||
int __kernel_cpumcf_begin(void);
|
||||
unsigned long kernel_cpumcf_alert(int clear);
|
||||
void __kernel_cpumcf_end(void);
|
||||
|
||||
static inline int kernel_cpumcf_begin(void)
|
||||
{
|
||||
if (!cpum_cf_avail())
|
||||
return -ENODEV;
|
||||
|
||||
preempt_disable();
|
||||
return __kernel_cpumcf_begin();
|
||||
}
|
||||
static inline void kernel_cpumcf_end(void)
|
||||
{
|
||||
__kernel_cpumcf_end();
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/* Return true if store counter set multiple instruction is available */
|
||||
static inline int stccm_avail(void)
|
||||
{
|
||||
return test_facility(142);
|
||||
}
|
||||
|
||||
#endif /* _ASM_S390_CPU_MCF_H */
|
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Support for CPU-MF instructions
|
||||
*
|
||||
* Copyright IBM Corp. 2019
|
||||
* Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
|
||||
*/
|
||||
#ifndef _ASM_S390_CPU_MF_INSN_H
|
||||
#define _ASM_S390_CPU_MF_INSN_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
/* Macro to generate the STCCTM instruction with a customized
|
||||
* M3 field designating the counter set.
|
||||
*/
|
||||
.macro STCCTM r1 m3 db2
|
||||
.insn rsy,0xeb0000000017,\r1,\m3 & 0xf,\db2
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
|
@ -12,6 +12,8 @@
|
|||
#include <linux/errno.h>
|
||||
#include <asm/facility.h>
|
||||
|
||||
asm(".include \"asm/cpu_mf-insn.h\"\n");
|
||||
|
||||
#define CPU_MF_INT_SF_IAE (1 << 31) /* invalid entry address */
|
||||
#define CPU_MF_INT_SF_ISE (1 << 30) /* incorrect SDBT entry */
|
||||
#define CPU_MF_INT_SF_PRA (1 << 29) /* program request alert */
|
||||
|
@ -209,17 +211,25 @@ static inline int ecctr(u64 ctr, u64 *val)
|
|||
return cc;
|
||||
}
|
||||
|
||||
/* Store CPU counter multiple for the MT utilization counter set */
|
||||
static inline int stcctm5(u64 num, u64 *val)
|
||||
/* Store CPU counter multiple for a particular counter set */
|
||||
enum stcctm_ctr_set {
|
||||
EXTENDED = 0,
|
||||
BASIC = 1,
|
||||
PROBLEM_STATE = 2,
|
||||
CRYPTO_ACTIVITY = 3,
|
||||
MT_DIAG = 5,
|
||||
MT_DIAG_CLEARING = 9, /* clears loss-of-MT-ctr-data alert */
|
||||
};
|
||||
static inline int stcctm(enum stcctm_ctr_set set, u64 range, u64 *dest)
|
||||
{
|
||||
int cc;
|
||||
|
||||
asm volatile (
|
||||
" .insn rsy,0xeb0000000017,%2,5,%1\n"
|
||||
" STCCTM %2,%3,%1\n"
|
||||
" ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
: "=d" (cc)
|
||||
: "Q" (*val), "d" (num)
|
||||
: "Q" (*dest), "d" (range), "i" (set)
|
||||
: "cc", "memory");
|
||||
return cc;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ enum diag_stat_enum {
|
|||
DIAG_STAT_X2FC,
|
||||
DIAG_STAT_X304,
|
||||
DIAG_STAT_X308,
|
||||
DIAG_STAT_X318,
|
||||
DIAG_STAT_X500,
|
||||
NR_DIAG_STAT
|
||||
};
|
||||
|
@ -293,6 +294,17 @@ struct diag26c_mac_resp {
|
|||
u8 res[2];
|
||||
} __aligned(8);
|
||||
|
||||
#define CPNC_LINUX 0x4
|
||||
union diag318_info {
|
||||
unsigned long val;
|
||||
struct {
|
||||
unsigned int cpnc : 8;
|
||||
unsigned int cpvc_linux : 24;
|
||||
unsigned char cpvc_distro[3];
|
||||
unsigned char zero;
|
||||
};
|
||||
};
|
||||
|
||||
int diag204(unsigned long subcode, unsigned long size, void *addr);
|
||||
int diag224(void *ptr);
|
||||
int diag26c(void *req, void *resp, enum diag26c_sc subcode);
|
||||
|
|
|
@ -81,5 +81,30 @@ static inline void ftrace_generate_call_insn(struct ftrace_insn *insn,
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Even though the system call numbers are identical for s390/s390x a
|
||||
* different system call table is used for compat tasks. This may lead
|
||||
* to e.g. incorrect or missing trace event sysfs files.
|
||||
* Therefore simply do not trace compat system calls at all.
|
||||
* See kernel/trace/trace_syscalls.c.
|
||||
*/
|
||||
#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
|
||||
static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
|
||||
{
|
||||
return is_compat_task();
|
||||
}
|
||||
|
||||
#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
|
||||
static inline bool arch_syscall_match_sym_name(const char *sym,
|
||||
const char *name)
|
||||
{
|
||||
/*
|
||||
* Skip __s390_ and __s390x_ prefix - due to compat wrappers
|
||||
* and aliasing some symbols of 64 bit system call functions
|
||||
* may get the __s390_ prefix instead of the __s390x_ prefix.
|
||||
*/
|
||||
return !strcmp(sym + 7, name) || !strcmp(sym + 8, name);
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _ASM_S390_FTRACE_H */
|
||||
|
|
|
@ -10,6 +10,12 @@
|
|||
#define JUMP_LABEL_NOP_SIZE 6
|
||||
#define JUMP_LABEL_NOP_OFFSET 2
|
||||
|
||||
#if __GNUC__ < 9
|
||||
#define JUMP_LABEL_STATIC_KEY_CONSTRAINT "X"
|
||||
#else
|
||||
#define JUMP_LABEL_STATIC_KEY_CONSTRAINT "jdd"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We use a brcl 0,2 instruction for jump labels at compile time so it
|
||||
* can be easily distinguished from a hotpatch generated instruction.
|
||||
|
@ -20,9 +26,9 @@ static inline bool arch_static_branch(struct static_key *key, bool branch)
|
|||
".pushsection __jump_table,\"aw\"\n"
|
||||
".balign 8\n"
|
||||
".long 0b-.,%l[label]-.\n"
|
||||
".quad %0-.\n"
|
||||
".quad %0+%1-.\n"
|
||||
".popsection\n"
|
||||
: : "X" (&((char *)key)[branch]) : : label);
|
||||
: : JUMP_LABEL_STATIC_KEY_CONSTRAINT (key), "i" (branch) : : label);
|
||||
return false;
|
||||
label:
|
||||
return true;
|
||||
|
@ -34,9 +40,9 @@ static inline bool arch_static_branch_jump(struct static_key *key, bool branch)
|
|||
".pushsection __jump_table,\"aw\"\n"
|
||||
".balign 8\n"
|
||||
".long 0b-.,%l[label]-.\n"
|
||||
".quad %0-.\n"
|
||||
".quad %0+%1-.\n"
|
||||
".popsection\n"
|
||||
: : "X" (&((char *)key)[branch]) : : label);
|
||||
: : JUMP_LABEL_STATIC_KEY_CONSTRAINT (key), "i" (branch) : : label);
|
||||
return false;
|
||||
label:
|
||||
return true;
|
||||
|
|
|
@ -148,7 +148,6 @@ struct zpci_dev {
|
|||
enum pci_bus_speed max_bus_speed;
|
||||
|
||||
struct dentry *debugfs_dev;
|
||||
struct dentry *debugfs_perf;
|
||||
|
||||
struct s390_domain *s390_domain; /* s390 IOMMU domain data */
|
||||
};
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/cpu_mf.h>
|
||||
|
||||
/* Per-CPU flags for PMU states */
|
||||
#define PMU_F_RESERVED 0x1000
|
||||
|
@ -55,6 +54,7 @@ struct perf_sf_sde_regs {
|
|||
#define PERF_CPUM_SF_MAX_CTR 2
|
||||
#define PERF_EVENT_CPUM_SF 0xB0000UL /* Event: Basic-sampling */
|
||||
#define PERF_EVENT_CPUM_SF_DIAG 0xBD000UL /* Event: Combined-sampling */
|
||||
#define PERF_EVENT_CPUM_CF_DIAG 0xBC000UL /* Event: Counter sets */
|
||||
#define PERF_CPUM_SF_BASIC_MODE 0x0001 /* Basic-sampling flag */
|
||||
#define PERF_CPUM_SF_DIAG_MODE 0x0002 /* Diagnostic-sampling flag */
|
||||
#define PERF_CPUM_SF_MODE_MASK (PERF_CPUM_SF_BASIC_MODE| \
|
||||
|
|
|
@ -361,8 +361,8 @@ struct qdio_initialize {
|
|||
unsigned long);
|
||||
int scan_threshold;
|
||||
unsigned long int_parm;
|
||||
void **input_sbal_addr_array;
|
||||
void **output_sbal_addr_array;
|
||||
struct qdio_buffer **input_sbal_addr_array;
|
||||
struct qdio_buffer **output_sbal_addr_array;
|
||||
struct qdio_outbuf_state *output_sbal_state_array;
|
||||
};
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ struct sclp_info {
|
|||
unsigned char has_skey : 1;
|
||||
unsigned char has_kss : 1;
|
||||
unsigned char has_gisaf : 1;
|
||||
unsigned char has_diag318 : 1;
|
||||
unsigned int ibc;
|
||||
unsigned int mtid;
|
||||
unsigned int mtid_cp;
|
||||
|
|
|
@ -12,15 +12,21 @@
|
|||
#include <linux/types.h>
|
||||
#endif
|
||||
|
||||
#define __HAVE_ARCH_MEMCHR /* inline & arch function */
|
||||
#define __HAVE_ARCH_MEMCMP /* arch function */
|
||||
#define __HAVE_ARCH_MEMCPY /* gcc builtin & arch function */
|
||||
#define __HAVE_ARCH_MEMMOVE /* gcc builtin & arch function */
|
||||
#define __HAVE_ARCH_MEMSCAN /* inline & arch function */
|
||||
#define __HAVE_ARCH_MEMSET /* gcc builtin & arch function */
|
||||
#define __HAVE_ARCH_MEMSET16 /* arch function */
|
||||
#define __HAVE_ARCH_MEMSET32 /* arch function */
|
||||
#define __HAVE_ARCH_MEMSET64 /* arch function */
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
|
||||
#ifndef CONFIG_KASAN
|
||||
#define __HAVE_ARCH_MEMCHR /* inline & arch function */
|
||||
#define __HAVE_ARCH_MEMCMP /* arch function */
|
||||
#define __HAVE_ARCH_MEMSCAN /* inline & arch function */
|
||||
#define __HAVE_ARCH_STRCAT /* inline & arch function */
|
||||
#define __HAVE_ARCH_STRCMP /* arch function */
|
||||
#define __HAVE_ARCH_STRCPY /* inline & arch function */
|
||||
|
@ -35,9 +41,6 @@
|
|||
|
||||
/* Prototypes for non-inlined arch strings functions. */
|
||||
int memcmp(const void *s1, const void *s2, size_t n);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
size_t strlcat(char *dest, const char *src, size_t n);
|
||||
size_t strlcpy(char *dest, const char *src, size_t size);
|
||||
|
@ -45,6 +48,7 @@ char *strncat(char *dest, const char *src, size_t n);
|
|||
char *strncpy(char *dest, const char *src, size_t n);
|
||||
char *strrchr(const char *s, int c);
|
||||
char *strstr(const char *s1, const char *s2);
|
||||
#endif /* !CONFIG_KASAN */
|
||||
|
||||
#undef __HAVE_ARCH_STRCHR
|
||||
#undef __HAVE_ARCH_STRNCHR
|
||||
|
@ -95,6 +99,7 @@ static inline void *memset64(uint64_t *s, uint64_t v, size_t count)
|
|||
|
||||
#if !defined(IN_ARCH_STRING_C) && (!defined(CONFIG_FORTIFY_SOURCE) || defined(__NO_FORTIFY))
|
||||
|
||||
#ifdef __HAVE_ARCH_MEMCHR
|
||||
static inline void *memchr(const void * s, int c, size_t n)
|
||||
{
|
||||
register int r0 asm("0") = (char) c;
|
||||
|
@ -109,7 +114,9 @@ static inline void *memchr(const void * s, int c, size_t n)
|
|||
: "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory");
|
||||
return (void *) ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __HAVE_ARCH_MEMSCAN
|
||||
static inline void *memscan(void *s, int c, size_t n)
|
||||
{
|
||||
register int r0 asm("0") = (char) c;
|
||||
|
@ -121,7 +128,9 @@ static inline void *memscan(void *s, int c, size_t n)
|
|||
: "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory");
|
||||
return (void *) ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __HAVE_ARCH_STRCAT
|
||||
static inline char *strcat(char *dst, const char *src)
|
||||
{
|
||||
register int r0 asm("0") = 0;
|
||||
|
@ -137,7 +146,9 @@ static inline char *strcat(char *dst, const char *src)
|
|||
: "d" (r0), "0" (0) : "cc", "memory" );
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __HAVE_ARCH_STRCPY
|
||||
static inline char *strcpy(char *dst, const char *src)
|
||||
{
|
||||
register int r0 asm("0") = 0;
|
||||
|
@ -150,7 +161,9 @@ static inline char *strcpy(char *dst, const char *src)
|
|||
: "cc", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __HAVE_ARCH_STRLEN
|
||||
static inline size_t strlen(const char *s)
|
||||
{
|
||||
register unsigned long r0 asm("0") = 0;
|
||||
|
@ -162,7 +175,9 @@ static inline size_t strlen(const char *s)
|
|||
: "+d" (r0), "+a" (tmp) : : "cc", "memory");
|
||||
return r0 - (unsigned long) s;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __HAVE_ARCH_STRNLEN
|
||||
static inline size_t strnlen(const char * s, size_t n)
|
||||
{
|
||||
register int r0 asm("0") = 0;
|
||||
|
@ -175,6 +190,7 @@ static inline size_t strnlen(const char * s, size_t n)
|
|||
: "+a" (end), "+a" (tmp) : "d" (r0) : "cc", "memory");
|
||||
return end - s;
|
||||
}
|
||||
#endif
|
||||
#else /* IN_ARCH_STRING_C */
|
||||
void *memchr(const void * s, int c, size_t n);
|
||||
void *memscan(void *s, int c, size_t n);
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* syscall_wrapper.h - s390 specific wrappers to syscall definitions
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ASM_S390_SYSCALL_WRAPPER_H
|
||||
#define _ASM_S390_SYSCALL_WRAPPER_H
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
#define __SC_COMPAT_TYPE(t, a) \
|
||||
__typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
|
||||
|
||||
#define __SC_COMPAT_CAST(t, a) \
|
||||
({ \
|
||||
long __ReS = a; \
|
||||
\
|
||||
BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) && \
|
||||
!__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) && \
|
||||
!__TYPE_IS_LL(t)); \
|
||||
if (__TYPE_IS_L(t)) \
|
||||
__ReS = (s32)a; \
|
||||
if (__TYPE_IS_UL(t)) \
|
||||
__ReS = (u32)a; \
|
||||
if (__TYPE_IS_PTR(t)) \
|
||||
__ReS = a & 0x7fffffff; \
|
||||
if (__TYPE_IS_LL(t)) \
|
||||
return -ENOSYS; \
|
||||
(t)__ReS; \
|
||||
})
|
||||
|
||||
#define __S390_SYS_STUBx(x, name, ...) \
|
||||
asmlinkage long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))\
|
||||
ALLOW_ERROR_INJECTION(__s390_sys##name, ERRNO); \
|
||||
asmlinkage long __s390_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))\
|
||||
{ \
|
||||
long ret = __s390x_sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));\
|
||||
__MAP(x,__SC_TEST,__VA_ARGS__); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
/*
|
||||
* To keep the naming coherent, re-define SYSCALL_DEFINE0 to create an alias
|
||||
* named __s390x_sys_*()
|
||||
*/
|
||||
#define COMPAT_SYSCALL_DEFINE0(sname) \
|
||||
SYSCALL_METADATA(_##sname, 0); \
|
||||
asmlinkage long __s390_compat_sys_##sname(void); \
|
||||
ALLOW_ERROR_INJECTION(__s390_compat__sys_##sname, ERRNO); \
|
||||
asmlinkage long __s390_compat_sys_##sname(void)
|
||||
|
||||
#define SYSCALL_DEFINE0(sname) \
|
||||
SYSCALL_METADATA(_##sname, 0); \
|
||||
asmlinkage long __s390x_sys_##sname(void); \
|
||||
ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO); \
|
||||
asmlinkage long __s390_sys_##sname(void) \
|
||||
__attribute__((alias(__stringify(__s390x_sys_##sname)))); \
|
||||
asmlinkage long __s390x_sys_##sname(void)
|
||||
|
||||
#define COND_SYSCALL(name) \
|
||||
cond_syscall(__s390x_sys_##name); \
|
||||
cond_syscall(__s390_sys_##name)
|
||||
|
||||
#define SYS_NI(name) \
|
||||
SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers); \
|
||||
SYSCALL_ALIAS(__s390_sys_##name, sys_ni_posix_timers)
|
||||
|
||||
#define COMPAT_SYSCALL_DEFINEx(x, name, ...) \
|
||||
__diag_push(); \
|
||||
__diag_ignore(GCC, 8, "-Wattribute-alias", \
|
||||
"Type aliasing is used to sanitize syscall arguments");\
|
||||
asmlinkage long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
|
||||
asmlinkage long __s390_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
|
||||
__attribute__((alias(__stringify(__se_compat_sys##name)))); \
|
||||
ALLOW_ERROR_INJECTION(compat_sys##name, ERRNO); \
|
||||
static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
|
||||
asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
|
||||
asmlinkage long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
|
||||
{ \
|
||||
long ret = __do_compat_sys##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__));\
|
||||
__MAP(x,__SC_TEST,__VA_ARGS__); \
|
||||
return ret; \
|
||||
} \
|
||||
__diag_pop(); \
|
||||
static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
|
||||
|
||||
/*
|
||||
* As some compat syscalls may not be implemented, we need to expand
|
||||
* COND_SYSCALL_COMPAT in kernel/sys_ni.c and COMPAT_SYS_NI in
|
||||
* kernel/time/posix-stubs.c to cover this case as well.
|
||||
*/
|
||||
#define COND_SYSCALL_COMPAT(name) \
|
||||
cond_syscall(__s390_compat_sys_##name)
|
||||
|
||||
#define COMPAT_SYS_NI(name) \
|
||||
SYSCALL_ALIAS(__s390_compat_sys_##name, sys_ni_posix_timers)
|
||||
|
||||
#else /* CONFIG_COMPAT */
|
||||
|
||||
#define __S390_SYS_STUBx(x, fullname, name, ...)
|
||||
|
||||
#define SYSCALL_DEFINE0(sname) \
|
||||
SYSCALL_METADATA(_##sname, 0); \
|
||||
asmlinkage long __s390x_sys_##sname(void); \
|
||||
ALLOW_ERROR_INJECTION(__s390x_sys_##sname, ERRNO); \
|
||||
asmlinkage long __s390x_sys_##sname(void)
|
||||
|
||||
#define COND_SYSCALL(name) \
|
||||
cond_syscall(__s390x_sys_##name)
|
||||
|
||||
#define SYS_NI(name) \
|
||||
SYSCALL_ALIAS(__s390x_sys_##name, sys_ni_posix_timers);
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
#define __SYSCALL_DEFINEx(x, name, ...) \
|
||||
__diag_push(); \
|
||||
__diag_ignore(GCC, 8, "-Wattribute-alias", \
|
||||
"Type aliasing is used to sanitize syscall arguments");\
|
||||
asmlinkage long __s390x_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
|
||||
__attribute__((alias(__stringify(__se_sys##name)))); \
|
||||
ALLOW_ERROR_INJECTION(__s390x_sys##name, ERRNO); \
|
||||
static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
|
||||
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
|
||||
__S390_SYS_STUBx(x, name, __VA_ARGS__) \
|
||||
asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
|
||||
{ \
|
||||
long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \
|
||||
__MAP(x,__SC_TEST,__VA_ARGS__); \
|
||||
return ret; \
|
||||
} \
|
||||
__diag_pop(); \
|
||||
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
|
||||
|
||||
#endif /* _ASM_X86_SYSCALL_WRAPPER_H */
|
|
@ -363,23 +363,23 @@
|
|||
.endm
|
||||
|
||||
/* VECTOR LOAD MULTIPLE */
|
||||
.macro VLM vfrom, vto, disp, base
|
||||
.macro VLM vfrom, vto, disp, base, hint=3
|
||||
VX_NUM v1, \vfrom
|
||||
VX_NUM v3, \vto
|
||||
GR_NUM b2, \base /* Base register */
|
||||
.word 0xE700 | ((v1&15) << 4) | (v3&15)
|
||||
.word (b2 << 12) | (\disp)
|
||||
MRXBOPC 0, 0x36, v1, v3
|
||||
MRXBOPC \hint, 0x36, v1, v3
|
||||
.endm
|
||||
|
||||
/* VECTOR STORE MULTIPLE */
|
||||
.macro VSTM vfrom, vto, disp, base
|
||||
.macro VSTM vfrom, vto, disp, base, hint=3
|
||||
VX_NUM v1, \vfrom
|
||||
VX_NUM v3, \vto
|
||||
GR_NUM b2, \base /* Base register */
|
||||
.word 0xE700 | ((v1&15) << 4) | (v3&15)
|
||||
.word (b2 << 12) | (\disp)
|
||||
MRXBOPC 0, 0x3E, v1, v3
|
||||
MRXBOPC \hint, 0x3E, v1, v3
|
||||
.endm
|
||||
|
||||
/* VECTOR PERMUTE */
|
||||
|
|
|
@ -20,6 +20,12 @@ typedef long __kernel_ssize_t;
|
|||
typedef unsigned short __kernel_old_dev_t;
|
||||
#define __kernel_old_dev_t __kernel_old_dev_t
|
||||
|
||||
#ifdef __KERNEL__
|
||||
typedef unsigned short __kernel_old_uid_t;
|
||||
typedef unsigned short __kernel_old_gid_t;
|
||||
#define __kernel_old_uid_t __kernel_old_uid_t
|
||||
#endif
|
||||
|
||||
#ifndef __s390x__
|
||||
|
||||
typedef unsigned long __kernel_ino_t;
|
||||
|
|
|
@ -65,7 +65,7 @@ obj-$(CONFIG_HIBERNATION) += suspend.o swsusp.o
|
|||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
compat-obj-$(CONFIG_AUDIT) += compat_audit.o
|
||||
obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o
|
||||
obj-$(CONFIG_COMPAT) += compat_wrapper.o $(compat-obj-y)
|
||||
obj-$(CONFIG_COMPAT) += $(compat-obj-y)
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o
|
||||
|
@ -77,8 +77,10 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o
|
|||
obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_image.o
|
||||
obj-$(CONFIG_KEXEC_FILE) += kexec_elf.o
|
||||
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf_common.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf.o perf_cpum_sf.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_diag.o
|
||||
|
||||
obj-$(CONFIG_TRACEPOINTS) += trace.o
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <linux/stat.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/highuid.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/in.h>
|
||||
|
@ -58,245 +57,13 @@
|
|||
|
||||
#include "compat_linux.h"
|
||||
|
||||
/* For this source file, we want overflow handling. */
|
||||
|
||||
#undef high2lowuid
|
||||
#undef high2lowgid
|
||||
#undef low2highuid
|
||||
#undef low2highgid
|
||||
#undef SET_UID16
|
||||
#undef SET_GID16
|
||||
#undef NEW_TO_OLD_UID
|
||||
#undef NEW_TO_OLD_GID
|
||||
#undef SET_OLDSTAT_UID
|
||||
#undef SET_OLDSTAT_GID
|
||||
#undef SET_STAT_UID
|
||||
#undef SET_STAT_GID
|
||||
|
||||
#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
|
||||
#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
|
||||
#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
|
||||
#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
|
||||
#define SET_UID16(var, uid) var = high2lowuid(uid)
|
||||
#define SET_GID16(var, gid) var = high2lowgid(gid)
|
||||
#define NEW_TO_OLD_UID(uid) high2lowuid(uid)
|
||||
#define NEW_TO_OLD_GID(gid) high2lowgid(gid)
|
||||
#define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
|
||||
#define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
|
||||
#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
|
||||
#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename,
|
||||
u16, user, u16, group)
|
||||
{
|
||||
return ksys_chown(filename, low2highuid(user), low2highgid(group));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(s390_lchown16, const char __user *,
|
||||
filename, u16, user, u16, group)
|
||||
{
|
||||
return ksys_lchown(filename, low2highuid(user), low2highgid(group));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(s390_fchown16, unsigned int, fd, u16, user, u16, group)
|
||||
{
|
||||
return ksys_fchown(fd, low2highuid(user), low2highgid(group));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(s390_setregid16, u16, rgid, u16, egid)
|
||||
{
|
||||
return sys_setregid(low2highgid(rgid), low2highgid(egid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE1(s390_setgid16, u16, gid)
|
||||
{
|
||||
return sys_setgid(low2highgid(gid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(s390_setreuid16, u16, ruid, u16, euid)
|
||||
{
|
||||
return sys_setreuid(low2highuid(ruid), low2highuid(euid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE1(s390_setuid16, u16, uid)
|
||||
{
|
||||
return sys_setuid(low2highuid(uid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(s390_setresuid16, u16, ruid, u16, euid, u16, suid)
|
||||
{
|
||||
return sys_setresuid(low2highuid(ruid), low2highuid(euid),
|
||||
low2highuid(suid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(s390_getresuid16, u16 __user *, ruidp,
|
||||
u16 __user *, euidp, u16 __user *, suidp)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
int retval;
|
||||
u16 ruid, euid, suid;
|
||||
|
||||
ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
|
||||
euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
|
||||
suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
|
||||
|
||||
if (!(retval = put_user(ruid, ruidp)) &&
|
||||
!(retval = put_user(euid, euidp)))
|
||||
retval = put_user(suid, suidp);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(s390_setresgid16, u16, rgid, u16, egid, u16, sgid)
|
||||
{
|
||||
return sys_setresgid(low2highgid(rgid), low2highgid(egid),
|
||||
low2highgid(sgid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(s390_getresgid16, u16 __user *, rgidp,
|
||||
u16 __user *, egidp, u16 __user *, sgidp)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
int retval;
|
||||
u16 rgid, egid, sgid;
|
||||
|
||||
rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
|
||||
egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
|
||||
sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
|
||||
|
||||
if (!(retval = put_user(rgid, rgidp)) &&
|
||||
!(retval = put_user(egid, egidp)))
|
||||
retval = put_user(sgid, sgidp);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE1(s390_setfsuid16, u16, uid)
|
||||
{
|
||||
return sys_setfsuid(low2highuid(uid));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE1(s390_setfsgid16, u16, gid)
|
||||
{
|
||||
return sys_setfsgid(low2highgid(gid));
|
||||
}
|
||||
|
||||
static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
|
||||
{
|
||||
struct user_namespace *user_ns = current_user_ns();
|
||||
int i;
|
||||
u16 group;
|
||||
kgid_t kgid;
|
||||
|
||||
for (i = 0; i < group_info->ngroups; i++) {
|
||||
kgid = group_info->gid[i];
|
||||
group = (u16)from_kgid_munged(user_ns, kgid);
|
||||
if (put_user(group, grouplist+i))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist)
|
||||
{
|
||||
struct user_namespace *user_ns = current_user_ns();
|
||||
int i;
|
||||
u16 group;
|
||||
kgid_t kgid;
|
||||
|
||||
for (i = 0; i < group_info->ngroups; i++) {
|
||||
if (get_user(group, grouplist+i))
|
||||
return -EFAULT;
|
||||
|
||||
kgid = make_kgid(user_ns, (gid_t)group);
|
||||
if (!gid_valid(kgid))
|
||||
return -EINVAL;
|
||||
|
||||
group_info->gid[i] = kgid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(s390_getgroups16, int, gidsetsize, u16 __user *, grouplist)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
int i;
|
||||
|
||||
if (gidsetsize < 0)
|
||||
return -EINVAL;
|
||||
|
||||
get_group_info(cred->group_info);
|
||||
i = cred->group_info->ngroups;
|
||||
if (gidsetsize) {
|
||||
if (i > gidsetsize) {
|
||||
i = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (groups16_to_user(grouplist, cred->group_info)) {
|
||||
i = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
put_group_info(cred->group_info);
|
||||
return i;
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(s390_setgroups16, int, gidsetsize, u16 __user *, grouplist)
|
||||
{
|
||||
struct group_info *group_info;
|
||||
int retval;
|
||||
|
||||
if (!may_setgroups())
|
||||
return -EPERM;
|
||||
if ((unsigned)gidsetsize > NGROUPS_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
group_info = groups_alloc(gidsetsize);
|
||||
if (!group_info)
|
||||
return -ENOMEM;
|
||||
retval = groups16_from_user(group_info, grouplist);
|
||||
if (retval) {
|
||||
put_group_info(group_info);
|
||||
return retval;
|
||||
}
|
||||
|
||||
groups_sort(group_info);
|
||||
retval = set_current_groups(group_info);
|
||||
put_group_info(group_info);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE0(s390_getuid16)
|
||||
{
|
||||
return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE0(s390_geteuid16)
|
||||
{
|
||||
return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE0(s390_getgid16)
|
||||
{
|
||||
return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE0(s390_getegid16)
|
||||
{
|
||||
return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSVIPC
|
||||
COMPAT_SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, compat_ulong_t, second,
|
||||
compat_ulong_t, third, compat_uptr_t, ptr)
|
||||
{
|
||||
if (call >> 16) /* hack for backward compatibility */
|
||||
return -EINVAL;
|
||||
return compat_sys_ipc(call, first, second, third, ptr, third);
|
||||
return compat_ksys_ipc(call, first, second, third, ptr, third);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Compat system call wrappers.
|
||||
*
|
||||
* Copyright IBM Corp. 2014
|
||||
*/
|
||||
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/compat.h>
|
||||
#include "entry.h"
|
||||
|
||||
#define COMPAT_SYSCALL_WRAP1(name, ...) \
|
||||
COMPAT_SYSCALL_WRAPx(1, _##name, __VA_ARGS__)
|
||||
#define COMPAT_SYSCALL_WRAP2(name, ...) \
|
||||
COMPAT_SYSCALL_WRAPx(2, _##name, __VA_ARGS__)
|
||||
#define COMPAT_SYSCALL_WRAP3(name, ...) \
|
||||
COMPAT_SYSCALL_WRAPx(3, _##name, __VA_ARGS__)
|
||||
#define COMPAT_SYSCALL_WRAP4(name, ...) \
|
||||
COMPAT_SYSCALL_WRAPx(4, _##name, __VA_ARGS__)
|
||||
#define COMPAT_SYSCALL_WRAP5(name, ...) \
|
||||
COMPAT_SYSCALL_WRAPx(5, _##name, __VA_ARGS__)
|
||||
#define COMPAT_SYSCALL_WRAP6(name, ...) \
|
||||
COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__)
|
||||
|
||||
#define __SC_COMPAT_TYPE(t, a) \
|
||||
__typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
|
||||
|
||||
#define __SC_COMPAT_CAST(t, a) \
|
||||
({ \
|
||||
long __ReS = a; \
|
||||
\
|
||||
BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) && \
|
||||
!__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t)); \
|
||||
if (__TYPE_IS_L(t)) \
|
||||
__ReS = (s32)a; \
|
||||
if (__TYPE_IS_UL(t)) \
|
||||
__ReS = (u32)a; \
|
||||
if (__TYPE_IS_PTR(t)) \
|
||||
__ReS = a & 0x7fffffff; \
|
||||
(t)__ReS; \
|
||||
})
|
||||
|
||||
/*
|
||||
* The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by
|
||||
* compat tasks. These wrappers will only be used for system calls where only
|
||||
* the system call arguments need sign or zero extension or zeroing of the upper
|
||||
* 33 bits of pointers.
|
||||
* Note: since the wrapper function will afterwards call a system call which
|
||||
* again performs zero and sign extension for all system call arguments with
|
||||
* a size of less than eight bytes, these compat wrappers only touch those
|
||||
* system call arguments with a size of eight bytes ((unsigned) long and
|
||||
* pointers). Zero and sign extension for e.g. int parameters will be done by
|
||||
* the regular system call wrappers.
|
||||
*/
|
||||
#define COMPAT_SYSCALL_WRAPx(x, name, ...) \
|
||||
asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
|
||||
asmlinkage long notrace compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));\
|
||||
asmlinkage long notrace compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
|
||||
{ \
|
||||
return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__)); \
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
|
||||
COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
|
||||
COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
|
||||
COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename);
|
||||
COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
|
||||
COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode);
|
||||
COMPAT_SYSCALL_WRAP1(oldumount, char __user *, name);
|
||||
COMPAT_SYSCALL_WRAP2(access, const char __user *, filename, int, mode);
|
||||
COMPAT_SYSCALL_WRAP2(rename, const char __user *, oldname, const char __user *, newname);
|
||||
COMPAT_SYSCALL_WRAP2(mkdir, const char __user *, pathname, umode_t, mode);
|
||||
COMPAT_SYSCALL_WRAP1(rmdir, const char __user *, pathname);
|
||||
COMPAT_SYSCALL_WRAP1(pipe, int __user *, fildes);
|
||||
COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);
|
||||
COMPAT_SYSCALL_WRAP2(signal, int, sig, __sighandler_t, handler);
|
||||
COMPAT_SYSCALL_WRAP1(acct, const char __user *, name);
|
||||
COMPAT_SYSCALL_WRAP2(umount, char __user *, name, int, flags);
|
||||
COMPAT_SYSCALL_WRAP1(chroot, const char __user *, filename);
|
||||
COMPAT_SYSCALL_WRAP3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask);
|
||||
COMPAT_SYSCALL_WRAP2(sethostname, char __user *, name, int, len);
|
||||
COMPAT_SYSCALL_WRAP2(symlink, const char __user *, old, const char __user *, new);
|
||||
COMPAT_SYSCALL_WRAP3(readlink, const char __user *, path, char __user *, buf, int, bufsiz);
|
||||
COMPAT_SYSCALL_WRAP1(uselib, const char __user *, library);
|
||||
COMPAT_SYSCALL_WRAP2(swapon, const char __user *, specialfile, int, swap_flags);
|
||||
COMPAT_SYSCALL_WRAP4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg);
|
||||
COMPAT_SYSCALL_WRAP2(munmap, unsigned long, addr, size_t, len);
|
||||
COMPAT_SYSCALL_WRAP3(syslog, int, type, char __user *, buf, int, len);
|
||||
COMPAT_SYSCALL_WRAP1(swapoff, const char __user *, specialfile);
|
||||
COMPAT_SYSCALL_WRAP2(setdomainname, char __user *, name, int, len);
|
||||
COMPAT_SYSCALL_WRAP1(newuname, struct new_utsname __user *, name);
|
||||
COMPAT_SYSCALL_WRAP3(mprotect, unsigned long, start, size_t, len, unsigned long, prot);
|
||||
COMPAT_SYSCALL_WRAP3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs);
|
||||
COMPAT_SYSCALL_WRAP2(delete_module, const char __user *, name_user, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr);
|
||||
COMPAT_SYSCALL_WRAP2(bdflush, int, func, long, data);
|
||||
COMPAT_SYSCALL_WRAP3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2);
|
||||
COMPAT_SYSCALL_WRAP5(llseek, unsigned int, fd, unsigned long, high, unsigned long, low, loff_t __user *, result, unsigned int, whence);
|
||||
COMPAT_SYSCALL_WRAP3(msync, unsigned long, start, size_t, len, int, flags);
|
||||
COMPAT_SYSCALL_WRAP2(mlock, unsigned long, start, size_t, len);
|
||||
COMPAT_SYSCALL_WRAP2(munlock, unsigned long, start, size_t, len);
|
||||
COMPAT_SYSCALL_WRAP2(sched_setparam, pid_t, pid, struct sched_param __user *, param);
|
||||
COMPAT_SYSCALL_WRAP2(sched_getparam, pid_t, pid, struct sched_param __user *, param);
|
||||
COMPAT_SYSCALL_WRAP3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param);
|
||||
COMPAT_SYSCALL_WRAP5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr);
|
||||
COMPAT_SYSCALL_WRAP3(poll, struct pollfd __user *, ufds, unsigned int, nfds, int, timeout);
|
||||
COMPAT_SYSCALL_WRAP5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5);
|
||||
COMPAT_SYSCALL_WRAP2(getcwd, char __user *, buf, unsigned long, size);
|
||||
COMPAT_SYSCALL_WRAP2(capget, cap_user_header_t, header, cap_user_data_t, dataptr);
|
||||
COMPAT_SYSCALL_WRAP2(capset, cap_user_header_t, header, const cap_user_data_t, data);
|
||||
COMPAT_SYSCALL_WRAP3(lchown, const char __user *, filename, uid_t, user, gid_t, group);
|
||||
COMPAT_SYSCALL_WRAP2(getgroups, int, gidsetsize, gid_t __user *, grouplist);
|
||||
COMPAT_SYSCALL_WRAP2(setgroups, int, gidsetsize, gid_t __user *, grouplist);
|
||||
COMPAT_SYSCALL_WRAP3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid);
|
||||
COMPAT_SYSCALL_WRAP3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid);
|
||||
COMPAT_SYSCALL_WRAP3(chown, const char __user *, filename, uid_t, user, gid_t, group);
|
||||
COMPAT_SYSCALL_WRAP2(pivot_root, const char __user *, new_root, const char __user *, put_old);
|
||||
COMPAT_SYSCALL_WRAP3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec);
|
||||
COMPAT_SYSCALL_WRAP3(madvise, unsigned long, start, size_t, len, int, behavior);
|
||||
COMPAT_SYSCALL_WRAP5(setxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
|
||||
COMPAT_SYSCALL_WRAP5(lsetxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
|
||||
COMPAT_SYSCALL_WRAP5(fsetxattr, int, fd, const char __user *, name, const void __user *, value, size_t, size, int, flags);
|
||||
COMPAT_SYSCALL_WRAP3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count);
|
||||
COMPAT_SYSCALL_WRAP4(getxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
|
||||
COMPAT_SYSCALL_WRAP4(lgetxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
|
||||
COMPAT_SYSCALL_WRAP4(fgetxattr, int, fd, const char __user *, name, void __user *, value, size_t, size);
|
||||
COMPAT_SYSCALL_WRAP3(listxattr, const char __user *, path, char __user *, list, size_t, size);
|
||||
COMPAT_SYSCALL_WRAP3(llistxattr, const char __user *, path, char __user *, list, size_t, size);
|
||||
COMPAT_SYSCALL_WRAP3(flistxattr, int, fd, char __user *, list, size_t, size);
|
||||
COMPAT_SYSCALL_WRAP2(removexattr, const char __user *, path, const char __user *, name);
|
||||
COMPAT_SYSCALL_WRAP2(lremovexattr, const char __user *, path, const char __user *, name);
|
||||
COMPAT_SYSCALL_WRAP2(fremovexattr, int, fd, const char __user *, name);
|
||||
COMPAT_SYSCALL_WRAP1(set_tid_address, int __user *, tidptr);
|
||||
COMPAT_SYSCALL_WRAP4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event);
|
||||
COMPAT_SYSCALL_WRAP4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout);
|
||||
COMPAT_SYSCALL_WRAP1(io_destroy, aio_context_t, ctx);
|
||||
COMPAT_SYSCALL_WRAP3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result);
|
||||
COMPAT_SYSCALL_WRAP1(mq_unlink, const char __user *, name);
|
||||
COMPAT_SYSCALL_WRAP5(add_key, const char __user *, tp, const char __user *, dsc, const void __user *, pld, size_t, len, key_serial_t, id);
|
||||
COMPAT_SYSCALL_WRAP4(request_key, const char __user *, tp, const char __user *, dsc, const char __user *, info, key_serial_t, id);
|
||||
COMPAT_SYSCALL_WRAP5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags);
|
||||
COMPAT_SYSCALL_WRAP3(inotify_add_watch, int, fd, const char __user *, path, u32, mask);
|
||||
COMPAT_SYSCALL_WRAP3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode);
|
||||
COMPAT_SYSCALL_WRAP4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, unsigned, dev);
|
||||
COMPAT_SYSCALL_WRAP5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag);
|
||||
COMPAT_SYSCALL_WRAP3(unlinkat, int, dfd, const char __user *, pathname, int, flag);
|
||||
COMPAT_SYSCALL_WRAP4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname);
|
||||
COMPAT_SYSCALL_WRAP5(linkat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, int, flags);
|
||||
COMPAT_SYSCALL_WRAP3(symlinkat, const char __user *, oldname, int, newdfd, const char __user *, newname);
|
||||
COMPAT_SYSCALL_WRAP4(readlinkat, int, dfd, const char __user *, path, char __user *, buf, int, bufsiz);
|
||||
COMPAT_SYSCALL_WRAP3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode);
|
||||
COMPAT_SYSCALL_WRAP3(faccessat, int, dfd, const char __user *, filename, int, mode);
|
||||
COMPAT_SYSCALL_WRAP1(unshare, unsigned long, unshare_flags);
|
||||
COMPAT_SYSCALL_WRAP6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP3(getcpu, unsigned __user *, cpu, unsigned __user *, node, struct getcpu_cache __user *, cache);
|
||||
COMPAT_SYSCALL_WRAP2(pipe2, int __user *, fildes, int, flags);
|
||||
COMPAT_SYSCALL_WRAP5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags);
|
||||
COMPAT_SYSCALL_WRAP5(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr, unsigned long, tls);
|
||||
COMPAT_SYSCALL_WRAP4(prlimit64, pid_t, pid, unsigned int, resource, const struct rlimit64 __user *, new_rlim, struct rlimit64 __user *, old_rlim);
|
||||
COMPAT_SYSCALL_WRAP5(name_to_handle_at, int, dfd, const char __user *, name, struct file_handle __user *, handle, int __user *, mnt_id, int, flag);
|
||||
COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2);
|
||||
COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
|
||||
COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, void __user *, uargs)
|
||||
COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
|
||||
COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
|
||||
COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
|
||||
COMPAT_SYSCALL_WRAP3(s390_pci_mmio_write, const unsigned long, mmio_addr, const void __user *, user_buffer, const size_t, length);
|
||||
COMPAT_SYSCALL_WRAP3(s390_pci_mmio_read, const unsigned long, mmio_addr, void __user *, user_buffer, const size_t, length);
|
||||
COMPAT_SYSCALL_WRAP4(socketpair, int, family, int, type, int, protocol, int __user *, usockvec);
|
||||
COMPAT_SYSCALL_WRAP3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen);
|
||||
COMPAT_SYSCALL_WRAP3(connect, int, fd, struct sockaddr __user *, uservaddr, int, addrlen);
|
||||
COMPAT_SYSCALL_WRAP4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, int __user *, upeer_addrlen, int, flags);
|
||||
COMPAT_SYSCALL_WRAP3(getsockname, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
|
||||
COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
|
||||
COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int, addr_len);
|
||||
COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags);
|
||||
COMPAT_SYSCALL_WRAP6(copy_file_range, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP2(s390_guarded_storage, int, command, struct gs_cb *, gs_cb);
|
||||
COMPAT_SYSCALL_WRAP5(statx, int, dfd, const char __user *, path, unsigned, flags, unsigned, mask, struct statx __user *, buffer);
|
||||
COMPAT_SYSCALL_WRAP4(s390_sthyi, unsigned long, code, void __user *, info, u64 __user *, rc, unsigned long, flags);
|
||||
COMPAT_SYSCALL_WRAP5(kexec_file_load, int, kernel_fd, int, initrd_fd, unsigned long, cmdline_len, const char __user *, cmdline_ptr, unsigned long, flags)
|
||||
COMPAT_SYSCALL_WRAP4(rseq, struct rseq __user *, rseq, u32, rseq_len, int, flags, u32, sig)
|
|
@ -1056,12 +1056,6 @@ int debug_register_view(debug_info_t *id, struct debug_view *view)
|
|||
mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
|
||||
pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
|
||||
id, &debug_file_ops);
|
||||
if (!pde) {
|
||||
pr_err("Registering view %s/%s failed due to out of "
|
||||
"memory\n", id->name, view->name);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
spin_lock_irqsave(&id->lock, flags);
|
||||
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
|
||||
if (!id->views[i])
|
||||
|
|
|
@ -45,6 +45,7 @@ static const struct diag_desc diag_map[NR_DIAG_STAT] = {
|
|||
[DIAG_STAT_X2FC] = { .code = 0x2fc, .name = "Guest Performance Data" },
|
||||
[DIAG_STAT_X304] = { .code = 0x304, .name = "Partition-Resource Service" },
|
||||
[DIAG_STAT_X308] = { .code = 0x308, .name = "List-Directed IPL" },
|
||||
[DIAG_STAT_X318] = { .code = 0x318, .name = "CP Name and Version Codes" },
|
||||
[DIAG_STAT_X500] = { .code = 0x500, .name = "Virtio Service" },
|
||||
};
|
||||
|
||||
|
|
|
@ -164,8 +164,6 @@ static noinline __init void setup_lowcore_early(void)
|
|||
|
||||
static noinline __init void setup_facility_list(void)
|
||||
{
|
||||
stfle(S390_lowcore.stfle_fac_list,
|
||||
ARRAY_SIZE(S390_lowcore.stfle_fac_list));
|
||||
memcpy(S390_lowcore.alt_stfle_fac_list,
|
||||
S390_lowcore.stfle_fac_list,
|
||||
sizeof(S390_lowcore.alt_stfle_fac_list));
|
||||
|
|
|
@ -1512,7 +1512,7 @@ cleanup_critical:
|
|||
.quad .Lsie_skip - .Lsie_entry
|
||||
#endif
|
||||
.section .rodata, "a"
|
||||
#define SYSCALL(esame,emu) .long esame
|
||||
#define SYSCALL(esame,emu) .long __s390x_ ## esame
|
||||
.globl sys_call_table
|
||||
sys_call_table:
|
||||
#include "asm/syscall_table.h"
|
||||
|
@ -1520,7 +1520,7 @@ sys_call_table:
|
|||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
#define SYSCALL(esame,emu) .long emu
|
||||
#define SYSCALL(esame,emu) .long __s390_ ## emu
|
||||
.globl sys_call_table_emu
|
||||
sys_call_table_emu:
|
||||
#include "asm/syscall_table.h"
|
||||
|
|
|
@ -27,8 +27,6 @@ ENTRY(startup_continue)
|
|||
mvc 0(16,%r1),__LC_BOOT_CLOCK
|
||||
larl %r13,.LPG1 # get base
|
||||
lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
|
||||
lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
|
||||
# move IPL device to lowcore
|
||||
larl %r0,boot_vdso_data
|
||||
stg %r0,__LC_VDSO_PER_CPU
|
||||
#
|
||||
|
|
|
@ -9,8 +9,6 @@ EXPORT_SYMBOL(arch_debugfs_dir);
|
|||
static int __init arch_kdebugfs_init(void)
|
||||
{
|
||||
arch_debugfs_dir = debugfs_create_dir("s390", NULL);
|
||||
if (IS_ERR(arch_debugfs_dir))
|
||||
arch_debugfs_dir = NULL;
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(arch_kdebugfs_init);
|
||||
|
|
|
@ -10,73 +10,11 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <asm/ctl_reg.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/cpu_mf.h>
|
||||
|
||||
enum cpumf_ctr_set {
|
||||
CPUMF_CTR_SET_BASIC = 0, /* Basic Counter Set */
|
||||
CPUMF_CTR_SET_USER = 1, /* Problem-State Counter Set */
|
||||
CPUMF_CTR_SET_CRYPTO = 2, /* Crypto-Activity Counter Set */
|
||||
CPUMF_CTR_SET_EXT = 3, /* Extended Counter Set */
|
||||
CPUMF_CTR_SET_MT_DIAG = 4, /* MT-diagnostic Counter Set */
|
||||
|
||||
/* Maximum number of counter sets */
|
||||
CPUMF_CTR_SET_MAX,
|
||||
};
|
||||
|
||||
#define CPUMF_LCCTL_ENABLE_SHIFT 16
|
||||
#define CPUMF_LCCTL_ACTCTL_SHIFT 0
|
||||
static const u64 cpumf_state_ctl[CPUMF_CTR_SET_MAX] = {
|
||||
[CPUMF_CTR_SET_BASIC] = 0x02,
|
||||
[CPUMF_CTR_SET_USER] = 0x04,
|
||||
[CPUMF_CTR_SET_CRYPTO] = 0x08,
|
||||
[CPUMF_CTR_SET_EXT] = 0x01,
|
||||
[CPUMF_CTR_SET_MT_DIAG] = 0x20,
|
||||
};
|
||||
|
||||
static void ctr_set_enable(u64 *state, int ctr_set)
|
||||
{
|
||||
*state |= cpumf_state_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT;
|
||||
}
|
||||
static void ctr_set_disable(u64 *state, int ctr_set)
|
||||
{
|
||||
*state &= ~(cpumf_state_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT);
|
||||
}
|
||||
static void ctr_set_start(u64 *state, int ctr_set)
|
||||
{
|
||||
*state |= cpumf_state_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT;
|
||||
}
|
||||
static void ctr_set_stop(u64 *state, int ctr_set)
|
||||
{
|
||||
*state &= ~(cpumf_state_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT);
|
||||
}
|
||||
|
||||
/* Local CPUMF event structure */
|
||||
struct cpu_hw_events {
|
||||
struct cpumf_ctr_info info;
|
||||
atomic_t ctr_set[CPUMF_CTR_SET_MAX];
|
||||
u64 state, tx_state;
|
||||
unsigned int flags;
|
||||
unsigned int txn_flags;
|
||||
};
|
||||
static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
|
||||
.ctr_set = {
|
||||
[CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_USER] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_MT_DIAG] = ATOMIC_INIT(0),
|
||||
},
|
||||
.state = 0,
|
||||
.flags = 0,
|
||||
.txn_flags = 0,
|
||||
};
|
||||
#include <asm/cpu_mcf.h>
|
||||
|
||||
static enum cpumf_ctr_set get_counter_set(u64 event)
|
||||
{
|
||||
|
@ -98,11 +36,11 @@ static enum cpumf_ctr_set get_counter_set(u64 event)
|
|||
|
||||
static int validate_ctr_version(const struct hw_perf_event *hwc)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw;
|
||||
struct cpu_cf_events *cpuhw;
|
||||
int err = 0;
|
||||
u16 mtdiag_ctl;
|
||||
|
||||
cpuhw = &get_cpu_var(cpu_hw_events);
|
||||
cpuhw = &get_cpu_var(cpu_cf_events);
|
||||
|
||||
/* check required version for counter sets */
|
||||
switch (hwc->config_base) {
|
||||
|
@ -135,7 +73,7 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
|
|||
* Thus, the counters can only be used if SMT is on and the
|
||||
* counter set is enabled and active.
|
||||
*/
|
||||
mtdiag_ctl = cpumf_state_ctl[CPUMF_CTR_SET_MT_DIAG];
|
||||
mtdiag_ctl = cpumf_ctr_ctl[CPUMF_CTR_SET_MT_DIAG];
|
||||
if (!((cpuhw->info.auth_ctl & mtdiag_ctl) &&
|
||||
(cpuhw->info.enable_ctl & mtdiag_ctl) &&
|
||||
(cpuhw->info.act_ctl & mtdiag_ctl)))
|
||||
|
@ -143,28 +81,28 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
|
|||
break;
|
||||
}
|
||||
|
||||
put_cpu_var(cpu_hw_events);
|
||||
put_cpu_var(cpu_cf_events);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int validate_ctr_auth(const struct hw_perf_event *hwc)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw;
|
||||
struct cpu_cf_events *cpuhw;
|
||||
u64 ctrs_state;
|
||||
int err = 0;
|
||||
|
||||
cpuhw = &get_cpu_var(cpu_hw_events);
|
||||
cpuhw = &get_cpu_var(cpu_cf_events);
|
||||
|
||||
/* Check authorization for cpu counter sets.
|
||||
* If the particular CPU counter set is not authorized,
|
||||
* return with -ENOENT in order to fall back to other
|
||||
* PMUs that might suffice the event request.
|
||||
*/
|
||||
ctrs_state = cpumf_state_ctl[hwc->config_base];
|
||||
ctrs_state = cpumf_ctr_ctl[hwc->config_base];
|
||||
if (!(ctrs_state & cpuhw->info.auth_ctl))
|
||||
err = -ENOENT;
|
||||
|
||||
put_cpu_var(cpu_hw_events);
|
||||
put_cpu_var(cpu_cf_events);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -175,7 +113,7 @@ static int validate_ctr_auth(const struct hw_perf_event *hwc)
|
|||
*/
|
||||
static void cpumf_pmu_enable(struct pmu *pmu)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
int err;
|
||||
|
||||
if (cpuhw->flags & PMU_F_ENABLED)
|
||||
|
@ -198,7 +136,7 @@ static void cpumf_pmu_enable(struct pmu *pmu)
|
|||
*/
|
||||
static void cpumf_pmu_disable(struct pmu *pmu)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
int err;
|
||||
u64 inactive;
|
||||
|
||||
|
@ -222,86 +160,13 @@ static atomic_t num_events = ATOMIC_INIT(0);
|
|||
/* Used to avoid races in calling reserve/release_cpumf_hardware */
|
||||
static DEFINE_MUTEX(pmc_reserve_mutex);
|
||||
|
||||
/* CPU-measurement alerts for the counter facility */
|
||||
static void cpumf_measurement_alert(struct ext_code ext_code,
|
||||
unsigned int alert, unsigned long unused)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw;
|
||||
|
||||
if (!(alert & CPU_MF_INT_CF_MASK))
|
||||
return;
|
||||
|
||||
inc_irq_stat(IRQEXT_CMC);
|
||||
cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
|
||||
/* Measurement alerts are shared and might happen when the PMU
|
||||
* is not reserved. Ignore these alerts in this case. */
|
||||
if (!(cpuhw->flags & PMU_F_RESERVED))
|
||||
return;
|
||||
|
||||
/* counter authorization change alert */
|
||||
if (alert & CPU_MF_INT_CF_CACA)
|
||||
qctri(&cpuhw->info);
|
||||
|
||||
/* loss of counter data alert */
|
||||
if (alert & CPU_MF_INT_CF_LCDA)
|
||||
pr_err("CPU[%i] Counter data was lost\n", smp_processor_id());
|
||||
|
||||
/* loss of MT counter data alert */
|
||||
if (alert & CPU_MF_INT_CF_MTDA)
|
||||
pr_warn("CPU[%i] MT counter data was lost\n",
|
||||
smp_processor_id());
|
||||
}
|
||||
|
||||
#define PMC_INIT 0
|
||||
#define PMC_RELEASE 1
|
||||
static void setup_pmc_cpu(void *flags)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
|
||||
switch (*((int *) flags)) {
|
||||
case PMC_INIT:
|
||||
memset(&cpuhw->info, 0, sizeof(cpuhw->info));
|
||||
qctri(&cpuhw->info);
|
||||
cpuhw->flags |= PMU_F_RESERVED;
|
||||
break;
|
||||
|
||||
case PMC_RELEASE:
|
||||
cpuhw->flags &= ~PMU_F_RESERVED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable CPU counter sets */
|
||||
lcctl(0);
|
||||
}
|
||||
|
||||
/* Initialize the CPU-measurement facility */
|
||||
static int reserve_pmc_hardware(void)
|
||||
{
|
||||
int flags = PMC_INIT;
|
||||
|
||||
on_each_cpu(setup_pmc_cpu, &flags, 1);
|
||||
irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Release the CPU-measurement facility */
|
||||
static void release_pmc_hardware(void)
|
||||
{
|
||||
int flags = PMC_RELEASE;
|
||||
|
||||
on_each_cpu(setup_pmc_cpu, &flags, 1);
|
||||
irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT);
|
||||
}
|
||||
|
||||
/* Release the PMU if event is the last perf event */
|
||||
static void hw_perf_event_destroy(struct perf_event *event)
|
||||
{
|
||||
if (!atomic_add_unless(&num_events, -1, 1)) {
|
||||
mutex_lock(&pmc_reserve_mutex);
|
||||
if (atomic_dec_return(&num_events) == 0)
|
||||
release_pmc_hardware();
|
||||
__kernel_cpumcf_end();
|
||||
mutex_unlock(&pmc_reserve_mutex);
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +197,7 @@ static int __hw_perf_event_init(struct perf_event *event)
|
|||
struct perf_event_attr *attr = &event->attr;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
enum cpumf_ctr_set set;
|
||||
int err;
|
||||
int err = 0;
|
||||
u64 ev;
|
||||
|
||||
switch (attr->type) {
|
||||
|
@ -402,12 +267,14 @@ static int __hw_perf_event_init(struct perf_event *event)
|
|||
/* Initialize for using the CPU-measurement counter facility */
|
||||
if (!atomic_inc_not_zero(&num_events)) {
|
||||
mutex_lock(&pmc_reserve_mutex);
|
||||
if (atomic_read(&num_events) == 0 && reserve_pmc_hardware())
|
||||
if (atomic_read(&num_events) == 0 && __kernel_cpumcf_begin())
|
||||
err = -EBUSY;
|
||||
else
|
||||
atomic_inc(&num_events);
|
||||
mutex_unlock(&pmc_reserve_mutex);
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
event->destroy = hw_perf_event_destroy;
|
||||
|
||||
/* Finally, validate version and authorization of the counter set */
|
||||
|
@ -488,7 +355,7 @@ static void cpumf_pmu_read(struct perf_event *event)
|
|||
|
||||
static void cpumf_pmu_start(struct perf_event *event, int flags)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
|
||||
|
@ -519,7 +386,7 @@ static void cpumf_pmu_start(struct perf_event *event, int flags)
|
|||
|
||||
static void cpumf_pmu_stop(struct perf_event *event, int flags)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
if (!(hwc->state & PERF_HES_STOPPED)) {
|
||||
|
@ -540,7 +407,7 @@ static void cpumf_pmu_stop(struct perf_event *event, int flags)
|
|||
|
||||
static int cpumf_pmu_add(struct perf_event *event, int flags)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
|
||||
/* Check authorization for the counter set to which this
|
||||
* counter belongs.
|
||||
|
@ -564,7 +431,7 @@ static int cpumf_pmu_add(struct perf_event *event, int flags)
|
|||
|
||||
static void cpumf_pmu_del(struct perf_event *event, int flags)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
|
||||
cpumf_pmu_stop(event, PERF_EF_UPDATE);
|
||||
|
||||
|
@ -592,7 +459,7 @@ static void cpumf_pmu_del(struct perf_event *event, int flags)
|
|||
*/
|
||||
static void cpumf_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
|
||||
WARN_ON_ONCE(cpuhw->txn_flags); /* txn already in flight */
|
||||
|
||||
|
@ -612,7 +479,7 @@ static void cpumf_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags)
|
|||
static void cpumf_pmu_cancel_txn(struct pmu *pmu)
|
||||
{
|
||||
unsigned int txn_flags;
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
|
||||
WARN_ON_ONCE(!cpuhw->txn_flags); /* no txn in flight */
|
||||
|
||||
|
@ -633,7 +500,7 @@ static void cpumf_pmu_cancel_txn(struct pmu *pmu)
|
|||
*/
|
||||
static int cpumf_pmu_commit_txn(struct pmu *pmu)
|
||||
{
|
||||
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
u64 state;
|
||||
|
||||
WARN_ON_ONCE(!cpuhw->txn_flags); /* no txn in flight */
|
||||
|
@ -671,54 +538,17 @@ static struct pmu cpumf_pmu = {
|
|||
.cancel_txn = cpumf_pmu_cancel_txn,
|
||||
};
|
||||
|
||||
static int cpumf_pmf_setup(unsigned int cpu, int flags)
|
||||
{
|
||||
local_irq_disable();
|
||||
setup_pmc_cpu(&flags);
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s390_pmu_online_cpu(unsigned int cpu)
|
||||
{
|
||||
return cpumf_pmf_setup(cpu, PMC_INIT);
|
||||
}
|
||||
|
||||
static int s390_pmu_offline_cpu(unsigned int cpu)
|
||||
{
|
||||
return cpumf_pmf_setup(cpu, PMC_RELEASE);
|
||||
}
|
||||
|
||||
static int __init cpumf_pmu_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!cpum_cf_avail())
|
||||
if (!kernel_cpumcf_avail())
|
||||
return -ENODEV;
|
||||
|
||||
/* clear bit 15 of cr0 to unauthorize problem-state to
|
||||
* extract measurement counters */
|
||||
ctl_clear_bit(0, 48);
|
||||
|
||||
/* register handler for measurement-alert interruptions */
|
||||
rc = register_external_irq(EXT_IRQ_MEASURE_ALERT,
|
||||
cpumf_measurement_alert);
|
||||
if (rc) {
|
||||
pr_err("Registering for CPU-measurement alerts "
|
||||
"failed with rc=%i\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
cpumf_pmu.attr_groups = cpumf_cf_event_group();
|
||||
rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
|
||||
if (rc) {
|
||||
if (rc)
|
||||
pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc);
|
||||
unregister_external_irq(EXT_IRQ_MEASURE_ALERT,
|
||||
cpumf_measurement_alert);
|
||||
return rc;
|
||||
}
|
||||
return cpuhp_setup_state(CPUHP_AP_PERF_S390_CF_ONLINE,
|
||||
"perf/s390/cf:online",
|
||||
s390_pmu_online_cpu, s390_pmu_offline_cpu);
|
||||
return rc;
|
||||
}
|
||||
early_initcall(cpumf_pmu_init);
|
||||
subsys_initcall(cpumf_pmu_init);
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* CPU-Measurement Counter Facility Support - Common Layer
|
||||
*
|
||||
* Copyright IBM Corp. 2019
|
||||
* Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
|
||||
*/
|
||||
#define KMSG_COMPONENT "cpum_cf_common"
|
||||
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <asm/ctl_reg.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/cpu_mcf.h>
|
||||
|
||||
/* Per-CPU event structure for the counter facility */
|
||||
DEFINE_PER_CPU(struct cpu_cf_events, cpu_cf_events) = {
|
||||
.ctr_set = {
|
||||
[CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_USER] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_MT_DIAG] = ATOMIC_INIT(0),
|
||||
},
|
||||
.alert = ATOMIC64_INIT(0),
|
||||
.state = 0,
|
||||
.flags = 0,
|
||||
.txn_flags = 0,
|
||||
};
|
||||
/* Indicator whether the CPU-Measurement Counter Facility Support is ready */
|
||||
static bool cpum_cf_initalized;
|
||||
|
||||
/* CPU-measurement alerts for the counter facility */
|
||||
static void cpumf_measurement_alert(struct ext_code ext_code,
|
||||
unsigned int alert, unsigned long unused)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw;
|
||||
|
||||
if (!(alert & CPU_MF_INT_CF_MASK))
|
||||
return;
|
||||
|
||||
inc_irq_stat(IRQEXT_CMC);
|
||||
cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
|
||||
/* Measurement alerts are shared and might happen when the PMU
|
||||
* is not reserved. Ignore these alerts in this case. */
|
||||
if (!(cpuhw->flags & PMU_F_RESERVED))
|
||||
return;
|
||||
|
||||
/* counter authorization change alert */
|
||||
if (alert & CPU_MF_INT_CF_CACA)
|
||||
qctri(&cpuhw->info);
|
||||
|
||||
/* loss of counter data alert */
|
||||
if (alert & CPU_MF_INT_CF_LCDA)
|
||||
pr_err("CPU[%i] Counter data was lost\n", smp_processor_id());
|
||||
|
||||
/* loss of MT counter data alert */
|
||||
if (alert & CPU_MF_INT_CF_MTDA)
|
||||
pr_warn("CPU[%i] MT counter data was lost\n",
|
||||
smp_processor_id());
|
||||
|
||||
/* store alert for special handling by in-kernel users */
|
||||
atomic64_or(alert, &cpuhw->alert);
|
||||
}
|
||||
|
||||
#define PMC_INIT 0
|
||||
#define PMC_RELEASE 1
|
||||
static void cpum_cf_setup_cpu(void *flags)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
|
||||
switch (*((int *) flags)) {
|
||||
case PMC_INIT:
|
||||
memset(&cpuhw->info, 0, sizeof(cpuhw->info));
|
||||
qctri(&cpuhw->info);
|
||||
cpuhw->flags |= PMU_F_RESERVED;
|
||||
break;
|
||||
|
||||
case PMC_RELEASE:
|
||||
cpuhw->flags &= ~PMU_F_RESERVED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable CPU counter sets */
|
||||
lcctl(0);
|
||||
}
|
||||
|
||||
bool kernel_cpumcf_avail(void)
|
||||
{
|
||||
return cpum_cf_initalized;
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_cpumcf_avail);
|
||||
|
||||
|
||||
/* Reserve/release functions for sharing perf hardware */
|
||||
static DEFINE_SPINLOCK(cpumcf_owner_lock);
|
||||
static void *cpumcf_owner;
|
||||
|
||||
/* Initialize the CPU-measurement counter facility */
|
||||
int __kernel_cpumcf_begin(void)
|
||||
{
|
||||
int flags = PMC_INIT;
|
||||
int err = 0;
|
||||
|
||||
spin_lock(&cpumcf_owner_lock);
|
||||
if (cpumcf_owner)
|
||||
err = -EBUSY;
|
||||
else
|
||||
cpumcf_owner = __builtin_return_address(0);
|
||||
spin_unlock(&cpumcf_owner_lock);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
on_each_cpu(cpum_cf_setup_cpu, &flags, 1);
|
||||
irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__kernel_cpumcf_begin);
|
||||
|
||||
/* Obtain the CPU-measurement alerts for the counter facility */
|
||||
unsigned long kernel_cpumcf_alert(int clear)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
unsigned long alert;
|
||||
|
||||
alert = atomic64_read(&cpuhw->alert);
|
||||
if (clear)
|
||||
atomic64_set(&cpuhw->alert, 0);
|
||||
|
||||
return alert;
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_cpumcf_alert);
|
||||
|
||||
/* Release the CPU-measurement counter facility */
|
||||
void __kernel_cpumcf_end(void)
|
||||
{
|
||||
int flags = PMC_RELEASE;
|
||||
|
||||
on_each_cpu(cpum_cf_setup_cpu, &flags, 1);
|
||||
irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT);
|
||||
|
||||
spin_lock(&cpumcf_owner_lock);
|
||||
cpumcf_owner = NULL;
|
||||
spin_unlock(&cpumcf_owner_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(__kernel_cpumcf_end);
|
||||
|
||||
static int cpum_cf_setup(unsigned int cpu, int flags)
|
||||
{
|
||||
local_irq_disable();
|
||||
cpum_cf_setup_cpu(&flags);
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpum_cf_online_cpu(unsigned int cpu)
|
||||
{
|
||||
return cpum_cf_setup(cpu, PMC_INIT);
|
||||
}
|
||||
|
||||
static int cpum_cf_offline_cpu(unsigned int cpu)
|
||||
{
|
||||
return cpum_cf_setup(cpu, PMC_RELEASE);
|
||||
}
|
||||
|
||||
static int __init cpum_cf_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!cpum_cf_avail())
|
||||
return -ENODEV;
|
||||
|
||||
/* clear bit 15 of cr0 to unauthorize problem-state to
|
||||
* extract measurement counters */
|
||||
ctl_clear_bit(0, 48);
|
||||
|
||||
/* register handler for measurement-alert interruptions */
|
||||
rc = register_external_irq(EXT_IRQ_MEASURE_ALERT,
|
||||
cpumf_measurement_alert);
|
||||
if (rc) {
|
||||
pr_err("Registering for CPU-measurement alerts "
|
||||
"failed with rc=%i\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cpuhp_setup_state(CPUHP_AP_PERF_S390_CF_ONLINE,
|
||||
"perf/s390/cf:online",
|
||||
cpum_cf_online_cpu, cpum_cf_offline_cpu);
|
||||
if (!rc)
|
||||
cpum_cf_initalized = true;
|
||||
|
||||
return rc;
|
||||
}
|
||||
early_initcall(cpum_cf_init);
|
|
@ -0,0 +1,693 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Performance event support for s390x - CPU-measurement Counter Sets
|
||||
*
|
||||
* Copyright IBM Corp. 2019
|
||||
* Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
|
||||
* Thomas Richer <tmricht@linux.ibm.com>
|
||||
*/
|
||||
#define KMSG_COMPONENT "cpum_cf_diag"
|
||||
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/processor.h>
|
||||
|
||||
#include <asm/ctl_reg.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/cpu_mcf.h>
|
||||
#include <asm/timex.h>
|
||||
#include <asm/debug.h>
|
||||
|
||||
#define CF_DIAG_CTRSET_DEF 0xfeef /* Counter set header mark */
|
||||
|
||||
static unsigned int cf_diag_cpu_speed;
|
||||
static debug_info_t *cf_diag_dbg;
|
||||
|
||||
struct cf_diag_csd { /* Counter set data per CPU */
|
||||
size_t used; /* Bytes used in data/start */
|
||||
unsigned char start[PAGE_SIZE]; /* Counter set at event start */
|
||||
unsigned char data[PAGE_SIZE]; /* Counter set at event delete */
|
||||
};
|
||||
DEFINE_PER_CPU(struct cf_diag_csd, cf_diag_csd);
|
||||
|
||||
/* Counter sets are stored as data stream in a page sized memory buffer and
|
||||
* exported to user space via raw data attached to the event sample data.
|
||||
* Each counter set starts with an eight byte header consisting of:
|
||||
* - a two byte eye catcher (0xfeef)
|
||||
* - a one byte counter set number
|
||||
* - a two byte counter set size (indicates the number of counters in this set)
|
||||
* - a three byte reserved value (must be zero) to make the header the same
|
||||
* size as a counter value.
|
||||
* All counter values are eight byte in size.
|
||||
*
|
||||
* All counter sets are followed by a 64 byte trailer.
|
||||
* The trailer consists of a:
|
||||
* - flag field indicating valid fields when corresponding bit set
|
||||
* - the counter facility first and second version number
|
||||
* - the CPU speed if nonzero
|
||||
* - the time stamp the counter sets have been collected
|
||||
* - the time of day (TOD) base value
|
||||
* - the machine type.
|
||||
*
|
||||
* The counter sets are saved when the process is prepared to be executed on a
|
||||
* CPU and saved again when the process is going to be removed from a CPU.
|
||||
* The difference of both counter sets are calculated and stored in the event
|
||||
* sample data area.
|
||||
*/
|
||||
|
||||
struct cf_ctrset_entry { /* CPU-M CF counter set entry (8 byte) */
|
||||
unsigned int def:16; /* 0-15 Data Entry Format */
|
||||
unsigned int set:16; /* 16-31 Counter set identifier */
|
||||
unsigned int ctr:16; /* 32-47 Number of stored counters */
|
||||
unsigned int res1:16; /* 48-63 Reserved */
|
||||
};
|
||||
|
||||
struct cf_trailer_entry { /* CPU-M CF_DIAG trailer (64 byte) */
|
||||
/* 0 - 7 */
|
||||
union {
|
||||
struct {
|
||||
unsigned int clock_base:1; /* TOD clock base set */
|
||||
unsigned int speed:1; /* CPU speed set */
|
||||
/* Measurement alerts */
|
||||
unsigned int mtda:1; /* Loss of MT ctr. data alert */
|
||||
unsigned int caca:1; /* Counter auth. change alert */
|
||||
unsigned int lcda:1; /* Loss of counter data alert */
|
||||
};
|
||||
unsigned long flags; /* 0-63 All indicators */
|
||||
};
|
||||
/* 8 - 15 */
|
||||
unsigned int cfvn:16; /* 64-79 Ctr First Version */
|
||||
unsigned int csvn:16; /* 80-95 Ctr Second Version */
|
||||
unsigned int cpu_speed:32; /* 96-127 CPU speed */
|
||||
/* 16 - 23 */
|
||||
unsigned long timestamp; /* 128-191 Timestamp (TOD) */
|
||||
/* 24 - 55 */
|
||||
union {
|
||||
struct {
|
||||
unsigned long progusage1;
|
||||
unsigned long progusage2;
|
||||
unsigned long progusage3;
|
||||
unsigned long tod_base;
|
||||
};
|
||||
unsigned long progusage[4];
|
||||
};
|
||||
/* 56 - 63 */
|
||||
unsigned int mach_type:16; /* Machine type */
|
||||
unsigned int res1:16; /* Reserved */
|
||||
unsigned int res2:32; /* Reserved */
|
||||
};
|
||||
|
||||
/* Create the trailer data at the end of a page. */
|
||||
static void cf_diag_trailer(struct cf_trailer_entry *te)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
struct cpuid cpuid;
|
||||
|
||||
te->cfvn = cpuhw->info.cfvn; /* Counter version numbers */
|
||||
te->csvn = cpuhw->info.csvn;
|
||||
|
||||
get_cpu_id(&cpuid); /* Machine type */
|
||||
te->mach_type = cpuid.machine;
|
||||
te->cpu_speed = cf_diag_cpu_speed;
|
||||
if (te->cpu_speed)
|
||||
te->speed = 1;
|
||||
te->clock_base = 1; /* Save clock base */
|
||||
memcpy(&te->tod_base, &tod_clock_base[1], 8);
|
||||
store_tod_clock((__u64 *)&te->timestamp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the CPUMF state to active.
|
||||
* Enable and activate the CPU-counter sets according
|
||||
* to the per-cpu control state.
|
||||
*/
|
||||
static void cf_diag_enable(struct pmu *pmu)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
int err;
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s pmu %p cpu %d flags %#x state %#llx\n",
|
||||
__func__, pmu, smp_processor_id(), cpuhw->flags,
|
||||
cpuhw->state);
|
||||
if (cpuhw->flags & PMU_F_ENABLED)
|
||||
return;
|
||||
|
||||
err = lcctl(cpuhw->state);
|
||||
if (err) {
|
||||
pr_err("Enabling the performance measuring unit "
|
||||
"failed with rc=%x\n", err);
|
||||
return;
|
||||
}
|
||||
cpuhw->flags |= PMU_F_ENABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the CPUMF state to inactive.
|
||||
* Disable and enable (inactive) the CPU-counter sets according
|
||||
* to the per-cpu control state.
|
||||
*/
|
||||
static void cf_diag_disable(struct pmu *pmu)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
u64 inactive;
|
||||
int err;
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s pmu %p cpu %d flags %#x state %#llx\n",
|
||||
__func__, pmu, smp_processor_id(), cpuhw->flags,
|
||||
cpuhw->state);
|
||||
if (!(cpuhw->flags & PMU_F_ENABLED))
|
||||
return;
|
||||
|
||||
inactive = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1);
|
||||
err = lcctl(inactive);
|
||||
if (err) {
|
||||
pr_err("Disabling the performance measuring unit "
|
||||
"failed with rc=%x\n", err);
|
||||
return;
|
||||
}
|
||||
cpuhw->flags &= ~PMU_F_ENABLED;
|
||||
}
|
||||
|
||||
/* Number of perf events counting hardware events */
|
||||
static atomic_t cf_diag_events = ATOMIC_INIT(0);
|
||||
|
||||
/* Release the PMU if event is the last perf event */
|
||||
static void cf_diag_perf_event_destroy(struct perf_event *event)
|
||||
{
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s event %p cpu %d cf_diag_events %d\n",
|
||||
__func__, event, event->cpu,
|
||||
atomic_read(&cf_diag_events));
|
||||
if (atomic_dec_return(&cf_diag_events) == 0)
|
||||
__kernel_cpumcf_end();
|
||||
}
|
||||
|
||||
/* Setup the event. Test for authorized counter sets and only include counter
|
||||
* sets which are authorized at the time of the setup. Including unauthorized
|
||||
* counter sets result in specification exception (and panic).
|
||||
*/
|
||||
static int __hw_perf_event_init(struct perf_event *event)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
struct perf_event_attr *attr = &event->attr;
|
||||
enum cpumf_ctr_set i;
|
||||
int err = 0;
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s event %p cpu %d authorized %#x\n", __func__,
|
||||
event, event->cpu, cpuhw->info.auth_ctl);
|
||||
|
||||
event->hw.config = attr->config;
|
||||
event->hw.config_base = 0;
|
||||
local64_set(&event->count, 0);
|
||||
|
||||
/* Add all authorized counter sets to config_base */
|
||||
for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i)
|
||||
if (cpuhw->info.auth_ctl & cpumf_ctr_ctl[i])
|
||||
event->hw.config_base |= cpumf_ctr_ctl[i];
|
||||
|
||||
/* No authorized counter sets, nothing to count/sample */
|
||||
if (!event->hw.config_base) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set sample_period to indicate sampling */
|
||||
event->hw.sample_period = attr->sample_period;
|
||||
local64_set(&event->hw.period_left, event->hw.sample_period);
|
||||
event->hw.last_period = event->hw.sample_period;
|
||||
out:
|
||||
debug_sprintf_event(cf_diag_dbg, 5, "%s err %d config_base %#lx\n",
|
||||
__func__, err, event->hw.config_base);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cf_diag_event_init(struct perf_event *event)
|
||||
{
|
||||
struct perf_event_attr *attr = &event->attr;
|
||||
int err = -ENOENT;
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s event %p cpu %d config %#llx "
|
||||
"sample_type %#llx cf_diag_events %d\n", __func__,
|
||||
event, event->cpu, attr->config, attr->sample_type,
|
||||
atomic_read(&cf_diag_events));
|
||||
|
||||
if (event->attr.config != PERF_EVENT_CPUM_CF_DIAG ||
|
||||
event->attr.type != PERF_TYPE_RAW)
|
||||
goto out;
|
||||
|
||||
/* Raw events are used to access counters directly,
|
||||
* hence do not permit excludes.
|
||||
* This event is usesless without PERF_SAMPLE_RAW to return counter set
|
||||
* values as raw data.
|
||||
*/
|
||||
if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv ||
|
||||
!(attr->sample_type & (PERF_SAMPLE_CPU | PERF_SAMPLE_RAW))) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Initialize for using the CPU-measurement counter facility */
|
||||
if (atomic_inc_return(&cf_diag_events) == 1) {
|
||||
if (__kernel_cpumcf_begin()) {
|
||||
atomic_dec(&cf_diag_events);
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
event->destroy = cf_diag_perf_event_destroy;
|
||||
|
||||
err = __hw_perf_event_init(event);
|
||||
if (unlikely(err))
|
||||
event->destroy(event);
|
||||
out:
|
||||
debug_sprintf_event(cf_diag_dbg, 5, "%s err %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void cf_diag_read(struct perf_event *event)
|
||||
{
|
||||
debug_sprintf_event(cf_diag_dbg, 5, "%s event %p\n", __func__, event);
|
||||
}
|
||||
|
||||
/* Return the maximum possible counter set size (in number of 8 byte counters)
|
||||
* depending on type and model number.
|
||||
*/
|
||||
static size_t cf_diag_ctrset_size(enum cpumf_ctr_set ctrset,
|
||||
struct cpumf_ctr_info *info)
|
||||
{
|
||||
size_t ctrset_size = 0;
|
||||
|
||||
switch (ctrset) {
|
||||
case CPUMF_CTR_SET_BASIC:
|
||||
if (info->cfvn >= 1)
|
||||
ctrset_size = 6;
|
||||
break;
|
||||
case CPUMF_CTR_SET_USER:
|
||||
if (info->cfvn == 1)
|
||||
ctrset_size = 6;
|
||||
else if (info->cfvn >= 3)
|
||||
ctrset_size = 2;
|
||||
break;
|
||||
case CPUMF_CTR_SET_CRYPTO:
|
||||
ctrset_size = 16;
|
||||
break;
|
||||
case CPUMF_CTR_SET_EXT:
|
||||
if (info->csvn == 1)
|
||||
ctrset_size = 32;
|
||||
else if (info->csvn == 2)
|
||||
ctrset_size = 48;
|
||||
else if (info->csvn >= 3)
|
||||
ctrset_size = 128;
|
||||
break;
|
||||
case CPUMF_CTR_SET_MT_DIAG:
|
||||
if (info->csvn > 3)
|
||||
ctrset_size = 48;
|
||||
break;
|
||||
case CPUMF_CTR_SET_MAX:
|
||||
break;
|
||||
}
|
||||
|
||||
return ctrset_size;
|
||||
}
|
||||
|
||||
/* Calculate memory needed to store all counter sets together with header and
|
||||
* trailer data. This is independend of the counter set authorization which
|
||||
* can vary depending on the configuration.
|
||||
*/
|
||||
static size_t cf_diag_ctrset_maxsize(struct cpumf_ctr_info *info)
|
||||
{
|
||||
size_t max_size = sizeof(struct cf_trailer_entry);
|
||||
enum cpumf_ctr_set i;
|
||||
|
||||
for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
|
||||
size_t size = cf_diag_ctrset_size(i, info);
|
||||
|
||||
if (size)
|
||||
max_size += size * sizeof(u64) +
|
||||
sizeof(struct cf_ctrset_entry);
|
||||
}
|
||||
debug_sprintf_event(cf_diag_dbg, 5, "%s max_size %zu\n", __func__,
|
||||
max_size);
|
||||
|
||||
return max_size;
|
||||
}
|
||||
|
||||
/* Read a counter set. The counter set number determines which counter set and
|
||||
* the CPUM-CF first and second version number determine the number of
|
||||
* available counters in this counter set.
|
||||
* Each counter set starts with header containing the counter set number and
|
||||
* the number of 8 byte counters.
|
||||
*
|
||||
* The functions returns the number of bytes occupied by this counter set
|
||||
* including the header.
|
||||
* If there is no counter in the counter set, this counter set is useless and
|
||||
* zero is returned on this case.
|
||||
*/
|
||||
static size_t cf_diag_getctrset(struct cf_ctrset_entry *ctrdata, int ctrset,
|
||||
size_t room)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
size_t ctrset_size, need = 0;
|
||||
int rc = 3; /* Assume write failure */
|
||||
|
||||
ctrdata->def = CF_DIAG_CTRSET_DEF;
|
||||
ctrdata->set = ctrset;
|
||||
ctrdata->res1 = 0;
|
||||
ctrset_size = cf_diag_ctrset_size(ctrset, &cpuhw->info);
|
||||
|
||||
if (ctrset_size) { /* Save data */
|
||||
need = ctrset_size * sizeof(u64) + sizeof(*ctrdata);
|
||||
if (need <= room)
|
||||
rc = ctr_stcctm(ctrset, ctrset_size,
|
||||
(u64 *)(ctrdata + 1));
|
||||
if (rc != 3)
|
||||
ctrdata->ctr = ctrset_size;
|
||||
else
|
||||
need = 0;
|
||||
}
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 6,
|
||||
"%s ctrset %d ctrset_size %zu cfvn %d csvn %d"
|
||||
" need %zd rc:%d\n",
|
||||
__func__, ctrset, ctrset_size, cpuhw->info.cfvn,
|
||||
cpuhw->info.csvn, need, rc);
|
||||
return need;
|
||||
}
|
||||
|
||||
/* Read out all counter sets and save them in the provided data buffer.
|
||||
* The last 64 byte host an artificial trailer entry.
|
||||
*/
|
||||
static size_t cf_diag_getctr(void *data, size_t sz, unsigned long auth)
|
||||
{
|
||||
struct cf_trailer_entry *trailer;
|
||||
size_t offset = 0, done;
|
||||
int i;
|
||||
|
||||
memset(data, 0, sz);
|
||||
sz -= sizeof(*trailer); /* Always room for trailer */
|
||||
for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
|
||||
struct cf_ctrset_entry *ctrdata = data + offset;
|
||||
|
||||
if (!(auth & cpumf_ctr_ctl[i]))
|
||||
continue; /* Counter set not authorized */
|
||||
|
||||
done = cf_diag_getctrset(ctrdata, i, sz - offset);
|
||||
offset += done;
|
||||
debug_sprintf_event(cf_diag_dbg, 6,
|
||||
"%s ctrset %d offset %zu done %zu\n",
|
||||
__func__, i, offset, done);
|
||||
}
|
||||
trailer = data + offset;
|
||||
cf_diag_trailer(trailer);
|
||||
return offset + sizeof(*trailer);
|
||||
}
|
||||
|
||||
/* Calculate the difference for each counter in a counter set. */
|
||||
static void cf_diag_diffctrset(u64 *pstart, u64 *pstop, int counters)
|
||||
{
|
||||
for (; --counters >= 0; ++pstart, ++pstop)
|
||||
if (*pstop >= *pstart)
|
||||
*pstop -= *pstart;
|
||||
else
|
||||
*pstop = *pstart - *pstop;
|
||||
}
|
||||
|
||||
/* Scan the counter sets and calculate the difference of each counter
|
||||
* in each set. The result is the increment of each counter during the
|
||||
* period the counter set has been activated.
|
||||
*
|
||||
* Return true on success.
|
||||
*/
|
||||
static int cf_diag_diffctr(struct cf_diag_csd *csd, unsigned long auth)
|
||||
{
|
||||
struct cf_trailer_entry *trailer_start, *trailer_stop;
|
||||
struct cf_ctrset_entry *ctrstart, *ctrstop;
|
||||
size_t offset = 0;
|
||||
|
||||
auth &= (1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1;
|
||||
do {
|
||||
ctrstart = (struct cf_ctrset_entry *)(csd->start + offset);
|
||||
ctrstop = (struct cf_ctrset_entry *)(csd->data + offset);
|
||||
|
||||
if (memcmp(ctrstop, ctrstart, sizeof(*ctrstop))) {
|
||||
pr_err("cpum_cf_diag counter set compare error "
|
||||
"in set %i\n", ctrstart->set);
|
||||
return 0;
|
||||
}
|
||||
auth &= ~cpumf_ctr_ctl[ctrstart->set];
|
||||
if (ctrstart->def == CF_DIAG_CTRSET_DEF) {
|
||||
cf_diag_diffctrset((u64 *)(ctrstart + 1),
|
||||
(u64 *)(ctrstop + 1), ctrstart->ctr);
|
||||
offset += ctrstart->ctr * sizeof(u64) +
|
||||
sizeof(*ctrstart);
|
||||
}
|
||||
debug_sprintf_event(cf_diag_dbg, 6,
|
||||
"%s set %d ctr %d offset %zu auth %lx\n",
|
||||
__func__, ctrstart->set, ctrstart->ctr,
|
||||
offset, auth);
|
||||
} while (ctrstart->def && auth);
|
||||
|
||||
/* Save time_stamp from start of event in stop's trailer */
|
||||
trailer_start = (struct cf_trailer_entry *)(csd->start + offset);
|
||||
trailer_stop = (struct cf_trailer_entry *)(csd->data + offset);
|
||||
trailer_stop->progusage[0] = trailer_start->timestamp;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create perf event sample with the counter sets as raw data. The sample
|
||||
* is then pushed to the event subsystem and the function checks for
|
||||
* possible event overflows. If an event overflow occurs, the PMU is
|
||||
* stopped.
|
||||
*
|
||||
* Return non-zero if an event overflow occurred.
|
||||
*/
|
||||
static int cf_diag_push_sample(struct perf_event *event,
|
||||
struct cf_diag_csd *csd)
|
||||
{
|
||||
struct perf_sample_data data;
|
||||
struct perf_raw_record raw;
|
||||
struct pt_regs regs;
|
||||
int overflow;
|
||||
|
||||
/* Setup perf sample */
|
||||
perf_sample_data_init(&data, 0, event->hw.last_period);
|
||||
memset(®s, 0, sizeof(regs));
|
||||
memset(&raw, 0, sizeof(raw));
|
||||
|
||||
if (event->attr.sample_type & PERF_SAMPLE_CPU)
|
||||
data.cpu_entry.cpu = event->cpu;
|
||||
if (event->attr.sample_type & PERF_SAMPLE_RAW) {
|
||||
raw.frag.size = csd->used;
|
||||
raw.frag.data = csd->data;
|
||||
raw.size = csd->used;
|
||||
data.raw = &raw;
|
||||
}
|
||||
|
||||
overflow = perf_event_overflow(event, &data, ®s);
|
||||
debug_sprintf_event(cf_diag_dbg, 6,
|
||||
"%s event %p cpu %d sample_type %#llx raw %d "
|
||||
"ov %d\n", __func__, event, event->cpu,
|
||||
event->attr.sample_type, raw.size, overflow);
|
||||
if (overflow)
|
||||
event->pmu->stop(event, 0);
|
||||
|
||||
perf_event_update_userpage(event);
|
||||
return overflow;
|
||||
}
|
||||
|
||||
static void cf_diag_start(struct perf_event *event, int flags)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
struct cf_diag_csd *csd = this_cpu_ptr(&cf_diag_csd);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s event %p cpu %d flags %#x hwc-state %#x\n",
|
||||
__func__, event, event->cpu, flags, hwc->state);
|
||||
if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
|
||||
return;
|
||||
|
||||
/* (Re-)enable and activate all counter sets */
|
||||
lcctl(0); /* Reset counter sets */
|
||||
hwc->state = 0;
|
||||
ctr_set_multiple_enable(&cpuhw->state, hwc->config_base);
|
||||
lcctl(cpuhw->state); /* Enable counter sets */
|
||||
csd->used = cf_diag_getctr(csd->start, sizeof(csd->start),
|
||||
event->hw.config_base);
|
||||
ctr_set_multiple_start(&cpuhw->state, hwc->config_base);
|
||||
/* Function cf_diag_enable() starts the counter sets. */
|
||||
}
|
||||
|
||||
static void cf_diag_stop(struct perf_event *event, int flags)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
struct cf_diag_csd *csd = this_cpu_ptr(&cf_diag_csd);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s event %p cpu %d flags %#x hwc-state %#x\n",
|
||||
__func__, event, event->cpu, flags, hwc->state);
|
||||
|
||||
/* Deactivate all counter sets */
|
||||
ctr_set_multiple_stop(&cpuhw->state, hwc->config_base);
|
||||
local64_inc(&event->count);
|
||||
csd->used = cf_diag_getctr(csd->data, sizeof(csd->data),
|
||||
event->hw.config_base);
|
||||
if (cf_diag_diffctr(csd, event->hw.config_base))
|
||||
cf_diag_push_sample(event, csd);
|
||||
hwc->state |= PERF_HES_STOPPED;
|
||||
}
|
||||
|
||||
static int cf_diag_add(struct perf_event *event, int flags)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
int err = 0;
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s event %p cpu %d flags %#x cpuhw:%p\n",
|
||||
__func__, event, event->cpu, flags, cpuhw);
|
||||
|
||||
if (cpuhw->flags & PMU_F_IN_USE) {
|
||||
err = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
|
||||
|
||||
cpuhw->flags |= PMU_F_IN_USE;
|
||||
if (flags & PERF_EF_START)
|
||||
cf_diag_start(event, PERF_EF_RELOAD);
|
||||
out:
|
||||
debug_sprintf_event(cf_diag_dbg, 5, "%s err %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void cf_diag_del(struct perf_event *event, int flags)
|
||||
{
|
||||
struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
|
||||
|
||||
debug_sprintf_event(cf_diag_dbg, 5,
|
||||
"%s event %p cpu %d flags %#x\n",
|
||||
__func__, event, event->cpu, flags);
|
||||
|
||||
cf_diag_stop(event, PERF_EF_UPDATE);
|
||||
ctr_set_multiple_stop(&cpuhw->state, event->hw.config_base);
|
||||
ctr_set_multiple_disable(&cpuhw->state, event->hw.config_base);
|
||||
cpuhw->flags &= ~PMU_F_IN_USE;
|
||||
}
|
||||
|
||||
CPUMF_EVENT_ATTR(CF_DIAG, CF_DIAG, PERF_EVENT_CPUM_CF_DIAG);
|
||||
|
||||
static struct attribute *cf_diag_events_attr[] = {
|
||||
CPUMF_EVENT_PTR(CF_DIAG, CF_DIAG),
|
||||
NULL,
|
||||
};
|
||||
|
||||
PMU_FORMAT_ATTR(event, "config:0-63");
|
||||
|
||||
static struct attribute *cf_diag_format_attr[] = {
|
||||
&format_attr_event.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group cf_diag_events_group = {
|
||||
.name = "events",
|
||||
.attrs = cf_diag_events_attr,
|
||||
};
|
||||
static struct attribute_group cf_diag_format_group = {
|
||||
.name = "format",
|
||||
.attrs = cf_diag_format_attr,
|
||||
};
|
||||
static const struct attribute_group *cf_diag_attr_groups[] = {
|
||||
&cf_diag_events_group,
|
||||
&cf_diag_format_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Performance monitoring unit for s390x */
|
||||
static struct pmu cf_diag = {
|
||||
.task_ctx_nr = perf_sw_context,
|
||||
.pmu_enable = cf_diag_enable,
|
||||
.pmu_disable = cf_diag_disable,
|
||||
.event_init = cf_diag_event_init,
|
||||
.add = cf_diag_add,
|
||||
.del = cf_diag_del,
|
||||
.start = cf_diag_start,
|
||||
.stop = cf_diag_stop,
|
||||
.read = cf_diag_read,
|
||||
|
||||
.attr_groups = cf_diag_attr_groups
|
||||
};
|
||||
|
||||
/* Get the CPU speed, try sampling facility first and CPU attributes second. */
|
||||
static void cf_diag_get_cpu_speed(void)
|
||||
{
|
||||
if (cpum_sf_avail()) { /* Sampling facility first */
|
||||
struct hws_qsi_info_block si;
|
||||
|
||||
memset(&si, 0, sizeof(si));
|
||||
if (!qsi(&si)) {
|
||||
cf_diag_cpu_speed = si.cpu_speed;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (test_facility(34)) { /* CPU speed extract static part */
|
||||
unsigned long mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0);
|
||||
|
||||
if (mhz != -1UL)
|
||||
cf_diag_cpu_speed = mhz & 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the counter set PMU to generate complete counter set data as
|
||||
* event raw data. This relies on the CPU Measurement Counter Facility device
|
||||
* already being loaded and initialized.
|
||||
*/
|
||||
static int __init cf_diag_init(void)
|
||||
{
|
||||
struct cpumf_ctr_info info;
|
||||
size_t need;
|
||||
int rc;
|
||||
|
||||
if (!kernel_cpumcf_avail() || !stccm_avail() || qctri(&info))
|
||||
return -ENODEV;
|
||||
cf_diag_get_cpu_speed();
|
||||
|
||||
/* Make sure the counter set data fits into predefined buffer. */
|
||||
need = cf_diag_ctrset_maxsize(&info);
|
||||
if (need > sizeof(((struct cf_diag_csd *)0)->start)) {
|
||||
pr_err("Insufficient memory for PMU(cpum_cf_diag) need=%zu\n",
|
||||
need);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Setup s390dbf facility */
|
||||
cf_diag_dbg = debug_register(KMSG_COMPONENT, 2, 1, 128);
|
||||
if (!cf_diag_dbg) {
|
||||
pr_err("Registration of s390dbf(cpum_cf_diag) failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
debug_register_view(cf_diag_dbg, &debug_sprintf_view);
|
||||
|
||||
rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", PERF_TYPE_RAW);
|
||||
if (rc) {
|
||||
debug_unregister_view(cf_diag_dbg, &debug_sprintf_view);
|
||||
debug_unregister(cf_diag_dbg);
|
||||
pr_err("Registration of PMU(cpum_cf_diag) failed with rc=%i\n",
|
||||
rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
arch_initcall(cf_diag_init);
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <asm/cpu_mf.h>
|
||||
|
||||
|
||||
/* BEGIN: CPUM_CF COUNTER DEFINITIONS =================================== */
|
||||
|
|
|
@ -369,7 +369,7 @@ void __init arch_call_rest_init(void)
|
|||
: : [_frame] "a" (frame));
|
||||
}
|
||||
|
||||
static void __init setup_lowcore(void)
|
||||
static void __init setup_lowcore_dat_off(void)
|
||||
{
|
||||
struct lowcore *lc;
|
||||
|
||||
|
@ -380,19 +380,16 @@ static void __init setup_lowcore(void)
|
|||
lc = memblock_alloc_low(sizeof(*lc), sizeof(*lc));
|
||||
lc->restart_psw.mask = PSW_KERNEL_BITS;
|
||||
lc->restart_psw.addr = (unsigned long) restart_int_handler;
|
||||
lc->external_new_psw.mask = PSW_KERNEL_BITS |
|
||||
PSW_MASK_DAT | PSW_MASK_MCHECK;
|
||||
lc->external_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
|
||||
lc->external_new_psw.addr = (unsigned long) ext_int_handler;
|
||||
lc->svc_new_psw.mask = PSW_KERNEL_BITS |
|
||||
PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
|
||||
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
|
||||
lc->svc_new_psw.addr = (unsigned long) system_call;
|
||||
lc->program_new_psw.mask = PSW_KERNEL_BITS |
|
||||
PSW_MASK_DAT | PSW_MASK_MCHECK;
|
||||
lc->program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
|
||||
lc->program_new_psw.addr = (unsigned long) pgm_check_handler;
|
||||
lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
|
||||
lc->mcck_new_psw.addr = (unsigned long) mcck_int_handler;
|
||||
lc->io_new_psw.mask = PSW_KERNEL_BITS |
|
||||
PSW_MASK_DAT | PSW_MASK_MCHECK;
|
||||
lc->io_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
|
||||
lc->io_new_psw.addr = (unsigned long) io_int_handler;
|
||||
lc->clock_comparator = clock_comparator_max;
|
||||
lc->nodat_stack = ((unsigned long) &init_thread_union)
|
||||
|
@ -452,6 +449,16 @@ static void __init setup_lowcore(void)
|
|||
lowcore_ptr[0] = lc;
|
||||
}
|
||||
|
||||
static void __init setup_lowcore_dat_on(void)
|
||||
{
|
||||
__ctl_clear_bit(0, 28);
|
||||
S390_lowcore.external_new_psw.mask |= PSW_MASK_DAT;
|
||||
S390_lowcore.svc_new_psw.mask |= PSW_MASK_DAT;
|
||||
S390_lowcore.program_new_psw.mask |= PSW_MASK_DAT;
|
||||
S390_lowcore.io_new_psw.mask |= PSW_MASK_DAT;
|
||||
__ctl_set_bit(0, 28);
|
||||
}
|
||||
|
||||
static struct resource code_resource = {
|
||||
.name = "Kernel code",
|
||||
.flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
|
||||
|
@ -794,18 +801,9 @@ static void __init reserve_kernel(void)
|
|||
{
|
||||
unsigned long start_pfn = PFN_UP(__pa(_end));
|
||||
|
||||
#ifdef CONFIG_DMA_API_DEBUG
|
||||
/*
|
||||
* DMA_API_DEBUG code stumbles over addresses from the
|
||||
* range [PARMAREA_END, _stext]. Mark the memory as reserved
|
||||
* so it is not used for CONFIG_DMA_API_DEBUG=y.
|
||||
*/
|
||||
memblock_reserve(0, PFN_PHYS(start_pfn));
|
||||
#else
|
||||
memblock_reserve(0, PARMAREA_END);
|
||||
memblock_reserve((unsigned long)_stext, PFN_PHYS(start_pfn)
|
||||
- (unsigned long)_stext);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init setup_memory(void)
|
||||
|
@ -989,6 +987,25 @@ static void __init setup_task_size(void)
|
|||
arch_task_struct_size = task_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue diagnose 318 to set the control program name and
|
||||
* version codes.
|
||||
*/
|
||||
static void __init setup_control_program_code(void)
|
||||
{
|
||||
union diag318_info diag318_info = {
|
||||
.cpnc = CPNC_LINUX,
|
||||
.cpvc_linux = 0,
|
||||
.cpvc_distro = {0},
|
||||
};
|
||||
|
||||
if (!sclp.has_diag318)
|
||||
return;
|
||||
|
||||
diag_stat_inc(DIAG_STAT_X318);
|
||||
asm volatile("diag %0,0,0x318\n" : : "d" (diag318_info.val));
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup function called from init/main.c just after the banner
|
||||
* was printed.
|
||||
|
@ -1033,6 +1050,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
os_info_init();
|
||||
setup_ipl();
|
||||
setup_task_size();
|
||||
setup_control_program_code();
|
||||
|
||||
/* Do some memory reservations *before* memory is added to memblock */
|
||||
reserve_memory_end();
|
||||
|
@ -1072,7 +1090,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
#endif
|
||||
|
||||
setup_resources();
|
||||
setup_lowcore();
|
||||
setup_lowcore_dat_off();
|
||||
smp_fill_possible_mask();
|
||||
cpu_detect_mhz_feature();
|
||||
cpu_init();
|
||||
|
@ -1085,6 +1103,12 @@ void __init setup_arch(char **cmdline_p)
|
|||
*/
|
||||
paging_init();
|
||||
|
||||
/*
|
||||
* After paging_init created the kernel page table, the new PSWs
|
||||
* in lowcore can now run with DAT enabled.
|
||||
*/
|
||||
setup_lowcore_dat_on();
|
||||
|
||||
/* Setup default console */
|
||||
conmode_default();
|
||||
set_preferred_console();
|
||||
|
|
|
@ -124,13 +124,13 @@ ENTRY(swsusp_arch_resume)
|
|||
lghi %r2,1
|
||||
brasl %r14,arch_set_page_states
|
||||
|
||||
/* Deactivate DAT */
|
||||
stnsm __SF_EMPTY(%r15),0xfb
|
||||
|
||||
/* Set prefix page to zero */
|
||||
xc __SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
|
||||
spx __SF_EMPTY(%r15)
|
||||
|
||||
/* Deactivate DAT */
|
||||
stnsm __SF_EMPTY(%r15),0xfb
|
||||
|
||||
/* Restore saved image */
|
||||
larl %r1,restore_pblist
|
||||
lg %r1,0(%r1)
|
||||
|
|
|
@ -58,6 +58,7 @@ out:
|
|||
return error;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSVIPC
|
||||
/*
|
||||
* sys_ipc() is the de-multiplexer for the SysV IPC calls.
|
||||
*/
|
||||
|
@ -74,19 +75,28 @@ SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second,
|
|||
* Therefore we can call the generic variant by simply passing the
|
||||
* third parameter also as fifth parameter.
|
||||
*/
|
||||
return sys_ipc(call, first, second, third, ptr, third);
|
||||
return ksys_ipc(call, first, second, third, ptr, third);
|
||||
}
|
||||
#endif /* CONFIG_SYSVIPC */
|
||||
|
||||
SYSCALL_DEFINE1(s390_personality, unsigned int, personality)
|
||||
{
|
||||
unsigned int ret;
|
||||
unsigned int ret = current->personality;
|
||||
|
||||
if (personality(current->personality) == PER_LINUX32 &&
|
||||
personality(personality) == PER_LINUX)
|
||||
personality |= PER_LINUX32;
|
||||
ret = sys_personality(personality);
|
||||
|
||||
if (personality != 0xffffffff)
|
||||
set_personality(personality);
|
||||
|
||||
if (personality(ret) == PER_LINUX32)
|
||||
ret &= ~PER_LINUX32;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE0(ni_syscall)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -15,86 +15,86 @@
|
|||
5 common open sys_open compat_sys_open
|
||||
6 common close sys_close sys_close
|
||||
7 common restart_syscall sys_restart_syscall sys_restart_syscall
|
||||
8 common creat sys_creat compat_sys_creat
|
||||
9 common link sys_link compat_sys_link
|
||||
10 common unlink sys_unlink compat_sys_unlink
|
||||
8 common creat sys_creat sys_creat
|
||||
9 common link sys_link sys_link
|
||||
10 common unlink sys_unlink sys_unlink
|
||||
11 common execve sys_execve compat_sys_execve
|
||||
12 common chdir sys_chdir compat_sys_chdir
|
||||
12 common chdir sys_chdir sys_chdir
|
||||
13 32 time - compat_sys_time
|
||||
14 common mknod sys_mknod compat_sys_mknod
|
||||
15 common chmod sys_chmod compat_sys_chmod
|
||||
16 32 lchown - compat_sys_s390_lchown16
|
||||
14 common mknod sys_mknod sys_mknod
|
||||
15 common chmod sys_chmod sys_chmod
|
||||
16 32 lchown - sys_lchown16
|
||||
19 common lseek sys_lseek compat_sys_lseek
|
||||
20 common getpid sys_getpid sys_getpid
|
||||
21 common mount sys_mount compat_sys_mount
|
||||
22 common umount sys_oldumount compat_sys_oldumount
|
||||
23 32 setuid - compat_sys_s390_setuid16
|
||||
24 32 getuid - compat_sys_s390_getuid16
|
||||
22 common umount sys_oldumount sys_oldumount
|
||||
23 32 setuid - sys_setuid16
|
||||
24 32 getuid - sys_getuid16
|
||||
25 32 stime - compat_sys_stime
|
||||
26 common ptrace sys_ptrace compat_sys_ptrace
|
||||
27 common alarm sys_alarm sys_alarm
|
||||
29 common pause sys_pause sys_pause
|
||||
30 common utime sys_utime compat_sys_utime
|
||||
33 common access sys_access compat_sys_access
|
||||
33 common access sys_access sys_access
|
||||
34 common nice sys_nice sys_nice
|
||||
36 common sync sys_sync sys_sync
|
||||
37 common kill sys_kill sys_kill
|
||||
38 common rename sys_rename compat_sys_rename
|
||||
39 common mkdir sys_mkdir compat_sys_mkdir
|
||||
40 common rmdir sys_rmdir compat_sys_rmdir
|
||||
38 common rename sys_rename sys_rename
|
||||
39 common mkdir sys_mkdir sys_mkdir
|
||||
40 common rmdir sys_rmdir sys_rmdir
|
||||
41 common dup sys_dup sys_dup
|
||||
42 common pipe sys_pipe compat_sys_pipe
|
||||
42 common pipe sys_pipe sys_pipe
|
||||
43 common times sys_times compat_sys_times
|
||||
45 common brk sys_brk compat_sys_brk
|
||||
46 32 setgid - compat_sys_s390_setgid16
|
||||
47 32 getgid - compat_sys_s390_getgid16
|
||||
48 common signal sys_signal compat_sys_signal
|
||||
49 32 geteuid - compat_sys_s390_geteuid16
|
||||
50 32 getegid - compat_sys_s390_getegid16
|
||||
51 common acct sys_acct compat_sys_acct
|
||||
52 common umount2 sys_umount compat_sys_umount
|
||||
45 common brk sys_brk sys_brk
|
||||
46 32 setgid - sys_setgid16
|
||||
47 32 getgid - sys_getgid16
|
||||
48 common signal sys_signal sys_signal
|
||||
49 32 geteuid - sys_geteuid16
|
||||
50 32 getegid - sys_getegid16
|
||||
51 common acct sys_acct sys_acct
|
||||
52 common umount2 sys_umount sys_umount
|
||||
54 common ioctl sys_ioctl compat_sys_ioctl
|
||||
55 common fcntl sys_fcntl compat_sys_fcntl
|
||||
57 common setpgid sys_setpgid sys_setpgid
|
||||
60 common umask sys_umask sys_umask
|
||||
61 common chroot sys_chroot compat_sys_chroot
|
||||
61 common chroot sys_chroot sys_chroot
|
||||
62 common ustat sys_ustat compat_sys_ustat
|
||||
63 common dup2 sys_dup2 sys_dup2
|
||||
64 common getppid sys_getppid sys_getppid
|
||||
65 common getpgrp sys_getpgrp sys_getpgrp
|
||||
66 common setsid sys_setsid sys_setsid
|
||||
67 common sigaction sys_sigaction compat_sys_sigaction
|
||||
70 32 setreuid - compat_sys_s390_setreuid16
|
||||
71 32 setregid - compat_sys_s390_setregid16
|
||||
72 common sigsuspend sys_sigsuspend compat_sys_sigsuspend
|
||||
70 32 setreuid - sys_setreuid16
|
||||
71 32 setregid - sys_setregid16
|
||||
72 common sigsuspend sys_sigsuspend sys_sigsuspend
|
||||
73 common sigpending sys_sigpending compat_sys_sigpending
|
||||
74 common sethostname sys_sethostname compat_sys_sethostname
|
||||
74 common sethostname sys_sethostname sys_sethostname
|
||||
75 common setrlimit sys_setrlimit compat_sys_setrlimit
|
||||
76 32 getrlimit - compat_sys_old_getrlimit
|
||||
77 common getrusage sys_getrusage compat_sys_getrusage
|
||||
78 common gettimeofday sys_gettimeofday compat_sys_gettimeofday
|
||||
79 common settimeofday sys_settimeofday compat_sys_settimeofday
|
||||
80 32 getgroups - compat_sys_s390_getgroups16
|
||||
81 32 setgroups - compat_sys_s390_setgroups16
|
||||
83 common symlink sys_symlink compat_sys_symlink
|
||||
85 common readlink sys_readlink compat_sys_readlink
|
||||
86 common uselib sys_uselib compat_sys_uselib
|
||||
87 common swapon sys_swapon compat_sys_swapon
|
||||
88 common reboot sys_reboot compat_sys_reboot
|
||||
80 32 getgroups - sys_getgroups16
|
||||
81 32 setgroups - sys_setgroups16
|
||||
83 common symlink sys_symlink sys_symlink
|
||||
85 common readlink sys_readlink sys_readlink
|
||||
86 common uselib sys_uselib sys_uselib
|
||||
87 common swapon sys_swapon sys_swapon
|
||||
88 common reboot sys_reboot sys_reboot
|
||||
89 common readdir - compat_sys_old_readdir
|
||||
90 common mmap sys_old_mmap compat_sys_s390_old_mmap
|
||||
91 common munmap sys_munmap compat_sys_munmap
|
||||
91 common munmap sys_munmap sys_munmap
|
||||
92 common truncate sys_truncate compat_sys_truncate
|
||||
93 common ftruncate sys_ftruncate compat_sys_ftruncate
|
||||
94 common fchmod sys_fchmod sys_fchmod
|
||||
95 32 fchown - compat_sys_s390_fchown16
|
||||
95 32 fchown - sys_fchown16
|
||||
96 common getpriority sys_getpriority sys_getpriority
|
||||
97 common setpriority sys_setpriority sys_setpriority
|
||||
99 common statfs sys_statfs compat_sys_statfs
|
||||
100 common fstatfs sys_fstatfs compat_sys_fstatfs
|
||||
101 32 ioperm - -
|
||||
102 common socketcall sys_socketcall compat_sys_socketcall
|
||||
103 common syslog sys_syslog compat_sys_syslog
|
||||
103 common syslog sys_syslog sys_syslog
|
||||
104 common setitimer sys_setitimer compat_sys_setitimer
|
||||
105 common getitimer sys_getitimer compat_sys_getitimer
|
||||
106 common stat sys_newstat compat_sys_newstat
|
||||
|
@ -104,63 +104,63 @@
|
|||
111 common vhangup sys_vhangup sys_vhangup
|
||||
112 common idle - -
|
||||
114 common wait4 sys_wait4 compat_sys_wait4
|
||||
115 common swapoff sys_swapoff compat_sys_swapoff
|
||||
115 common swapoff sys_swapoff sys_swapoff
|
||||
116 common sysinfo sys_sysinfo compat_sys_sysinfo
|
||||
117 common ipc sys_s390_ipc compat_sys_s390_ipc
|
||||
118 common fsync sys_fsync sys_fsync
|
||||
119 common sigreturn sys_sigreturn compat_sys_sigreturn
|
||||
120 common clone sys_clone compat_sys_clone
|
||||
121 common setdomainname sys_setdomainname compat_sys_setdomainname
|
||||
122 common uname sys_newuname compat_sys_newuname
|
||||
120 common clone sys_clone sys_clone
|
||||
121 common setdomainname sys_setdomainname sys_setdomainname
|
||||
122 common uname sys_newuname sys_newuname
|
||||
124 common adjtimex sys_adjtimex compat_sys_adjtimex
|
||||
125 common mprotect sys_mprotect compat_sys_mprotect
|
||||
125 common mprotect sys_mprotect sys_mprotect
|
||||
126 common sigprocmask sys_sigprocmask compat_sys_sigprocmask
|
||||
127 common create_module - -
|
||||
128 common init_module sys_init_module compat_sys_init_module
|
||||
129 common delete_module sys_delete_module compat_sys_delete_module
|
||||
128 common init_module sys_init_module sys_init_module
|
||||
129 common delete_module sys_delete_module sys_delete_module
|
||||
130 common get_kernel_syms - -
|
||||
131 common quotactl sys_quotactl compat_sys_quotactl
|
||||
131 common quotactl sys_quotactl sys_quotactl
|
||||
132 common getpgid sys_getpgid sys_getpgid
|
||||
133 common fchdir sys_fchdir sys_fchdir
|
||||
134 common bdflush sys_bdflush compat_sys_bdflush
|
||||
135 common sysfs sys_sysfs compat_sys_sysfs
|
||||
134 common bdflush sys_bdflush sys_bdflush
|
||||
135 common sysfs sys_sysfs sys_sysfs
|
||||
136 common personality sys_s390_personality sys_s390_personality
|
||||
137 common afs_syscall - -
|
||||
138 32 setfsuid - compat_sys_s390_setfsuid16
|
||||
139 32 setfsgid - compat_sys_s390_setfsgid16
|
||||
140 32 _llseek - compat_sys_llseek
|
||||
138 32 setfsuid - sys_setfsuid16
|
||||
139 32 setfsgid - sys_setfsgid16
|
||||
140 32 _llseek - sys_llseek
|
||||
141 common getdents sys_getdents compat_sys_getdents
|
||||
142 32 _newselect - compat_sys_select
|
||||
142 64 select sys_select -
|
||||
143 common flock sys_flock sys_flock
|
||||
144 common msync sys_msync compat_sys_msync
|
||||
144 common msync sys_msync sys_msync
|
||||
145 common readv sys_readv compat_sys_readv
|
||||
146 common writev sys_writev compat_sys_writev
|
||||
147 common getsid sys_getsid sys_getsid
|
||||
148 common fdatasync sys_fdatasync sys_fdatasync
|
||||
149 common _sysctl sys_sysctl compat_sys_sysctl
|
||||
150 common mlock sys_mlock compat_sys_mlock
|
||||
151 common munlock sys_munlock compat_sys_munlock
|
||||
150 common mlock sys_mlock sys_mlock
|
||||
151 common munlock sys_munlock sys_munlock
|
||||
152 common mlockall sys_mlockall sys_mlockall
|
||||
153 common munlockall sys_munlockall sys_munlockall
|
||||
154 common sched_setparam sys_sched_setparam compat_sys_sched_setparam
|
||||
155 common sched_getparam sys_sched_getparam compat_sys_sched_getparam
|
||||
156 common sched_setscheduler sys_sched_setscheduler compat_sys_sched_setscheduler
|
||||
154 common sched_setparam sys_sched_setparam sys_sched_setparam
|
||||
155 common sched_getparam sys_sched_getparam sys_sched_getparam
|
||||
156 common sched_setscheduler sys_sched_setscheduler sys_sched_setscheduler
|
||||
157 common sched_getscheduler sys_sched_getscheduler sys_sched_getscheduler
|
||||
158 common sched_yield sys_sched_yield sys_sched_yield
|
||||
159 common sched_get_priority_max sys_sched_get_priority_max sys_sched_get_priority_max
|
||||
160 common sched_get_priority_min sys_sched_get_priority_min sys_sched_get_priority_min
|
||||
161 common sched_rr_get_interval sys_sched_rr_get_interval compat_sys_sched_rr_get_interval
|
||||
162 common nanosleep sys_nanosleep compat_sys_nanosleep
|
||||
163 common mremap sys_mremap compat_sys_mremap
|
||||
164 32 setresuid - compat_sys_s390_setresuid16
|
||||
165 32 getresuid - compat_sys_s390_getresuid16
|
||||
163 common mremap sys_mremap sys_mremap
|
||||
164 32 setresuid - sys_setresuid16
|
||||
165 32 getresuid - sys_getresuid16
|
||||
167 common query_module - -
|
||||
168 common poll sys_poll compat_sys_poll
|
||||
168 common poll sys_poll sys_poll
|
||||
169 common nfsservctl - -
|
||||
170 32 setresgid - compat_sys_s390_setresgid16
|
||||
171 32 getresgid - compat_sys_s390_getresgid16
|
||||
172 common prctl sys_prctl compat_sys_prctl
|
||||
170 32 setresgid - sys_setresgid16
|
||||
171 32 getresgid - sys_getresgid16
|
||||
172 common prctl sys_prctl sys_prctl
|
||||
173 common rt_sigreturn sys_rt_sigreturn compat_sys_rt_sigreturn
|
||||
174 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction
|
||||
175 common rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask
|
||||
|
@ -170,10 +170,10 @@
|
|||
179 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend
|
||||
180 common pread64 sys_pread64 compat_sys_s390_pread64
|
||||
181 common pwrite64 sys_pwrite64 compat_sys_s390_pwrite64
|
||||
182 32 chown - compat_sys_s390_chown16
|
||||
183 common getcwd sys_getcwd compat_sys_getcwd
|
||||
184 common capget sys_capget compat_sys_capget
|
||||
185 common capset sys_capset compat_sys_capset
|
||||
182 32 chown - sys_chown16
|
||||
183 common getcwd sys_getcwd sys_getcwd
|
||||
184 common capget sys_capget sys_capget
|
||||
185 common capset sys_capset sys_capset
|
||||
186 common sigaltstack sys_sigaltstack compat_sys_sigaltstack
|
||||
187 common sendfile sys_sendfile64 compat_sys_sendfile
|
||||
188 common getpmsg - -
|
||||
|
@ -187,7 +187,7 @@
|
|||
195 32 stat64 - compat_sys_s390_stat64
|
||||
196 32 lstat64 - compat_sys_s390_lstat64
|
||||
197 32 fstat64 - compat_sys_s390_fstat64
|
||||
198 32 lchown32 - compat_sys_lchown
|
||||
198 32 lchown32 - sys_lchown
|
||||
198 64 lchown sys_lchown -
|
||||
199 32 getuid32 - sys_getuid
|
||||
199 64 getuid sys_getuid -
|
||||
|
@ -201,21 +201,21 @@
|
|||
203 64 setreuid sys_setreuid -
|
||||
204 32 setregid32 - sys_setregid
|
||||
204 64 setregid sys_setregid -
|
||||
205 32 getgroups32 - compat_sys_getgroups
|
||||
205 32 getgroups32 - sys_getgroups
|
||||
205 64 getgroups sys_getgroups -
|
||||
206 32 setgroups32 - compat_sys_setgroups
|
||||
206 32 setgroups32 - sys_setgroups
|
||||
206 64 setgroups sys_setgroups -
|
||||
207 32 fchown32 - sys_fchown
|
||||
207 64 fchown sys_fchown -
|
||||
208 32 setresuid32 - sys_setresuid
|
||||
208 64 setresuid sys_setresuid -
|
||||
209 32 getresuid32 - compat_sys_getresuid
|
||||
209 32 getresuid32 - sys_getresuid
|
||||
209 64 getresuid sys_getresuid -
|
||||
210 32 setresgid32 - sys_setresgid
|
||||
210 64 setresgid sys_setresgid -
|
||||
211 32 getresgid32 - compat_sys_getresgid
|
||||
211 32 getresgid32 - sys_getresgid
|
||||
211 64 getresgid sys_getresgid -
|
||||
212 32 chown32 - compat_sys_chown
|
||||
212 32 chown32 - sys_chown
|
||||
212 64 chown sys_chown -
|
||||
213 32 setuid32 - sys_setuid
|
||||
213 64 setuid sys_setuid -
|
||||
|
@ -225,25 +225,25 @@
|
|||
215 64 setfsuid sys_setfsuid -
|
||||
216 32 setfsgid32 - sys_setfsgid
|
||||
216 64 setfsgid sys_setfsgid -
|
||||
217 common pivot_root sys_pivot_root compat_sys_pivot_root
|
||||
218 common mincore sys_mincore compat_sys_mincore
|
||||
219 common madvise sys_madvise compat_sys_madvise
|
||||
220 common getdents64 sys_getdents64 compat_sys_getdents64
|
||||
217 common pivot_root sys_pivot_root sys_pivot_root
|
||||
218 common mincore sys_mincore sys_mincore
|
||||
219 common madvise sys_madvise sys_madvise
|
||||
220 common getdents64 sys_getdents64 sys_getdents64
|
||||
221 32 fcntl64 - compat_sys_fcntl64
|
||||
222 common readahead sys_readahead compat_sys_s390_readahead
|
||||
223 32 sendfile64 - compat_sys_sendfile64
|
||||
224 common setxattr sys_setxattr compat_sys_setxattr
|
||||
225 common lsetxattr sys_lsetxattr compat_sys_lsetxattr
|
||||
226 common fsetxattr sys_fsetxattr compat_sys_fsetxattr
|
||||
227 common getxattr sys_getxattr compat_sys_getxattr
|
||||
228 common lgetxattr sys_lgetxattr compat_sys_lgetxattr
|
||||
229 common fgetxattr sys_fgetxattr compat_sys_fgetxattr
|
||||
230 common listxattr sys_listxattr compat_sys_listxattr
|
||||
231 common llistxattr sys_llistxattr compat_sys_llistxattr
|
||||
232 common flistxattr sys_flistxattr compat_sys_flistxattr
|
||||
233 common removexattr sys_removexattr compat_sys_removexattr
|
||||
234 common lremovexattr sys_lremovexattr compat_sys_lremovexattr
|
||||
235 common fremovexattr sys_fremovexattr compat_sys_fremovexattr
|
||||
224 common setxattr sys_setxattr sys_setxattr
|
||||
225 common lsetxattr sys_lsetxattr sys_lsetxattr
|
||||
226 common fsetxattr sys_fsetxattr sys_fsetxattr
|
||||
227 common getxattr sys_getxattr sys_getxattr
|
||||
228 common lgetxattr sys_lgetxattr sys_lgetxattr
|
||||
229 common fgetxattr sys_fgetxattr sys_fgetxattr
|
||||
230 common listxattr sys_listxattr sys_listxattr
|
||||
231 common llistxattr sys_llistxattr sys_llistxattr
|
||||
232 common flistxattr sys_flistxattr sys_flistxattr
|
||||
233 common removexattr sys_removexattr sys_removexattr
|
||||
234 common lremovexattr sys_lremovexattr sys_lremovexattr
|
||||
235 common fremovexattr sys_fremovexattr sys_fremovexattr
|
||||
236 common gettid sys_gettid sys_gettid
|
||||
237 common tkill sys_tkill sys_tkill
|
||||
238 common futex sys_futex compat_sys_futex
|
||||
|
@ -251,15 +251,15 @@
|
|||
240 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity
|
||||
241 common tgkill sys_tgkill sys_tgkill
|
||||
243 common io_setup sys_io_setup compat_sys_io_setup
|
||||
244 common io_destroy sys_io_destroy compat_sys_io_destroy
|
||||
244 common io_destroy sys_io_destroy sys_io_destroy
|
||||
245 common io_getevents sys_io_getevents compat_sys_io_getevents
|
||||
246 common io_submit sys_io_submit compat_sys_io_submit
|
||||
247 common io_cancel sys_io_cancel compat_sys_io_cancel
|
||||
247 common io_cancel sys_io_cancel sys_io_cancel
|
||||
248 common exit_group sys_exit_group sys_exit_group
|
||||
249 common epoll_create sys_epoll_create sys_epoll_create
|
||||
250 common epoll_ctl sys_epoll_ctl compat_sys_epoll_ctl
|
||||
251 common epoll_wait sys_epoll_wait compat_sys_epoll_wait
|
||||
252 common set_tid_address sys_set_tid_address compat_sys_set_tid_address
|
||||
250 common epoll_ctl sys_epoll_ctl sys_epoll_ctl
|
||||
251 common epoll_wait sys_epoll_wait sys_epoll_wait
|
||||
252 common set_tid_address sys_set_tid_address sys_set_tid_address
|
||||
253 common fadvise64 sys_fadvise64_64 compat_sys_s390_fadvise64
|
||||
254 common timer_create sys_timer_create compat_sys_timer_create
|
||||
255 common timer_settime sys_timer_settime compat_sys_timer_settime
|
||||
|
@ -273,52 +273,52 @@
|
|||
264 32 fadvise64_64 - compat_sys_s390_fadvise64_64
|
||||
265 common statfs64 sys_statfs64 compat_sys_statfs64
|
||||
266 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64
|
||||
267 common remap_file_pages sys_remap_file_pages compat_sys_remap_file_pages
|
||||
267 common remap_file_pages sys_remap_file_pages sys_remap_file_pages
|
||||
268 common mbind sys_mbind compat_sys_mbind
|
||||
269 common get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
|
||||
270 common set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
|
||||
271 common mq_open sys_mq_open compat_sys_mq_open
|
||||
272 common mq_unlink sys_mq_unlink compat_sys_mq_unlink
|
||||
272 common mq_unlink sys_mq_unlink sys_mq_unlink
|
||||
273 common mq_timedsend sys_mq_timedsend compat_sys_mq_timedsend
|
||||
274 common mq_timedreceive sys_mq_timedreceive compat_sys_mq_timedreceive
|
||||
275 common mq_notify sys_mq_notify compat_sys_mq_notify
|
||||
276 common mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr
|
||||
277 common kexec_load sys_kexec_load compat_sys_kexec_load
|
||||
278 common add_key sys_add_key compat_sys_add_key
|
||||
279 common request_key sys_request_key compat_sys_request_key
|
||||
278 common add_key sys_add_key sys_add_key
|
||||
279 common request_key sys_request_key sys_request_key
|
||||
280 common keyctl sys_keyctl compat_sys_keyctl
|
||||
281 common waitid sys_waitid compat_sys_waitid
|
||||
282 common ioprio_set sys_ioprio_set sys_ioprio_set
|
||||
283 common ioprio_get sys_ioprio_get sys_ioprio_get
|
||||
284 common inotify_init sys_inotify_init sys_inotify_init
|
||||
285 common inotify_add_watch sys_inotify_add_watch compat_sys_inotify_add_watch
|
||||
285 common inotify_add_watch sys_inotify_add_watch sys_inotify_add_watch
|
||||
286 common inotify_rm_watch sys_inotify_rm_watch sys_inotify_rm_watch
|
||||
287 common migrate_pages sys_migrate_pages compat_sys_migrate_pages
|
||||
288 common openat sys_openat compat_sys_openat
|
||||
289 common mkdirat sys_mkdirat compat_sys_mkdirat
|
||||
290 common mknodat sys_mknodat compat_sys_mknodat
|
||||
291 common fchownat sys_fchownat compat_sys_fchownat
|
||||
289 common mkdirat sys_mkdirat sys_mkdirat
|
||||
290 common mknodat sys_mknodat sys_mknodat
|
||||
291 common fchownat sys_fchownat sys_fchownat
|
||||
292 common futimesat sys_futimesat compat_sys_futimesat
|
||||
293 32 fstatat64 - compat_sys_s390_fstatat64
|
||||
293 64 newfstatat sys_newfstatat -
|
||||
294 common unlinkat sys_unlinkat compat_sys_unlinkat
|
||||
295 common renameat sys_renameat compat_sys_renameat
|
||||
296 common linkat sys_linkat compat_sys_linkat
|
||||
297 common symlinkat sys_symlinkat compat_sys_symlinkat
|
||||
298 common readlinkat sys_readlinkat compat_sys_readlinkat
|
||||
299 common fchmodat sys_fchmodat compat_sys_fchmodat
|
||||
300 common faccessat sys_faccessat compat_sys_faccessat
|
||||
294 common unlinkat sys_unlinkat sys_unlinkat
|
||||
295 common renameat sys_renameat sys_renameat
|
||||
296 common linkat sys_linkat sys_linkat
|
||||
297 common symlinkat sys_symlinkat sys_symlinkat
|
||||
298 common readlinkat sys_readlinkat sys_readlinkat
|
||||
299 common fchmodat sys_fchmodat sys_fchmodat
|
||||
300 common faccessat sys_faccessat sys_faccessat
|
||||
301 common pselect6 sys_pselect6 compat_sys_pselect6
|
||||
302 common ppoll sys_ppoll compat_sys_ppoll
|
||||
303 common unshare sys_unshare compat_sys_unshare
|
||||
303 common unshare sys_unshare sys_unshare
|
||||
304 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
|
||||
305 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
|
||||
306 common splice sys_splice compat_sys_splice
|
||||
306 common splice sys_splice sys_splice
|
||||
307 common sync_file_range sys_sync_file_range compat_sys_s390_sync_file_range
|
||||
308 common tee sys_tee compat_sys_tee
|
||||
308 common tee sys_tee sys_tee
|
||||
309 common vmsplice sys_vmsplice compat_sys_vmsplice
|
||||
310 common move_pages sys_move_pages compat_sys_move_pages
|
||||
311 common getcpu sys_getcpu compat_sys_getcpu
|
||||
311 common getcpu sys_getcpu sys_getcpu
|
||||
312 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
|
||||
313 common utimes sys_utimes compat_sys_utimes
|
||||
314 common fallocate sys_fallocate compat_sys_s390_fallocate
|
||||
|
@ -332,17 +332,17 @@
|
|||
322 common signalfd4 sys_signalfd4 compat_sys_signalfd4
|
||||
323 common eventfd2 sys_eventfd2 sys_eventfd2
|
||||
324 common inotify_init1 sys_inotify_init1 sys_inotify_init1
|
||||
325 common pipe2 sys_pipe2 compat_sys_pipe2
|
||||
325 common pipe2 sys_pipe2 sys_pipe2
|
||||
326 common dup3 sys_dup3 sys_dup3
|
||||
327 common epoll_create1 sys_epoll_create1 sys_epoll_create1
|
||||
328 common preadv sys_preadv compat_sys_preadv
|
||||
329 common pwritev sys_pwritev compat_sys_pwritev
|
||||
330 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
|
||||
331 common perf_event_open sys_perf_event_open compat_sys_perf_event_open
|
||||
331 common perf_event_open sys_perf_event_open sys_perf_event_open
|
||||
332 common fanotify_init sys_fanotify_init sys_fanotify_init
|
||||
333 common fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark
|
||||
334 common prlimit64 sys_prlimit64 compat_sys_prlimit64
|
||||
335 common name_to_handle_at sys_name_to_handle_at compat_sys_name_to_handle_at
|
||||
334 common prlimit64 sys_prlimit64 sys_prlimit64
|
||||
335 common name_to_handle_at sys_name_to_handle_at sys_name_to_handle_at
|
||||
336 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at
|
||||
337 common clock_adjtime sys_clock_adjtime compat_sys_clock_adjtime
|
||||
338 common syncfs sys_syncfs sys_syncfs
|
||||
|
@ -350,44 +350,44 @@
|
|||
340 common process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv
|
||||
341 common process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev
|
||||
342 common s390_runtime_instr sys_s390_runtime_instr sys_s390_runtime_instr
|
||||
343 common kcmp sys_kcmp compat_sys_kcmp
|
||||
344 common finit_module sys_finit_module compat_sys_finit_module
|
||||
345 common sched_setattr sys_sched_setattr compat_sys_sched_setattr
|
||||
346 common sched_getattr sys_sched_getattr compat_sys_sched_getattr
|
||||
347 common renameat2 sys_renameat2 compat_sys_renameat2
|
||||
348 common seccomp sys_seccomp compat_sys_seccomp
|
||||
349 common getrandom sys_getrandom compat_sys_getrandom
|
||||
350 common memfd_create sys_memfd_create compat_sys_memfd_create
|
||||
351 common bpf sys_bpf compat_sys_bpf
|
||||
352 common s390_pci_mmio_write sys_s390_pci_mmio_write compat_sys_s390_pci_mmio_write
|
||||
353 common s390_pci_mmio_read sys_s390_pci_mmio_read compat_sys_s390_pci_mmio_read
|
||||
343 common kcmp sys_kcmp sys_kcmp
|
||||
344 common finit_module sys_finit_module sys_finit_module
|
||||
345 common sched_setattr sys_sched_setattr sys_sched_setattr
|
||||
346 common sched_getattr sys_sched_getattr sys_sched_getattr
|
||||
347 common renameat2 sys_renameat2 sys_renameat2
|
||||
348 common seccomp sys_seccomp sys_seccomp
|
||||
349 common getrandom sys_getrandom sys_getrandom
|
||||
350 common memfd_create sys_memfd_create sys_memfd_create
|
||||
351 common bpf sys_bpf sys_bpf
|
||||
352 common s390_pci_mmio_write sys_s390_pci_mmio_write sys_s390_pci_mmio_write
|
||||
353 common s390_pci_mmio_read sys_s390_pci_mmio_read sys_s390_pci_mmio_read
|
||||
354 common execveat sys_execveat compat_sys_execveat
|
||||
355 common userfaultfd sys_userfaultfd sys_userfaultfd
|
||||
356 common membarrier sys_membarrier sys_membarrier
|
||||
357 common recvmmsg sys_recvmmsg compat_sys_recvmmsg
|
||||
358 common sendmmsg sys_sendmmsg compat_sys_sendmmsg
|
||||
359 common socket sys_socket sys_socket
|
||||
360 common socketpair sys_socketpair compat_sys_socketpair
|
||||
361 common bind sys_bind compat_sys_bind
|
||||
362 common connect sys_connect compat_sys_connect
|
||||
360 common socketpair sys_socketpair sys_socketpair
|
||||
361 common bind sys_bind sys_bind
|
||||
362 common connect sys_connect sys_connect
|
||||
363 common listen sys_listen sys_listen
|
||||
364 common accept4 sys_accept4 compat_sys_accept4
|
||||
364 common accept4 sys_accept4 sys_accept4
|
||||
365 common getsockopt sys_getsockopt compat_sys_getsockopt
|
||||
366 common setsockopt sys_setsockopt compat_sys_setsockopt
|
||||
367 common getsockname sys_getsockname compat_sys_getsockname
|
||||
368 common getpeername sys_getpeername compat_sys_getpeername
|
||||
369 common sendto sys_sendto compat_sys_sendto
|
||||
367 common getsockname sys_getsockname sys_getsockname
|
||||
368 common getpeername sys_getpeername sys_getpeername
|
||||
369 common sendto sys_sendto sys_sendto
|
||||
370 common sendmsg sys_sendmsg compat_sys_sendmsg
|
||||
371 common recvfrom sys_recvfrom compat_sys_recvfrom
|
||||
372 common recvmsg sys_recvmsg compat_sys_recvmsg
|
||||
373 common shutdown sys_shutdown sys_shutdown
|
||||
374 common mlock2 sys_mlock2 compat_sys_mlock2
|
||||
375 common copy_file_range sys_copy_file_range compat_sys_copy_file_range
|
||||
374 common mlock2 sys_mlock2 sys_mlock2
|
||||
375 common copy_file_range sys_copy_file_range sys_copy_file_range
|
||||
376 common preadv2 sys_preadv2 compat_sys_preadv2
|
||||
377 common pwritev2 sys_pwritev2 compat_sys_pwritev2
|
||||
378 common s390_guarded_storage sys_s390_guarded_storage compat_sys_s390_guarded_storage
|
||||
379 common statx sys_statx compat_sys_statx
|
||||
380 common s390_sthyi sys_s390_sthyi compat_sys_s390_sthyi
|
||||
381 common kexec_file_load sys_kexec_file_load compat_sys_kexec_file_load
|
||||
378 common s390_guarded_storage sys_s390_guarded_storage sys_s390_guarded_storage
|
||||
379 common statx sys_statx sys_statx
|
||||
380 common s390_sthyi sys_s390_sthyi sys_s390_sthyi
|
||||
381 common kexec_file_load sys_kexec_file_load sys_kexec_file_load
|
||||
382 common io_pgetevents sys_io_pgetevents compat_sys_io_pgetevents
|
||||
383 common rseq sys_rseq compat_sys_rseq
|
||||
383 common rseq sys_rseq sys_rseq
|
||||
|
|
|
@ -545,8 +545,6 @@ static __init int stsi_init_debugfs(void)
|
|||
int lvl, i;
|
||||
|
||||
stsi_root = debugfs_create_dir("stsi", arch_debugfs_dir);
|
||||
if (IS_ERR_OR_NULL(stsi_root))
|
||||
return 0;
|
||||
lvl = stsi(NULL, 0, 0, 0);
|
||||
if (lvl > 0)
|
||||
stsi_0_0_0 = lvl;
|
||||
|
|
|
@ -69,7 +69,7 @@ static void update_mt_scaling(void)
|
|||
u64 delta, fac, mult, div;
|
||||
int i;
|
||||
|
||||
stcctm5(smp_cpu_mtid + 1, cycles_new);
|
||||
stcctm(MT_DIAG, smp_cpu_mtid + 1, cycles_new);
|
||||
cycles_old = this_cpu_ptr(mt_cycles);
|
||||
fac = 1;
|
||||
mult = div = 0;
|
||||
|
@ -432,6 +432,6 @@ void vtime_init(void)
|
|||
__this_cpu_write(mt_scaling_jiffies, jiffies);
|
||||
__this_cpu_write(mt_scaling_mult, 1);
|
||||
__this_cpu_write(mt_scaling_div, 1);
|
||||
stcctm5(smp_cpu_mtid + 1, this_cpu_ptr(mt_cycles));
|
||||
stcctm(MT_DIAG, smp_cpu_mtid + 1, this_cpu_ptr(mt_cycles));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,11 +43,13 @@ static inline char *__strnend(const char *s, size_t n)
|
|||
*
|
||||
* returns the length of @s
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRLEN
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
return __strend(s) - s;
|
||||
}
|
||||
EXPORT_SYMBOL(strlen);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strnlen - Find the length of a length-limited string
|
||||
|
@ -56,11 +58,13 @@ EXPORT_SYMBOL(strlen);
|
|||
*
|
||||
* returns the minimum of the length of @s and @n
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRNLEN
|
||||
size_t strnlen(const char *s, size_t n)
|
||||
{
|
||||
return __strnend(s, n) - s;
|
||||
}
|
||||
EXPORT_SYMBOL(strnlen);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strcpy - Copy a %NUL terminated string
|
||||
|
@ -69,6 +73,7 @@ EXPORT_SYMBOL(strnlen);
|
|||
*
|
||||
* returns a pointer to @dest
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRCPY
|
||||
char *strcpy(char *dest, const char *src)
|
||||
{
|
||||
register int r0 asm("0") = 0;
|
||||
|
@ -81,6 +86,7 @@ char *strcpy(char *dest, const char *src)
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(strcpy);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strlcpy - Copy a %NUL terminated string into a sized buffer
|
||||
|
@ -93,6 +99,7 @@ EXPORT_SYMBOL(strcpy);
|
|||
* of course, the buffer size is zero). It does not pad
|
||||
* out the result like strncpy() does.
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRLCPY
|
||||
size_t strlcpy(char *dest, const char *src, size_t size)
|
||||
{
|
||||
size_t ret = __strend(src) - src;
|
||||
|
@ -105,6 +112,7 @@ size_t strlcpy(char *dest, const char *src, size_t size)
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(strlcpy);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strncpy - Copy a length-limited, %NUL-terminated string
|
||||
|
@ -115,6 +123,7 @@ EXPORT_SYMBOL(strlcpy);
|
|||
* The result is not %NUL-terminated if the source exceeds
|
||||
* @n bytes.
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRNCPY
|
||||
char *strncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
size_t len = __strnend(src, n) - src;
|
||||
|
@ -123,6 +132,7 @@ char *strncpy(char *dest, const char *src, size_t n)
|
|||
return dest;
|
||||
}
|
||||
EXPORT_SYMBOL(strncpy);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strcat - Append one %NUL-terminated string to another
|
||||
|
@ -131,6 +141,7 @@ EXPORT_SYMBOL(strncpy);
|
|||
*
|
||||
* returns a pointer to @dest
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRCAT
|
||||
char *strcat(char *dest, const char *src)
|
||||
{
|
||||
register int r0 asm("0") = 0;
|
||||
|
@ -146,6 +157,7 @@ char *strcat(char *dest, const char *src)
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(strcat);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strlcat - Append a length-limited, %NUL-terminated string to another
|
||||
|
@ -153,6 +165,7 @@ EXPORT_SYMBOL(strcat);
|
|||
* @src: The string to append to it
|
||||
* @n: The size of the destination buffer.
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRLCAT
|
||||
size_t strlcat(char *dest, const char *src, size_t n)
|
||||
{
|
||||
size_t dsize = __strend(dest) - dest;
|
||||
|
@ -170,6 +183,7 @@ size_t strlcat(char *dest, const char *src, size_t n)
|
|||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(strlcat);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strncat - Append a length-limited, %NUL-terminated string to another
|
||||
|
@ -182,6 +196,7 @@ EXPORT_SYMBOL(strlcat);
|
|||
* Note that in contrast to strncpy, strncat ensures the result is
|
||||
* terminated.
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRNCAT
|
||||
char *strncat(char *dest, const char *src, size_t n)
|
||||
{
|
||||
size_t len = __strnend(src, n) - src;
|
||||
|
@ -192,6 +207,7 @@ char *strncat(char *dest, const char *src, size_t n)
|
|||
return dest;
|
||||
}
|
||||
EXPORT_SYMBOL(strncat);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strcmp - Compare two strings
|
||||
|
@ -202,6 +218,7 @@ EXPORT_SYMBOL(strncat);
|
|||
* < 0 if @s1 is less than @s2
|
||||
* > 0 if @s1 is greater than @s2
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRCMP
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
register int r0 asm("0") = 0;
|
||||
|
@ -219,12 +236,14 @@ int strcmp(const char *s1, const char *s2)
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(strcmp);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* strrchr - Find the last occurrence of a character in a string
|
||||
* @s: The string to be searched
|
||||
* @c: The character to search for
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRRCHR
|
||||
char *strrchr(const char *s, int c)
|
||||
{
|
||||
size_t len = __strend(s) - s;
|
||||
|
@ -237,6 +256,7 @@ char *strrchr(const char *s, int c)
|
|||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(strrchr);
|
||||
#endif
|
||||
|
||||
static inline int clcle(const char *s1, unsigned long l1,
|
||||
const char *s2, unsigned long l2)
|
||||
|
@ -261,6 +281,7 @@ static inline int clcle(const char *s1, unsigned long l1,
|
|||
* @s1: The string to be searched
|
||||
* @s2: The string to search for
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_STRSTR
|
||||
char *strstr(const char *s1, const char *s2)
|
||||
{
|
||||
int l1, l2;
|
||||
|
@ -280,6 +301,7 @@ char *strstr(const char *s1, const char *s2)
|
|||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(strstr);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* memchr - Find a character in an area of memory.
|
||||
|
@ -290,6 +312,7 @@ EXPORT_SYMBOL(strstr);
|
|||
* returns the address of the first occurrence of @c, or %NULL
|
||||
* if @c is not found
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_MEMCHR
|
||||
void *memchr(const void *s, int c, size_t n)
|
||||
{
|
||||
register int r0 asm("0") = (char) c;
|
||||
|
@ -304,6 +327,7 @@ void *memchr(const void *s, int c, size_t n)
|
|||
return (void *) ret;
|
||||
}
|
||||
EXPORT_SYMBOL(memchr);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* memcmp - Compare two areas of memory
|
||||
|
@ -311,6 +335,7 @@ EXPORT_SYMBOL(memchr);
|
|||
* @s2: Another area of memory
|
||||
* @count: The size of the area.
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_MEMCMP
|
||||
int memcmp(const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
int ret;
|
||||
|
@ -321,6 +346,7 @@ int memcmp(const void *s1, const void *s2, size_t n)
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(memcmp);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* memscan - Find a character in an area of memory.
|
||||
|
@ -331,6 +357,7 @@ EXPORT_SYMBOL(memcmp);
|
|||
* returns the address of the first occurrence of @c, or 1 byte past
|
||||
* the area if @c is not found
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_MEMSCAN
|
||||
void *memscan(void *s, int c, size_t n)
|
||||
{
|
||||
register int r0 asm("0") = (char) c;
|
||||
|
@ -342,3 +369,4 @@ void *memscan(void *s, int c, size_t n)
|
|||
return (void *) ret;
|
||||
}
|
||||
EXPORT_SYMBOL(memscan);
|
||||
#endif
|
||||
|
|
|
@ -28,12 +28,7 @@
|
|||
#include <asm/cpcmd.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#define DCSS_LOADSHR 0x00
|
||||
#define DCSS_LOADNSR 0x04
|
||||
#define DCSS_PURGESEG 0x08
|
||||
#define DCSS_FINDSEG 0x0c
|
||||
#define DCSS_LOADNOLY 0x10
|
||||
#define DCSS_SEGEXT 0x18
|
||||
#define DCSS_LOADSHRX 0x20
|
||||
#define DCSS_LOADNSRX 0x24
|
||||
#define DCSS_FINDSEGX 0x2c
|
||||
|
@ -53,20 +48,6 @@ struct qout64 {
|
|||
struct qrange range[6];
|
||||
};
|
||||
|
||||
struct qrange_old {
|
||||
unsigned int start; /* last byte type */
|
||||
unsigned int end; /* last byte reserved */
|
||||
};
|
||||
|
||||
/* output area format for the Diag x'64' old subcode x'18' */
|
||||
struct qout64_old {
|
||||
int segstart;
|
||||
int segend;
|
||||
int segcnt;
|
||||
int segrcnt;
|
||||
struct qrange_old range[6];
|
||||
};
|
||||
|
||||
struct qin64 {
|
||||
char qopcode;
|
||||
char rsrv1[3];
|
||||
|
@ -95,52 +76,10 @@ static DEFINE_MUTEX(dcss_lock);
|
|||
static LIST_HEAD(dcss_list);
|
||||
static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC",
|
||||
"EW/EN-MIXED" };
|
||||
static int loadshr_scode, loadnsr_scode;
|
||||
static int segext_scode, purgeseg_scode;
|
||||
static int scode_set;
|
||||
|
||||
/* set correct Diag x'64' subcodes. */
|
||||
static int
|
||||
dcss_set_subcodes(void)
|
||||
{
|
||||
char *name = kmalloc(8, GFP_KERNEL | GFP_DMA);
|
||||
unsigned long rx, ry;
|
||||
int rc;
|
||||
|
||||
if (name == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rx = (unsigned long) name;
|
||||
ry = DCSS_FINDSEGX;
|
||||
|
||||
strcpy(name, "dummy");
|
||||
diag_stat_inc(DIAG_STAT_X064);
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
"0: ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
" j 2f\n"
|
||||
"1: la %2,3\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b, 1b)
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc", "memory");
|
||||
|
||||
kfree(name);
|
||||
/* Diag x'64' new subcodes are supported, set to new subcodes */
|
||||
if (rc != 3) {
|
||||
loadshr_scode = DCSS_LOADSHRX;
|
||||
loadnsr_scode = DCSS_LOADNSRX;
|
||||
purgeseg_scode = DCSS_PURGESEG;
|
||||
segext_scode = DCSS_SEGEXTX;
|
||||
return 0;
|
||||
}
|
||||
/* Diag x'64' new subcodes are not supported, set to old subcodes */
|
||||
loadshr_scode = DCSS_LOADNOLY;
|
||||
loadnsr_scode = DCSS_LOADNSR;
|
||||
purgeseg_scode = DCSS_PURGESEG;
|
||||
segext_scode = DCSS_SEGEXT;
|
||||
return 0;
|
||||
}
|
||||
static int loadshr_scode = DCSS_LOADSHRX;
|
||||
static int loadnsr_scode = DCSS_LOADNSRX;
|
||||
static int purgeseg_scode = DCSS_PURGESEG;
|
||||
static int segext_scode = DCSS_SEGEXTX;
|
||||
|
||||
/*
|
||||
* Create the 8 bytes, ebcdic VM segment name from
|
||||
|
@ -196,32 +135,15 @@ dcss_diag(int *func, void *parameter,
|
|||
unsigned long rx, ry;
|
||||
int rc;
|
||||
|
||||
if (scode_set == 0) {
|
||||
rc = dcss_set_subcodes();
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
scode_set = 1;
|
||||
}
|
||||
rx = (unsigned long) parameter;
|
||||
ry = (unsigned long) *func;
|
||||
|
||||
/* 64-bit Diag x'64' new subcode, keep in 64-bit addressing mode */
|
||||
diag_stat_inc(DIAG_STAT_X064);
|
||||
if (*func > DCSS_SEGEXT)
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
/* 31-bit Diag x'64' old subcode, switch to 31-bit addressing mode */
|
||||
else
|
||||
asm volatile(
|
||||
" sam31\n"
|
||||
" diag %0,%1,0x64\n"
|
||||
" sam64\n"
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
asm volatile(
|
||||
" diag %0,%1,0x64\n"
|
||||
" ipm %2\n"
|
||||
" srl %2,28\n"
|
||||
: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
|
||||
*ret1 = rx;
|
||||
*ret2 = ry;
|
||||
return rc;
|
||||
|
@ -271,31 +193,6 @@ query_segment_type (struct dcss_segment *seg)
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
/* Only old format of output area of Diagnose x'64' is supported,
|
||||
copy data for the new format. */
|
||||
if (segext_scode == DCSS_SEGEXT) {
|
||||
struct qout64_old *qout_old;
|
||||
qout_old = kzalloc(sizeof(*qout_old), GFP_KERNEL | GFP_DMA);
|
||||
if (qout_old == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
memcpy(qout_old, qout, sizeof(struct qout64_old));
|
||||
qout->segstart = (unsigned long) qout_old->segstart;
|
||||
qout->segend = (unsigned long) qout_old->segend;
|
||||
qout->segcnt = qout_old->segcnt;
|
||||
qout->segrcnt = qout_old->segrcnt;
|
||||
|
||||
if (qout->segcnt > 6)
|
||||
qout->segrcnt = 6;
|
||||
for (i = 0; i < qout->segrcnt; i++) {
|
||||
qout->range[i].start =
|
||||
(unsigned long) qout_old->range[i].start;
|
||||
qout->range[i].end =
|
||||
(unsigned long) qout_old->range[i].end;
|
||||
}
|
||||
kfree(qout_old);
|
||||
}
|
||||
if (qout->segcnt > 6) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out_free;
|
||||
|
@ -410,11 +307,9 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
|
|||
if (rc < 0)
|
||||
goto out_free;
|
||||
|
||||
if (loadshr_scode == DCSS_LOADSHRX) {
|
||||
if (segment_overlaps_others(seg)) {
|
||||
rc = -EBUSY;
|
||||
goto out_free;
|
||||
}
|
||||
if (segment_overlaps_others(seg)) {
|
||||
rc = -EBUSY;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
rc = vmem_add_mapping(seg->start_addr, seg->end - seg->start_addr + 1);
|
||||
|
@ -472,11 +367,11 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
|
|||
*addr = seg->start_addr;
|
||||
*end = seg->end;
|
||||
if (do_nonshared)
|
||||
pr_info("DCSS %s of range %p to %p and type %s loaded as "
|
||||
pr_info("DCSS %s of range %px to %px and type %s loaded as "
|
||||
"exclusive-writable\n", name, (void*) seg->start_addr,
|
||||
(void*) seg->end, segtype_string[seg->vm_segtype]);
|
||||
else {
|
||||
pr_info("DCSS %s of range %p to %p and type %s loaded in "
|
||||
pr_info("DCSS %s of range %px to %px and type %s loaded in "
|
||||
"shared access mode\n", name, (void*) seg->start_addr,
|
||||
(void*) seg->end, segtype_string[seg->vm_segtype]);
|
||||
}
|
||||
|
|
|
@ -226,8 +226,6 @@ static void __init kasan_enable_dat(void)
|
|||
|
||||
static void __init kasan_early_detect_facilities(void)
|
||||
{
|
||||
__stfle(S390_lowcore.stfle_fac_list,
|
||||
ARRAY_SIZE(S390_lowcore.stfle_fac_list));
|
||||
if (test_facility(8)) {
|
||||
has_edat = true;
|
||||
__ctl_set_bit(0, 23);
|
||||
|
|
|
@ -29,14 +29,6 @@ static unsigned long stack_maxrandom_size(void)
|
|||
return STACK_RND_MASK << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Top of mmap area (just below the process stack).
|
||||
*
|
||||
* Leave at least a ~32 MB hole.
|
||||
*/
|
||||
#define MIN_GAP (32*1024*1024)
|
||||
#define MAX_GAP (STACK_TOP/6*5)
|
||||
|
||||
static inline int mmap_is_legacy(struct rlimit *rlim_stack)
|
||||
{
|
||||
if (current->personality & ADDR_COMPAT_LAYOUT)
|
||||
|
@ -60,13 +52,26 @@ static inline unsigned long mmap_base(unsigned long rnd,
|
|||
struct rlimit *rlim_stack)
|
||||
{
|
||||
unsigned long gap = rlim_stack->rlim_cur;
|
||||
unsigned long pad = stack_maxrandom_size() + stack_guard_gap;
|
||||
unsigned long gap_min, gap_max;
|
||||
|
||||
if (gap < MIN_GAP)
|
||||
gap = MIN_GAP;
|
||||
else if (gap > MAX_GAP)
|
||||
gap = MAX_GAP;
|
||||
gap &= PAGE_MASK;
|
||||
return STACK_TOP - stack_maxrandom_size() - rnd - gap;
|
||||
/* Values close to RLIM_INFINITY can overflow. */
|
||||
if (gap + pad > gap)
|
||||
gap += pad;
|
||||
|
||||
/*
|
||||
* Top of mmap area (just below the process stack).
|
||||
* Leave at least a ~32 MB hole.
|
||||
*/
|
||||
gap_min = 32 * 1024 * 1024UL;
|
||||
gap_max = (STACK_TOP / 6) * 5;
|
||||
|
||||
if (gap < gap_min)
|
||||
gap = gap_min;
|
||||
else if (gap > gap_max)
|
||||
gap = gap_max;
|
||||
|
||||
return PAGE_ALIGN(STACK_TOP - gap - rnd);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
|
|
|
@ -318,7 +318,6 @@ pte_t ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr,
|
|||
}
|
||||
return old;
|
||||
}
|
||||
EXPORT_SYMBOL(ptep_modify_prot_start);
|
||||
|
||||
void ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte)
|
||||
|
@ -337,7 +336,6 @@ void ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
|
|||
}
|
||||
preempt_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(ptep_modify_prot_commit);
|
||||
|
||||
static inline void pmdp_idte_local(struct mm_struct *mm,
|
||||
unsigned long addr, pmd_t *pmdp)
|
||||
|
|
|
@ -285,7 +285,7 @@ void __iomem *pci_iomap_range(struct pci_dev *pdev,
|
|||
struct zpci_dev *zdev = to_zpci(pdev);
|
||||
int idx;
|
||||
|
||||
if (!pci_resource_len(pdev, bar))
|
||||
if (!pci_resource_len(pdev, bar) || bar >= PCI_BAR_COUNT)
|
||||
return NULL;
|
||||
|
||||
idx = zdev->bars[bar].map_idx;
|
||||
|
@ -484,6 +484,15 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static struct resource iov_res = {
|
||||
.name = "PCI IOV res",
|
||||
.start = 0,
|
||||
.end = -1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void zpci_map_resources(struct pci_dev *pdev)
|
||||
{
|
||||
resource_size_t len;
|
||||
|
@ -497,6 +506,17 @@ static void zpci_map_resources(struct pci_dev *pdev)
|
|||
(resource_size_t __force) pci_iomap(pdev, i, 0);
|
||||
pdev->resource[i].end = pdev->resource[i].start + len - 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
i = PCI_IOV_RESOURCES;
|
||||
|
||||
for (; i < PCI_SRIOV_NUM_BARS + PCI_IOV_RESOURCES; i++) {
|
||||
len = pci_resource_len(pdev, i);
|
||||
if (!len)
|
||||
continue;
|
||||
pdev->resource[i].parent = &iov_res;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void zpci_unmap_resources(struct pci_dev *pdev)
|
||||
|
|
|
@ -172,21 +172,14 @@ static const struct file_operations debugfs_pci_perf_fops = {
|
|||
void zpci_debug_init_device(struct zpci_dev *zdev, const char *name)
|
||||
{
|
||||
zdev->debugfs_dev = debugfs_create_dir(name, debugfs_root);
|
||||
if (IS_ERR(zdev->debugfs_dev))
|
||||
zdev->debugfs_dev = NULL;
|
||||
|
||||
zdev->debugfs_perf = debugfs_create_file("statistics",
|
||||
S_IFREG | S_IRUGO | S_IWUSR,
|
||||
zdev->debugfs_dev, zdev,
|
||||
&debugfs_pci_perf_fops);
|
||||
if (IS_ERR(zdev->debugfs_perf))
|
||||
zdev->debugfs_perf = NULL;
|
||||
debugfs_create_file("statistics", S_IFREG | S_IRUGO | S_IWUSR,
|
||||
zdev->debugfs_dev, zdev, &debugfs_pci_perf_fops);
|
||||
}
|
||||
|
||||
void zpci_debug_exit_device(struct zpci_dev *zdev)
|
||||
{
|
||||
debugfs_remove(zdev->debugfs_perf);
|
||||
debugfs_remove(zdev->debugfs_dev);
|
||||
debugfs_remove_recursive(zdev->debugfs_dev);
|
||||
}
|
||||
|
||||
int __init zpci_debug_init(void)
|
||||
|
|
|
@ -3965,13 +3965,11 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
|
|||
EXPORT_SYMBOL_GPL(dasd_generic_restore_device);
|
||||
|
||||
static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
|
||||
void *rdc_buffer,
|
||||
int rdc_buffer_size,
|
||||
int magic)
|
||||
{
|
||||
struct dasd_ccw_req *cqr;
|
||||
struct ccw1 *ccw;
|
||||
unsigned long *idaw;
|
||||
|
||||
cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device,
|
||||
NULL);
|
||||
|
@ -3986,16 +3984,8 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
|
|||
|
||||
ccw = cqr->cpaddr;
|
||||
ccw->cmd_code = CCW_CMD_RDC;
|
||||
if (idal_is_needed(rdc_buffer, rdc_buffer_size)) {
|
||||
idaw = (unsigned long *) (cqr->data);
|
||||
ccw->cda = (__u32)(addr_t) idaw;
|
||||
ccw->flags = CCW_FLAG_IDA;
|
||||
idaw = idal_create_words(idaw, rdc_buffer, rdc_buffer_size);
|
||||
} else {
|
||||
ccw->cda = (__u32)(addr_t) rdc_buffer;
|
||||
ccw->flags = 0;
|
||||
}
|
||||
|
||||
ccw->cda = (__u32)(addr_t) cqr->data;
|
||||
ccw->flags = 0;
|
||||
ccw->count = rdc_buffer_size;
|
||||
cqr->startdev = device;
|
||||
cqr->memdev = device;
|
||||
|
@ -4013,12 +4003,13 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, int magic,
|
|||
int ret;
|
||||
struct dasd_ccw_req *cqr;
|
||||
|
||||
cqr = dasd_generic_build_rdc(device, rdc_buffer, rdc_buffer_size,
|
||||
magic);
|
||||
cqr = dasd_generic_build_rdc(device, rdc_buffer_size, magic);
|
||||
if (IS_ERR(cqr))
|
||||
return PTR_ERR(cqr);
|
||||
|
||||
ret = dasd_sleep_on(cqr);
|
||||
if (ret == 0)
|
||||
memcpy(rdc_buffer, cqr->data, rdc_buffer_size);
|
||||
dasd_sfree_request(cqr, cqr->memdev);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -195,7 +195,9 @@ struct read_info_sccb {
|
|||
u16 hcpua; /* 120-121 */
|
||||
u8 _pad_122[124 - 122]; /* 122-123 */
|
||||
u32 hmfai; /* 124-127 */
|
||||
u8 _pad_128[4096 - 128]; /* 128-4095 */
|
||||
u8 _pad_128[134 - 128]; /* 128-133 */
|
||||
u8 byte_134; /* 134 */
|
||||
u8 _pad_135[4096 - 135]; /* 135-4095 */
|
||||
} __packed __aligned(PAGE_SIZE);
|
||||
|
||||
struct read_storage_sccb {
|
||||
|
|
|
@ -44,6 +44,8 @@ static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
|
|||
S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
|
||||
if (sccb->fac91 & 0x40)
|
||||
S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST;
|
||||
if (sccb->cpuoff > 134)
|
||||
sclp.has_diag318 = !!(sccb->byte_134 & 0x80);
|
||||
sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
|
||||
sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
|
||||
sclp.rzm <<= 20;
|
||||
|
|
|
@ -181,7 +181,7 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr,
|
|||
}
|
||||
|
||||
static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
|
||||
void **sbals_array, int i)
|
||||
struct qdio_buffer **sbals_array, int i)
|
||||
{
|
||||
struct qdio_q *prev;
|
||||
int j;
|
||||
|
@ -212,8 +212,8 @@ static void setup_queues(struct qdio_irq *irq_ptr,
|
|||
struct qdio_initialize *qdio_init)
|
||||
{
|
||||
struct qdio_q *q;
|
||||
void **input_sbal_array = qdio_init->input_sbal_addr_array;
|
||||
void **output_sbal_array = qdio_init->output_sbal_addr_array;
|
||||
struct qdio_buffer **input_sbal_array = qdio_init->input_sbal_addr_array;
|
||||
struct qdio_buffer **output_sbal_array = qdio_init->output_sbal_addr_array;
|
||||
struct qdio_outbuf_state *output_sbal_state_array =
|
||||
qdio_init->output_sbal_state_array;
|
||||
int i;
|
||||
|
|
|
@ -283,6 +283,33 @@ static long copy_ccw_from_iova(struct channel_program *cp,
|
|||
|
||||
#define ccw_is_chain(_ccw) ((_ccw)->flags & (CCW_FLAG_CC | CCW_FLAG_DC))
|
||||
|
||||
/*
|
||||
* is_cpa_within_range()
|
||||
*
|
||||
* @cpa: channel program address being questioned
|
||||
* @head: address of the beginning of a CCW chain
|
||||
* @len: number of CCWs within the chain
|
||||
*
|
||||
* Determine whether the address of a CCW (whether a new chain,
|
||||
* or the target of a TIC) falls within a range (including the end points).
|
||||
*
|
||||
* Returns 1 if yes, 0 if no.
|
||||
*/
|
||||
static inline int is_cpa_within_range(u32 cpa, u32 head, int len)
|
||||
{
|
||||
u32 tail = head + (len - 1) * sizeof(struct ccw1);
|
||||
|
||||
return (head <= cpa && cpa <= tail);
|
||||
}
|
||||
|
||||
static inline int is_tic_within_range(struct ccw1 *ccw, u32 head, int len)
|
||||
{
|
||||
if (!ccw_is_tic(ccw))
|
||||
return 0;
|
||||
|
||||
return is_cpa_within_range(ccw->cda, head, len);
|
||||
}
|
||||
|
||||
static struct ccwchain *ccwchain_alloc(struct channel_program *cp, int len)
|
||||
{
|
||||
struct ccwchain *chain;
|
||||
|
@ -392,7 +419,15 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if ((!ccw_is_chain(ccw)) && (!ccw_is_tic(ccw)))
|
||||
/*
|
||||
* We want to keep counting if the current CCW has the
|
||||
* command-chaining flag enabled, or if it is a TIC CCW
|
||||
* that loops back into the current chain. The latter
|
||||
* is used for device orientation, where the CCW PRIOR to
|
||||
* the TIC can either jump to the TIC or a CCW immediately
|
||||
* after the TIC, depending on the results of its operation.
|
||||
*/
|
||||
if (!ccw_is_chain(ccw) && !is_tic_within_range(ccw, iova, cnt))
|
||||
break;
|
||||
|
||||
ccw++;
|
||||
|
@ -408,13 +443,11 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
|
|||
static int tic_target_chain_exists(struct ccw1 *tic, struct channel_program *cp)
|
||||
{
|
||||
struct ccwchain *chain;
|
||||
u32 ccw_head, ccw_tail;
|
||||
u32 ccw_head;
|
||||
|
||||
list_for_each_entry(chain, &cp->ccwchain_list, next) {
|
||||
ccw_head = chain->ch_iova;
|
||||
ccw_tail = ccw_head + (chain->ch_len - 1) * sizeof(struct ccw1);
|
||||
|
||||
if ((ccw_head <= tic->cda) && (tic->cda <= ccw_tail))
|
||||
if (is_cpa_within_range(tic->cda, ccw_head, chain->ch_len))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -481,13 +514,11 @@ static int ccwchain_fetch_tic(struct ccwchain *chain,
|
|||
{
|
||||
struct ccw1 *ccw = chain->ch_ccw + idx;
|
||||
struct ccwchain *iter;
|
||||
u32 ccw_head, ccw_tail;
|
||||
u32 ccw_head;
|
||||
|
||||
list_for_each_entry(iter, &cp->ccwchain_list, next) {
|
||||
ccw_head = iter->ch_iova;
|
||||
ccw_tail = ccw_head + (iter->ch_len - 1) * sizeof(struct ccw1);
|
||||
|
||||
if ((ccw_head <= ccw->cda) && (ccw->cda <= ccw_tail)) {
|
||||
if (is_cpa_within_range(ccw->cda, ccw_head, iter->ch_len)) {
|
||||
ccw->cda = (__u32) (addr_t) (((char *)iter->ch_ccw) +
|
||||
(ccw->cda - ccw_head));
|
||||
return 0;
|
||||
|
@ -829,7 +860,7 @@ void cp_update_scsw(struct channel_program *cp, union scsw *scsw)
|
|||
{
|
||||
struct ccwchain *chain;
|
||||
u32 cpa = scsw->cmd.cpa;
|
||||
u32 ccw_head, ccw_tail;
|
||||
u32 ccw_head;
|
||||
|
||||
/*
|
||||
* LATER:
|
||||
|
@ -839,9 +870,7 @@ void cp_update_scsw(struct channel_program *cp, union scsw *scsw)
|
|||
*/
|
||||
list_for_each_entry(chain, &cp->ccwchain_list, next) {
|
||||
ccw_head = (u32)(u64)chain->ch_ccw;
|
||||
ccw_tail = (u32)(u64)(chain->ch_ccw + chain->ch_len - 1);
|
||||
|
||||
if ((ccw_head <= cpa) && (cpa <= ccw_tail)) {
|
||||
if (is_cpa_within_range(cpa, ccw_head, chain->ch_len)) {
|
||||
/*
|
||||
* (cpa - ccw_head) is the offset value of the host
|
||||
* physical ccw to its chain head.
|
||||
|
|
|
@ -1335,6 +1335,16 @@ static int __match_queue_device_with_qid(struct device *dev, void *data)
|
|||
return is_queue_dev(dev) && to_ap_queue(dev)->qid == (int)(long) data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to be used with bus_find_dev
|
||||
* matches any queue device with given queue id
|
||||
*/
|
||||
static int __match_queue_device_with_queue_id(struct device *dev, void *data)
|
||||
{
|
||||
return is_queue_dev(dev)
|
||||
&& AP_QID_QUEUE(to_ap_queue(dev)->qid) == (int)(long) data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for ap_scan_bus().
|
||||
* Does the scan bus job for the given adapter id.
|
||||
|
@ -1435,8 +1445,13 @@ static void _ap_scan_bus_adapter(int id)
|
|||
borked = aq->state == AP_STATE_BORKED;
|
||||
spin_unlock_bh(&aq->lock);
|
||||
}
|
||||
if (borked) /* Remove broken device */
|
||||
if (borked) {
|
||||
/* Remove broken device */
|
||||
AP_DBF(DBF_DEBUG,
|
||||
"removing broken queue=%02x.%04x\n",
|
||||
id, dom);
|
||||
device_unregister(dev);
|
||||
}
|
||||
put_device(dev);
|
||||
continue;
|
||||
}
|
||||
|
@ -1506,7 +1521,7 @@ static void ap_scan_bus(struct work_struct *unused)
|
|||
struct device *dev =
|
||||
bus_find_device(&ap_bus_type, NULL,
|
||||
(void *)(long) ap_domain_index,
|
||||
__match_queue_device_with_qid);
|
||||
__match_queue_device_with_queue_id);
|
||||
if (dev)
|
||||
put_device(dev);
|
||||
else
|
||||
|
|
|
@ -91,7 +91,8 @@ enum ap_state {
|
|||
AP_STATE_WORKING,
|
||||
AP_STATE_QUEUE_FULL,
|
||||
AP_STATE_SUSPEND_WAIT,
|
||||
AP_STATE_BORKED,
|
||||
AP_STATE_UNBOUND, /* momentary not bound to a driver */
|
||||
AP_STATE_BORKED, /* broken */
|
||||
NR_AP_STATES
|
||||
};
|
||||
|
||||
|
|
|
@ -420,6 +420,10 @@ static ap_func_t *ap_jumptable[NR_AP_STATES][NR_AP_EVENTS] = {
|
|||
[AP_EVENT_POLL] = ap_sm_suspend_read,
|
||||
[AP_EVENT_TIMEOUT] = ap_sm_nop,
|
||||
},
|
||||
[AP_STATE_UNBOUND] = {
|
||||
[AP_EVENT_POLL] = ap_sm_nop,
|
||||
[AP_EVENT_TIMEOUT] = ap_sm_nop,
|
||||
},
|
||||
[AP_STATE_BORKED] = {
|
||||
[AP_EVENT_POLL] = ap_sm_nop,
|
||||
[AP_EVENT_TIMEOUT] = ap_sm_nop,
|
||||
|
@ -725,6 +729,7 @@ static void __ap_flush_queue(struct ap_queue *aq)
|
|||
ap_msg->rc = -EAGAIN;
|
||||
ap_msg->receive(aq, ap_msg, NULL);
|
||||
}
|
||||
aq->queue_count = 0;
|
||||
}
|
||||
|
||||
void ap_flush_queue(struct ap_queue *aq)
|
||||
|
@ -743,7 +748,7 @@ void ap_queue_remove(struct ap_queue *aq)
|
|||
/* reset with zero, also clears irq registration */
|
||||
spin_lock_bh(&aq->lock);
|
||||
ap_zapq(aq->qid);
|
||||
aq->state = AP_STATE_BORKED;
|
||||
aq->state = AP_STATE_UNBOUND;
|
||||
spin_unlock_bh(&aq->lock);
|
||||
}
|
||||
EXPORT_SYMBOL(ap_queue_remove);
|
||||
|
|
|
@ -1079,7 +1079,7 @@ int pkey_verifykey(const struct pkey_seckey *seckey,
|
|||
rc = mkvp_cache_fetch(cardnr, domain, mkvp);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (t->mkvp == mkvp[1]) {
|
||||
if (t->mkvp == mkvp[1] && t->mkvp != mkvp[0]) {
|
||||
DEBUG_DBG("%s secure key has old mkvp\n", __func__);
|
||||
if (pattributes)
|
||||
*pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "vfio_ap_private.h"
|
||||
|
||||
#define VFIO_AP_ROOT_NAME "vfio_ap"
|
||||
#define VFIO_AP_DEV_TYPE_NAME "ap_matrix"
|
||||
#define VFIO_AP_DEV_NAME "matrix"
|
||||
|
||||
MODULE_AUTHOR("IBM Corporation");
|
||||
|
@ -24,10 +23,6 @@ MODULE_LICENSE("GPL v2");
|
|||
|
||||
static struct ap_driver vfio_ap_drv;
|
||||
|
||||
static struct device_type vfio_ap_dev_type = {
|
||||
.name = VFIO_AP_DEV_TYPE_NAME,
|
||||
};
|
||||
|
||||
struct ap_matrix_dev *matrix_dev;
|
||||
|
||||
/* Only type 10 adapters (CEX4 and later) are supported
|
||||
|
@ -62,6 +57,22 @@ static void vfio_ap_matrix_dev_release(struct device *dev)
|
|||
kfree(matrix_dev);
|
||||
}
|
||||
|
||||
static int matrix_bus_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct bus_type matrix_bus = {
|
||||
.name = "matrix",
|
||||
.match = &matrix_bus_match,
|
||||
};
|
||||
|
||||
static struct device_driver matrix_driver = {
|
||||
.name = "vfio_ap",
|
||||
.bus = &matrix_bus,
|
||||
.suppress_bind_attrs = true,
|
||||
};
|
||||
|
||||
static int vfio_ap_matrix_dev_create(void)
|
||||
{
|
||||
int ret;
|
||||
|
@ -71,6 +82,10 @@ static int vfio_ap_matrix_dev_create(void)
|
|||
if (IS_ERR(root_device))
|
||||
return PTR_ERR(root_device);
|
||||
|
||||
ret = bus_register(&matrix_bus);
|
||||
if (ret)
|
||||
goto bus_register_err;
|
||||
|
||||
matrix_dev = kzalloc(sizeof(*matrix_dev), GFP_KERNEL);
|
||||
if (!matrix_dev) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -87,30 +102,41 @@ static int vfio_ap_matrix_dev_create(void)
|
|||
mutex_init(&matrix_dev->lock);
|
||||
INIT_LIST_HEAD(&matrix_dev->mdev_list);
|
||||
|
||||
matrix_dev->device.type = &vfio_ap_dev_type;
|
||||
dev_set_name(&matrix_dev->device, "%s", VFIO_AP_DEV_NAME);
|
||||
matrix_dev->device.parent = root_device;
|
||||
matrix_dev->device.bus = &matrix_bus;
|
||||
matrix_dev->device.release = vfio_ap_matrix_dev_release;
|
||||
matrix_dev->device.driver = &vfio_ap_drv.driver;
|
||||
matrix_dev->vfio_ap_drv = &vfio_ap_drv;
|
||||
|
||||
ret = device_register(&matrix_dev->device);
|
||||
if (ret)
|
||||
goto matrix_reg_err;
|
||||
|
||||
ret = driver_register(&matrix_driver);
|
||||
if (ret)
|
||||
goto matrix_drv_err;
|
||||
|
||||
return 0;
|
||||
|
||||
matrix_drv_err:
|
||||
device_unregister(&matrix_dev->device);
|
||||
matrix_reg_err:
|
||||
put_device(&matrix_dev->device);
|
||||
matrix_alloc_err:
|
||||
bus_unregister(&matrix_bus);
|
||||
bus_register_err:
|
||||
root_device_unregister(root_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vfio_ap_matrix_dev_destroy(void)
|
||||
{
|
||||
struct device *root_device = matrix_dev->device.parent;
|
||||
|
||||
driver_unregister(&matrix_driver);
|
||||
device_unregister(&matrix_dev->device);
|
||||
root_device_unregister(matrix_dev->device.parent);
|
||||
bus_unregister(&matrix_bus);
|
||||
root_device_unregister(root_device);
|
||||
}
|
||||
|
||||
static int __init vfio_ap_init(void)
|
||||
|
|
|
@ -198,8 +198,8 @@ static int vfio_ap_verify_queue_reserved(unsigned long *apid,
|
|||
qres.apqi = apqi;
|
||||
qres.reserved = false;
|
||||
|
||||
ret = driver_for_each_device(matrix_dev->device.driver, NULL, &qres,
|
||||
vfio_ap_has_queue);
|
||||
ret = driver_for_each_device(&matrix_dev->vfio_ap_drv->driver, NULL,
|
||||
&qres, vfio_ap_has_queue);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ struct ap_matrix_dev {
|
|||
struct ap_config_info info;
|
||||
struct list_head mdev_list;
|
||||
struct mutex lock;
|
||||
struct ap_driver *vfio_ap_drv;
|
||||
};
|
||||
|
||||
extern struct ap_matrix_dev *matrix_dev;
|
||||
|
|
|
@ -141,10 +141,13 @@ static int register_ieq(struct ism_dev *ism)
|
|||
|
||||
static int unregister_sba(struct ism_dev *ism)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ism->sba)
|
||||
return 0;
|
||||
|
||||
if (ism_cmd_simple(ism, ISM_UNREG_SBA))
|
||||
ret = ism_cmd_simple(ism, ISM_UNREG_SBA);
|
||||
if (ret && ret != ISM_ERROR)
|
||||
return -EIO;
|
||||
|
||||
dma_free_coherent(&ism->pdev->dev, PAGE_SIZE,
|
||||
|
@ -158,10 +161,13 @@ static int unregister_sba(struct ism_dev *ism)
|
|||
|
||||
static int unregister_ieq(struct ism_dev *ism)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ism->ieq)
|
||||
return 0;
|
||||
|
||||
if (ism_cmd_simple(ism, ISM_UNREG_IEQ))
|
||||
ret = ism_cmd_simple(ism, ISM_UNREG_IEQ);
|
||||
if (ret && ret != ISM_ERROR)
|
||||
return -EIO;
|
||||
|
||||
dma_free_coherent(&ism->pdev->dev, PAGE_SIZE,
|
||||
|
@ -287,7 +293,7 @@ static int ism_unregister_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb)
|
|||
cmd.request.dmb_tok = dmb->dmb_tok;
|
||||
|
||||
ret = ism_cmd(ism, &cmd);
|
||||
if (ret)
|
||||
if (ret && ret != ISM_ERROR)
|
||||
goto out;
|
||||
|
||||
ism_free_dmb(ism, dmb);
|
||||
|
|
|
@ -4884,8 +4884,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
|
|||
init_data.output_handler = qeth_qdio_output_handler;
|
||||
init_data.queue_start_poll_array = queue_start_poll;
|
||||
init_data.int_parm = (unsigned long) card;
|
||||
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
|
||||
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
|
||||
init_data.input_sbal_addr_array = in_sbal_ptrs;
|
||||
init_data.output_sbal_addr_array = out_sbal_ptrs;
|
||||
init_data.output_sbal_state_array = card->qdio.out_bufstates;
|
||||
init_data.scan_threshold =
|
||||
(card->info.type == QETH_CARD_TYPE_IQD) ? 1 : 32;
|
||||
|
|
|
@ -294,8 +294,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
|
|||
id->input_handler = zfcp_qdio_int_resp;
|
||||
id->output_handler = zfcp_qdio_int_req;
|
||||
id->int_parm = (unsigned long) qdio;
|
||||
id->input_sbal_addr_array = (void **) (qdio->res_q);
|
||||
id->output_sbal_addr_array = (void **) (qdio->req_q);
|
||||
id->input_sbal_addr_array = qdio->res_q;
|
||||
id->output_sbal_addr_array = qdio->req_q;
|
||||
id->scan_threshold =
|
||||
QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
|
||||
}
|
||||
|
|
|
@ -1185,6 +1185,10 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
|
|||
unsigned long prot, unsigned long flags,
|
||||
unsigned long fd, unsigned long pgoff);
|
||||
ssize_t ksys_readahead(int fd, loff_t offset, size_t count);
|
||||
int ksys_ipc(unsigned int call, int first, unsigned long second,
|
||||
unsigned long third, void __user * ptr, long fifth);
|
||||
int compat_ksys_ipc(u32 call, int first, int second,
|
||||
u32 third, u32 ptr, u32 fifth);
|
||||
|
||||
/*
|
||||
* The following kernel syscall equivalents are just wrappers to fs-internal
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include <linux/shm.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
|
||||
unsigned long, third, void __user *, ptr, long, fifth)
|
||||
int ksys_ipc(unsigned int call, int first, unsigned long second,
|
||||
unsigned long third, void __user * ptr, long fifth)
|
||||
{
|
||||
int version, ret;
|
||||
|
||||
|
@ -106,6 +106,12 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
|
|||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
|
||||
unsigned long, third, void __user *, ptr, long, fifth)
|
||||
{
|
||||
return ksys_ipc(call, first, second, third, ptr, fifth);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
@ -121,8 +127,8 @@ struct compat_ipc_kludge {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
|
||||
COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
|
||||
u32, third, compat_uptr_t, ptr, u32, fifth)
|
||||
int compat_ksys_ipc(u32 call, int first, int second,
|
||||
u32 third, compat_uptr_t ptr, u32 fifth)
|
||||
{
|
||||
int version;
|
||||
u32 pad;
|
||||
|
@ -195,5 +201,11 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
|
|||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
|
||||
u32, third, compat_uptr_t, ptr, u32, fifth)
|
||||
{
|
||||
return compat_ksys_ipc(call, first, second, third, ptr, fifth);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -366,6 +366,7 @@ COND_SYSCALL(kexec_file_load);
|
|||
/* s390 */
|
||||
COND_SYSCALL(s390_pci_mmio_read);
|
||||
COND_SYSCALL(s390_pci_mmio_write);
|
||||
COND_SYSCALL(s390_ipc);
|
||||
COND_SYSCALL_COMPAT(s390_ipc);
|
||||
|
||||
/* powerpc */
|
||||
|
|
Loading…
Reference in New Issue