From 4c5b03b60762bbe6b129b648e845f7faa5933f61 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 9 Oct 2015 13:36:40 +0200 Subject: s390/zcore: remove invalid kfree in init_cpu_info The extended save area for the boot CPU has been allocated by smp_save_dump_cpus() with memblock_alloc() and may not be freed with kfree(). Signed-off-by: Martin Schwidefsky --- drivers/s390/char/zcore.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 823f41fc4bbd..c839a1593b8f 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -160,7 +160,6 @@ static int __init init_cpu_info(enum arch_id arch) if (memcpy_hsa_kernel(&sa_ext->sa, sys_info.sa_base, sys_info.sa_size) < 0) { TRACE("could not copy from HSA\n"); - kfree(sa_ext); return -EIO; } if (MACHINE_HAS_VX) -- cgit v1.2.3-59-g8ed1b From bbfed511c262db4d046a35f0389d98645124814f Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 15 Oct 2015 11:14:19 +0200 Subject: s390/zcore: copy vector registers into the image data The /sys/kernel/debug/zcore/mem interface delivers the memory of the old system with the CPU registers stored to the assigned locations in each prefix page. For the vector registers the prefix page of each CPU has an address of a 1024 byte save area at 0x11b0. But the /sys/kernel/debug/zcore/mem interface fails copy the vector registers saved at boot of the zfcpdump kernel into the dump image. Copy the saved vector registers of a CPU to the outout buffer if the memory area that is read via /sys/kernel/debug/zcore/mem intersects with the vector register save area of this CPU. Acked-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/lowcore.h | 1 + drivers/s390/char/zcore.c | 70 +++++++++++++++++++++++++++++++---------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index afe1cfebf1a4..bc618067e725 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -35,6 +35,7 @@ struct save_area { struct save_area_ext { struct save_area sa; __vector128 vx_regs[32]; + u64 vx_sa_addr; }; struct _lowcore { diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index c839a1593b8f..e0c87a83eb34 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "sclp.h" @@ -151,6 +152,9 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) static int __init init_cpu_info(enum arch_id arch) { struct save_area_ext *sa_ext; + struct _lowcore *lc; + void *ptr; + int i; /* get info for boot cpu from lowcore, stored in the HSA */ @@ -162,8 +166,18 @@ static int __init init_cpu_info(enum arch_id arch) TRACE("could not copy from HSA\n"); return -EIO; } - if (MACHINE_HAS_VX) - save_vx_regs_safe(sa_ext->vx_regs); + if (!MACHINE_HAS_VX) + return 0; + + save_vx_regs_safe(sa_ext->vx_regs); + /* Get address of the vector register save area for each CPU */ + for (i = 0; i < dump_save_areas.count; i++) { + sa_ext = dump_save_areas.areas[i]; + lc = (struct _lowcore *)(unsigned long) sa_ext->sa.pref_reg; + ptr = &lc->vector_save_area_addr; + copy_from_oldmem(&sa_ext->vx_sa_addr, ptr, + sizeof(sa_ext->vx_sa_addr)); + } return 0; } @@ -245,6 +259,8 @@ static int copy_lc(void __user *buf, void *sa, int sa_off, int len) */ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) { + struct save_area_ext *sa_ext; + struct save_area *sa; unsigned long end; int i; @@ -255,26 +271,48 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) for (i = 0; i < dump_save_areas.count; i++) { unsigned long cp_start, cp_end; /* copy range */ unsigned long sa_start, sa_end; /* save area range */ - unsigned long prefix; unsigned long sa_off, len, buf_off; - struct save_area *save_area = &dump_save_areas.areas[i]->sa; - prefix = save_area->pref_reg; - sa_start = prefix + sys_info.sa_base; - sa_end = prefix + sys_info.sa_base + sys_info.sa_size; + sa_ext = dump_save_areas.areas[i]; + sa = &sa_ext->sa; + + /* Copy the 512 bytes lowcore save area 0x1200 - 0x1400 */ + sa_start = sa->pref_reg + sys_info.sa_base; + sa_end = sa_start + sys_info.sa_size; + + if (end >= sa_start && start < sa_end) { + cp_start = max(start, sa_start); + cp_end = min(end, sa_end); + buf_off = cp_start - start; + sa_off = cp_start - sa_start; + len = cp_end - cp_start; - if ((end < sa_start) || (start > sa_end)) + TRACE("copy_lc: %lx-%lx\n", cp_start, cp_end); + if (copy_lc(buf + buf_off, sa, sa_off, len)) + return -EFAULT; + } + + if (!MACHINE_HAS_VX) continue; - cp_start = max(start, sa_start); - cp_end = min(end, sa_end); - buf_off = cp_start - start; - sa_off = cp_start - sa_start; - len = cp_end - cp_start; + /* Copy the 512 bytes vector save area */ + sa_start = sa_ext->vx_sa_addr & -1024UL; + sa_end = sa_start + 512; - TRACE("copy_lc for: %lx\n", start); - if (copy_lc(buf + buf_off, save_area, sa_off, len)) - return -EFAULT; + if (end >= sa_start && start < sa_end) { + cp_start = max(start, sa_start); + cp_end = min(end, sa_end); + + buf_off = cp_start - start; + sa_off = cp_start - sa_start; + len = cp_end - cp_start; + + TRACE("copy vxrs: %lx-%lx\n", cp_start, cp_end); + if (copy_to_user(buf + buf_off, + (void *) &sa_ext->vx_regs + sa_off, + len)) + return -EFAULT; + } } return 0; } -- cgit v1.2.3-59-g8ed1b From ffa52d02c50ea31420dc70869c0b6b439e7cb5ef Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 28 Oct 2015 09:47:58 +0100 Subject: s390/zcore: remove /sys/kernel/debug/zcore/mem New versions of the SCSI dumper use the /dev/vmcore interface instead of zcore mem. Remove the outdated interface. Acked-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- Documentation/s390/zfcpdump.txt | 22 +-- arch/s390/include/asm/lowcore.h | 1 - drivers/s390/char/Makefile | 4 +- drivers/s390/char/zcore.c | 394 +--------------------------------------- 4 files changed, 18 insertions(+), 403 deletions(-) diff --git a/Documentation/s390/zfcpdump.txt b/Documentation/s390/zfcpdump.txt index dc929be96016..b064aa59714d 100644 --- a/Documentation/s390/zfcpdump.txt +++ b/Documentation/s390/zfcpdump.txt @@ -15,19 +15,15 @@ the s390-tools package) to make the device bootable. The operator of a Linux system can then trigger a SCSI dump by booting the SCSI disk, where zfcpdump resides on. -The kernel part of zfcpdump is implemented as a debugfs file under "zcore/mem", -which exports memory and registers of the crashed Linux in an s390 -standalone dump format. It can be used in the same way as e.g. /dev/mem. The -dump format defines a 4K header followed by plain uncompressed memory. The -register sets are stored in the prefix pages of the respective CPUs. To build a -dump enabled kernel with the zcore driver, the kernel config option -CONFIG_CRASH_DUMP has to be set. When reading from "zcore/mem", the part of -memory, which has been saved by hardware is read by the driver via the SCLP -hardware interface. The second part is just copied from the non overwritten real -memory. - -Since kernel version 3.12 also the /proc/vmcore file can also be used to access -the dump. +The user space dump tool accesses the memory of the crashed system by means +of the /proc/vmcore interface. This interface exports the crashed system's +memory and registers in ELF core dump format. To access the memory which has +been saved by the hardware SCLP requests will be created at the time the data +is needed by /proc/vmcore. The tail part of the crashed systems memory which +has not been stashed by hardware can just be copied from real memory. + +To build a dump enabled kernel the kernel config option CONFIG_CRASH_DUMP +has to be set. To get a valid zfcpdump kernel configuration use "make zfcpdump_defconfig". diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index bc618067e725..afe1cfebf1a4 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -35,7 +35,6 @@ struct save_area { struct save_area_ext { struct save_area sa; __vector128 vx_regs[32]; - u64 vx_sa_addr; }; struct _lowcore { diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index 6fa9364d1c07..8a2632ba88dc 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -30,9 +30,7 @@ obj-$(CONFIG_S390_TAPE_3590) += tape_3590.o obj-$(CONFIG_MONREADER) += monreader.o obj-$(CONFIG_MONWRITER) += monwriter.o obj-$(CONFIG_S390_VMUR) += vmur.o - -zcore_mod-objs := sclp_sdias.o zcore.o -obj-$(CONFIG_CRASH_DUMP) += zcore_mod.o +obj-$(CONFIG_CRASH_DUMP) += sclp_sdias.o zcore.o hmcdrv-objs := hmcdrv_mod.o hmcdrv_dev.o hmcdrv_ftp.o hmcdrv_cache.o diag_ftp.o sclp_ftp.o obj-$(CONFIG_HMC_DRV) += hmcdrv.o diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index e0c87a83eb34..3ad3d538e432 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -43,27 +43,14 @@ enum arch_id { ARCH_S390X = 1, }; -/* dump system info */ - -struct sys_info { - enum arch_id arch; - unsigned long sa_base; - u32 sa_size; - int cpu_map[NR_CPUS]; - unsigned long mem_size; - struct save_area lc_mask; -}; - struct ipib_info { unsigned long ipib; u32 checksum; } __attribute__((packed)); -static struct sys_info sys_info; static struct debug_info *zcore_dbf; static int hsa_available; static struct dentry *zcore_dir; -static struct dentry *zcore_file; static struct dentry *zcore_memmap_file; static struct dentry *zcore_reipl_file; static struct dentry *zcore_hsa_file; @@ -149,171 +136,22 @@ static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) return memcpy_hsa(dest, src, count, TO_KERNEL); } -static int __init init_cpu_info(enum arch_id arch) +static int __init init_cpu_info(void) { struct save_area_ext *sa_ext; - struct _lowcore *lc; - void *ptr; - int i; /* get info for boot cpu from lowcore, stored in the HSA */ sa_ext = dump_save_areas.areas[0]; if (!sa_ext) return -ENOMEM; - if (memcpy_hsa_kernel(&sa_ext->sa, sys_info.sa_base, - sys_info.sa_size) < 0) { + if (memcpy_hsa_kernel(&sa_ext->sa, SAVE_AREA_BASE, + sizeof(struct save_area)) < 0) { TRACE("could not copy from HSA\n"); return -EIO; } - if (!MACHINE_HAS_VX) - return 0; - - save_vx_regs_safe(sa_ext->vx_regs); - /* Get address of the vector register save area for each CPU */ - for (i = 0; i < dump_save_areas.count; i++) { - sa_ext = dump_save_areas.areas[i]; - lc = (struct _lowcore *)(unsigned long) sa_ext->sa.pref_reg; - ptr = &lc->vector_save_area_addr; - copy_from_oldmem(&sa_ext->vx_sa_addr, ptr, - sizeof(sa_ext->vx_sa_addr)); - } - return 0; -} - -static DEFINE_MUTEX(zcore_mutex); - -#define DUMP_VERSION 0x5 -#define DUMP_MAGIC 0xa8190173618f23fdULL -#define DUMP_ARCH_S390X 2 -#define DUMP_ARCH_S390 1 -#define HEADER_SIZE 4096 - -/* dump header dumped according to s390 crash dump format */ - -struct zcore_header { - u64 magic; - u32 version; - u32 header_size; - u32 dump_level; - u32 page_size; - u64 mem_size; - u64 mem_start; - u64 mem_end; - u32 num_pages; - u32 pad1; - u64 tod; - struct cpuid cpu_id; - u32 arch_id; - u32 volnr; - u32 build_arch; - u64 rmem_size; - u8 mvdump; - u16 cpu_cnt; - u16 real_cpu_cnt; - u8 end_pad1[0x200-0x061]; - u64 mvdump_sign; - u64 mvdump_zipl_time; - u8 end_pad2[0x800-0x210]; - u32 lc_vec[512]; -} __attribute__((packed,__aligned__(16))); - -static struct zcore_header zcore_header = { - .magic = DUMP_MAGIC, - .version = DUMP_VERSION, - .header_size = 4096, - .dump_level = 0, - .page_size = PAGE_SIZE, - .mem_start = 0, - .build_arch = DUMP_ARCH_S390X, -}; - -/* - * Copy lowcore info to buffer. Use map in order to copy only register parts. - * - * @buf: User buffer - * @sa: Pointer to save area - * @sa_off: Offset in save area to copy - * @len: Number of bytes to copy - */ -static int copy_lc(void __user *buf, void *sa, int sa_off, int len) -{ - int i; - char *lc_mask = (char*)&sys_info.lc_mask; - - for (i = 0; i < len; i++) { - if (!lc_mask[i + sa_off]) - continue; - if (copy_to_user(buf + i, sa + sa_off + i, 1)) - return -EFAULT; - } - return 0; -} - -/* - * Copy lowcores info to memory, if necessary - * - * @buf: User buffer - * @addr: Start address of buffer in dump memory - * @count: Size of buffer - */ -static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) -{ - struct save_area_ext *sa_ext; - struct save_area *sa; - unsigned long end; - int i; - - if (count == 0) - return 0; - - end = start + count; - for (i = 0; i < dump_save_areas.count; i++) { - unsigned long cp_start, cp_end; /* copy range */ - unsigned long sa_start, sa_end; /* save area range */ - unsigned long sa_off, len, buf_off; - - sa_ext = dump_save_areas.areas[i]; - sa = &sa_ext->sa; - - /* Copy the 512 bytes lowcore save area 0x1200 - 0x1400 */ - sa_start = sa->pref_reg + sys_info.sa_base; - sa_end = sa_start + sys_info.sa_size; - - if (end >= sa_start && start < sa_end) { - cp_start = max(start, sa_start); - cp_end = min(end, sa_end); - buf_off = cp_start - start; - sa_off = cp_start - sa_start; - len = cp_end - cp_start; - - TRACE("copy_lc: %lx-%lx\n", cp_start, cp_end); - if (copy_lc(buf + buf_off, sa, sa_off, len)) - return -EFAULT; - } - - if (!MACHINE_HAS_VX) - continue; - - /* Copy the 512 bytes vector save area */ - sa_start = sa_ext->vx_sa_addr & -1024UL; - sa_end = sa_start + 512; - - if (end >= sa_start && start < sa_end) { - cp_start = max(start, sa_start); - cp_end = min(end, sa_end); - - buf_off = cp_start - start; - sa_off = cp_start - sa_start; - len = cp_end - cp_start; - - TRACE("copy vxrs: %lx-%lx\n", cp_start, cp_end); - if (copy_to_user(buf + buf_off, - (void *) &sa_ext->vx_regs + sa_off, - len)) - return -EFAULT; - } - } + if (MACHINE_HAS_VX) + save_vx_regs_safe(sa_ext->vx_regs); return 0; } @@ -326,126 +164,6 @@ static void release_hsa(void) hsa_available = 0; } -/* - * Read routine for zcore character device - * First 4K are dump header - * Next 32MB are HSA Memory - * Rest is read from absolute Memory - */ -static ssize_t zcore_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - unsigned long mem_start; /* Start address in memory */ - size_t mem_offs; /* Offset in dump memory */ - size_t hdr_count; /* Size of header part of output buffer */ - size_t size; - int rc; - - mutex_lock(&zcore_mutex); - - if (*ppos > (sys_info.mem_size + HEADER_SIZE)) { - rc = -EINVAL; - goto fail; - } - - count = min(count, (size_t) (sys_info.mem_size + HEADER_SIZE - *ppos)); - - /* Copy dump header */ - if (*ppos < HEADER_SIZE) { - size = min(count, (size_t) (HEADER_SIZE - *ppos)); - if (copy_to_user(buf, &zcore_header + *ppos, size)) { - rc = -EFAULT; - goto fail; - } - hdr_count = size; - mem_start = 0; - } else { - hdr_count = 0; - mem_start = *ppos - HEADER_SIZE; - } - - mem_offs = 0; - - /* Copy from HSA data */ - if (*ppos < sclp.hsa_size + HEADER_SIZE) { - size = min((count - hdr_count), - (size_t) (sclp.hsa_size - mem_start)); - rc = memcpy_hsa_user(buf + hdr_count, mem_start, size); - if (rc) - goto fail; - - mem_offs += size; - } - - /* Copy from real mem */ - size = count - mem_offs - hdr_count; - rc = copy_to_user_real(buf + hdr_count + mem_offs, - (void *) mem_start + mem_offs, size); - if (rc) - goto fail; - - /* - * Since s390 dump analysis tools like lcrash or crash - * expect register sets in the prefix pages of the cpus, - * we copy them into the read buffer, if necessary. - * buf + hdr_count: Start of memory part of output buffer - * mem_start: Start memory address to copy from - * count - hdr_count: Size of memory area to copy - */ - if (zcore_add_lc(buf + hdr_count, mem_start, count - hdr_count)) { - rc = -EFAULT; - goto fail; - } - *ppos += count; -fail: - mutex_unlock(&zcore_mutex); - return (rc < 0) ? rc : count; -} - -static int zcore_open(struct inode *inode, struct file *filp) -{ - if (!hsa_available) - return -ENODATA; - else - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -static int zcore_release(struct inode *inode, struct file *filep) -{ - if (hsa_available) - release_hsa(); - return 0; -} - -static loff_t zcore_lseek(struct file *file, loff_t offset, int orig) -{ - loff_t rc; - - mutex_lock(&zcore_mutex); - switch (orig) { - case 0: - file->f_pos = offset; - rc = file->f_pos; - break; - case 1: - file->f_pos += offset; - rc = file->f_pos; - break; - default: - rc = -EINVAL; - } - mutex_unlock(&zcore_mutex); - return rc; -} - -static const struct file_operations zcore_fops = { - .owner = THIS_MODULE, - .llseek = zcore_lseek, - .read = zcore_read, - .open = zcore_open, - .release = zcore_release, -}; - static ssize_t zcore_memmap_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { @@ -549,50 +267,6 @@ static const struct file_operations zcore_hsa_fops = { .llseek = no_llseek, }; -static void __init set_lc_mask(struct save_area *map) -{ - memset(&map->fp_regs, 0xff, sizeof(map->fp_regs)); - memset(&map->gp_regs, 0xff, sizeof(map->gp_regs)); - memset(&map->psw, 0xff, sizeof(map->psw)); - memset(&map->pref_reg, 0xff, sizeof(map->pref_reg)); - memset(&map->fp_ctrl_reg, 0xff, sizeof(map->fp_ctrl_reg)); - memset(&map->tod_reg, 0xff, sizeof(map->tod_reg)); - memset(&map->timer, 0xff, sizeof(map->timer)); - memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp)); - memset(&map->acc_regs, 0xff, sizeof(map->acc_regs)); - memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs)); -} - -/* - * Initialize dump globals for a given architecture - */ -static int __init sys_info_init(enum arch_id arch, unsigned long mem_end) -{ - int rc; - - switch (arch) { - case ARCH_S390X: - pr_alert("DETECTED 'S390X (64 bit) OS'\n"); - break; - case ARCH_S390: - pr_alert("DETECTED 'S390 (32 bit) OS'\n"); - break; - default: - pr_alert("0x%x is an unknown architecture.\n",arch); - return -EINVAL; - } - sys_info.sa_base = SAVE_AREA_BASE; - sys_info.sa_size = sizeof(struct save_area); - sys_info.arch = arch; - set_lc_mask(&sys_info.lc_mask); - rc = init_cpu_info(arch); - if (rc) - return rc; - sys_info.mem_size = mem_end; - - return 0; -} - static int __init check_sdias(void) { if (!sclp.hsa_size) { @@ -602,43 +276,6 @@ static int __init check_sdias(void) return 0; } -static int __init get_mem_info(unsigned long *mem, unsigned long *end) -{ - struct memblock_region *reg; - - for_each_memblock(memory, reg) { - *mem += reg->size; - *end = max_t(unsigned long, *end, reg->base + reg->size); - } - return 0; -} - -static void __init zcore_header_init(int arch, struct zcore_header *hdr, - unsigned long mem_size) -{ - u32 prefix; - int i; - - if (arch == ARCH_S390X) - hdr->arch_id = DUMP_ARCH_S390X; - else - hdr->arch_id = DUMP_ARCH_S390; - hdr->mem_size = mem_size; - hdr->rmem_size = mem_size; - hdr->mem_end = sys_info.mem_size; - hdr->num_pages = mem_size / PAGE_SIZE; - hdr->tod = get_tod_clock(); - get_cpu_id(&hdr->cpu_id); - for (i = 0; i < dump_save_areas.count; i++) { - prefix = dump_save_areas.areas[i]->sa.pref_reg; - hdr->real_cpu_cnt++; - if (!prefix) - continue; - hdr->lc_vec[hdr->cpu_cnt] = prefix; - hdr->cpu_cnt++; - } -} - /* * Provide IPL parameter information block from either HSA or memory * for future reipl @@ -671,11 +308,9 @@ static int __init zcore_reipl_init(void) static int __init zcore_init(void) { - unsigned long mem_size, mem_end; unsigned char arch; int rc; - mem_size = mem_end = 0; if (ipl_info.type != IPL_TYPE_FCP_DUMP) return -ENODATA; if (OLDMEM_BASE) @@ -709,15 +344,11 @@ static int __init zcore_init(void) goto fail; } - rc = get_mem_info(&mem_size, &mem_end); + pr_alert("DETECTED 'S390X (64 bit) OS'\n"); + rc = init_cpu_info(); if (rc) goto fail; - rc = sys_info_init(arch, mem_end); - if (rc) - goto fail; - zcore_header_init(arch, &zcore_header, mem_size); - rc = zcore_reipl_init(); if (rc) goto fail; @@ -727,17 +358,11 @@ static int __init zcore_init(void) rc = -ENOMEM; goto fail; } - zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL, - &zcore_fops); - if (!zcore_file) { - rc = -ENOMEM; - goto fail_dir; - } zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir, NULL, &zcore_memmap_fops); if (!zcore_memmap_file) { rc = -ENOMEM; - goto fail_file; + goto fail_dir; } zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, NULL, &zcore_reipl_fops); @@ -757,8 +382,6 @@ fail_reipl_file: debugfs_remove(zcore_reipl_file); fail_memmap_file: debugfs_remove(zcore_memmap_file); -fail_file: - debugfs_remove(zcore_file); fail_dir: debugfs_remove(zcore_dir); fail: @@ -774,7 +397,6 @@ static void __exit zcore_exit(void) debugfs_remove(zcore_hsa_file); debugfs_remove(zcore_reipl_file); debugfs_remove(zcore_memmap_file); - debugfs_remove(zcore_file); debugfs_remove(zcore_dir); diag308(DIAG308_REL_HSA, NULL); } -- cgit v1.2.3-59-g8ed1b From 8a07dd02d7615d91d65d6235f7232e3f9b5d347f Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 14 Oct 2015 15:53:06 +0200 Subject: s390/kdump: remove code to create ELF notes in the crashed system The s390 architecture can store the CPU registers of the crashed system after the kdump kernel has been started and this is the preferred way. Remove the remaining code fragments that deal with storing CPU registers while the crashed system is still active. Acked-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/elf.h | 2 -- arch/s390/kernel/crash_dump.c | 24 +++-------------------- arch/s390/kernel/machine_kexec.c | 42 +++++++++++++++++----------------------- arch/s390/kernel/setup.c | 15 +++++--------- arch/s390/kernel/smp.c | 8 ++------ 5 files changed, 28 insertions(+), 63 deletions(-) diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index bab6739a1154..7730e5b9e7e2 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -229,6 +229,4 @@ struct linux_binprm; #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 int arch_setup_additional_pages(struct linux_binprm *, int); -void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, __vector128 *vxrs); - #endif diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 171e09bb8ea2..07d75b969f59 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -72,11 +72,6 @@ static int copy_from_realmem(void *dest, void *src, size_t count) return 0; } -/* - * Pointer to ELF header in new kernel - */ -static void *elfcorehdr_newmem; - /* * Copy one page from zfcpdump "oldmem" * @@ -390,7 +385,8 @@ static void *nt_s390_vx_low(void *ptr, __vector128 *vx_regs) /* * Fill ELF notes for one CPU with save area registers */ -void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, __vector128 *vx_regs) +static void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, + __vector128 *vx_regs) { ptr = nt_prstatus(ptr, sa); ptr = nt_fpregset(ptr, sa); @@ -573,9 +569,6 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) /* If we are not in kdump or zfcpdump mode return */ if (!OLDMEM_BASE && ipl_info.type != IPL_TYPE_FCP_DUMP) return 0; - /* If elfcorehdr= has been passed via cmdline, we use that one */ - if (elfcorehdr_addr != ELFCORE_ADDR_MAX) - return 0; /* If we cannot get HSA size for zfcpdump return error */ if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp.hsa_size) return -ENODEV; @@ -606,7 +599,6 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) hdr_off = PTR_DIFF(ptr, hdr); loads_init(phdr_loads, hdr_off); *addr = (unsigned long long) hdr; - elfcorehdr_newmem = hdr; *size = (unsigned long long) hdr_off; BUG_ON(elfcorehdr_size > alloc_size); return 0; @@ -617,8 +609,6 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) */ void elfcorehdr_free(unsigned long long addr) { - if (!elfcorehdr_newmem) - return; kfree((void *)(unsigned long)addr); } @@ -629,7 +619,6 @@ ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos) { void *src = (void *)(unsigned long)*ppos; - src = elfcorehdr_newmem ? src : src - OLDMEM_BASE; memcpy(buf, src, count); *ppos += count; return count; @@ -641,15 +630,8 @@ ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos) ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos) { void *src = (void *)(unsigned long)*ppos; - int rc; - if (elfcorehdr_newmem) { - memcpy(buf, src, count); - } else { - rc = copy_from_oldmem(buf, src, count); - if (rc) - return rc; - } + memcpy(buf, src, count); *ppos += count; return count; } diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index fb0901ec4306..991b16819b97 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -34,44 +34,38 @@ extern const unsigned long long relocate_kernel_len; #ifdef CONFIG_CRASH_DUMP -/* - * Create ELF notes for one CPU - */ -static void add_elf_notes(int cpu) -{ - struct save_area *sa = (void *) 4608 + store_prefix(); - void *ptr; - - memcpy((void *) (4608UL + sa->pref_reg), sa, sizeof(*sa)); - ptr = (u64 *) per_cpu_ptr(crash_notes, cpu); - ptr = fill_cpu_elf_notes(ptr, sa, NULL); - memset(ptr, 0, sizeof(struct elf_note)); -} - /* * Initialize CPU ELF notes */ static void setup_regs(void) { - unsigned long sa = S390_lowcore.prefixreg_save_area + SAVE_AREA_BASE; - struct _lowcore *lc; + struct save_area *sa, *sa_0; + unsigned long prefix; int cpu, this_cpu; - /* Get lowcore pointer from store status of this CPU (absolute zero) */ - lc = (struct _lowcore *)(unsigned long)S390_lowcore.prefixreg_save_area; + /* setup_regs is called with the prefix register = 0 */ + sa_0 = (struct save_area *) SAVE_AREA_BASE; + + /* Get status of this CPU out of absolute zero */ + prefix = (unsigned long) S390_lowcore.prefixreg_save_area; + sa = (struct save_area *)(prefix + SAVE_AREA_BASE); + memcpy(sa, sa_0, sizeof(struct save_area)); + if (MACHINE_HAS_VX) { + struct _lowcore *lc = (struct _lowcore *) prefix; + save_vx_regs_safe((void *) lc->vector_save_area_addr); + } + + /* Get status of the other CPUs */ this_cpu = smp_find_processor_id(stap()); - add_elf_notes(this_cpu); for_each_online_cpu(cpu) { if (cpu == this_cpu) continue; if (smp_store_status(cpu)) continue; - add_elf_notes(cpu); + prefix = (unsigned long) S390_lowcore.prefixreg_save_area; + sa = (struct save_area *)(prefix + SAVE_AREA_BASE); + memcpy(sa, sa_0, sizeof(struct save_area)); } - if (MACHINE_HAS_VX) - save_vx_regs_safe((void *) lc->vector_save_area_addr); - /* Copy dump CPU store status info to absolute zero */ - memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area)); } /* diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index c837bcacf218..8f5107d6ebb3 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -661,15 +661,6 @@ static void __init reserve_kernel(void) #endif } -static void __init reserve_elfcorehdr(void) -{ -#ifdef CONFIG_CRASH_DUMP - if (is_kdump_kernel()) - memblock_reserve(elfcorehdr_addr - OLDMEM_BASE, - PAGE_ALIGN(elfcorehdr_size)); -#endif -} - static void __init setup_memory(void) { struct memblock_region *reg; @@ -841,6 +832,11 @@ void __init setup_arch(char **cmdline_p) init_mm.brk = (unsigned long) &_end; parse_early_param(); +#ifdef CONFIG_CRASH_DUMP + /* Deactivate elfcorehdr= kernel parameter */ + elfcorehdr_addr = ELFCORE_ADDR_MAX; +#endif + os_info_init(); setup_ipl(); @@ -849,7 +845,6 @@ void __init setup_arch(char **cmdline_p) reserve_oldmem(); reserve_kernel(); reserve_initrd(); - reserve_elfcorehdr(); memblock_allow_resize(); /* Get information about *all* installed memory */ diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 9062df575afe..7ad070e984f2 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -608,9 +608,8 @@ int smp_store_status(int cpu) * stored the registers of the boot CPU in the memory of the old system. * 4) kdump and the old kernel stored the CPU state * condition: OLDMEM_BASE != NULL && is_kdump_kernel() - * The state of all CPUs is stored in ELF sections in the memory of the - * old system. The ELF sections are picked up by the crash_dump code - * via elfcorehdr_addr. + * This case does not exist for s390 anymore, setup_arch explicitly + * deactivates the elfcorehdr= kernel parameter */ void __init smp_save_dump_cpus(void) { @@ -619,9 +618,6 @@ void __init smp_save_dump_cpus(void) struct save_area_ext *sa_ext; bool is_boot_cpu; - if (is_kdump_kernel()) - /* Previous system stored the CPU states. Nothing to do. */ - return; if (!(OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP)) /* No previous system present, normal boot. */ return; -- cgit v1.2.3-59-g8ed1b From df9694c7975ff9976368eb381388c61f65352aef Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 12 Oct 2015 10:43:37 +0200 Subject: s390/dump: streamline oldmem copy functions Introduce two copy functions for the memory of the dumped system, copy_oldmem_kernel() to copy to the virtual kernel address space and copy_oldmem_user() to copy to user space. Acked-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/os_info.h | 2 +- arch/s390/include/asm/sclp.h | 3 +- arch/s390/kernel/crash_dump.c | 171 +++++++++++++++++++--------------------- arch/s390/kernel/os_info.c | 7 +- arch/s390/kernel/smp.c | 4 +- drivers/s390/char/zcore.c | 20 ++++- 6 files changed, 105 insertions(+), 102 deletions(-) diff --git a/arch/s390/include/asm/os_info.h b/arch/s390/include/asm/os_info.h index 295f2c4f1c96..943475382d51 100644 --- a/arch/s390/include/asm/os_info.h +++ b/arch/s390/include/asm/os_info.h @@ -38,7 +38,7 @@ u32 os_info_csum(struct os_info *os_info); #ifdef CONFIG_CRASH_DUMP void *os_info_old_entry(int nr, unsigned long *size); -int copy_from_oldmem(void *dest, void *src, size_t count); +int copy_oldmem_kernel(void *dst, void *src, size_t count); #else static inline void *os_info_old_entry(int nr, unsigned long *size) { diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 821dde5f425d..2ca9c7bc50db 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -77,7 +77,8 @@ int sclp_chp_read_info(struct sclp_chp_info *info); void sclp_get_ipl_info(struct sclp_ipl_info *info); int sclp_pci_configure(u32 fid); int sclp_pci_deconfigure(u32 fid); -int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); +int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count); +int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count); void sclp_early_detect(void); int _sclp_print_early(const char *); diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 07d75b969f59..0d59c0705c4f 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -51,74 +51,85 @@ static inline void *load_real_addr(void *addr) } /* - * Copy real to virtual or real memory + * Copy memory of the old, dumped system to a kernel space virtual address */ -static int copy_from_realmem(void *dest, void *src, size_t count) -{ - unsigned long size; - - if (!count) - return 0; - if (!is_vmalloc_or_module_addr(dest)) - return memcpy_real(dest, src, count); - do { - size = min(count, PAGE_SIZE - (__pa(dest) & ~PAGE_MASK)); - if (memcpy_real(load_real_addr(dest), src, size)) - return -EFAULT; - count -= size; - dest += size; - src += size; - } while (count); - return 0; -} - -/* - * Copy one page from zfcpdump "oldmem" - * - * For pages below HSA size memory from the HSA is copied. Otherwise - * real memory copy is used. - */ -static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, - unsigned long src, int userbuf) +int copy_oldmem_kernel(void *dst, void *src, size_t count) { + unsigned long from, len; + void *ra; int rc; - if (src < sclp.hsa_size) { - rc = memcpy_hsa(buf, src, csize, userbuf); - } else { - if (userbuf) - rc = copy_to_user_real((void __force __user *) buf, - (void *) src, csize); - else - rc = memcpy_real(buf, (void *) src, csize); + while (count) { + from = __pa(src); + if (!OLDMEM_BASE && from < sclp.hsa_size) { + /* Copy from zfcpdump HSA area */ + len = min(count, sclp.hsa_size - from); + rc = memcpy_hsa_kernel(dst, from, len); + if (rc) + return rc; + } else { + /* Check for swapped kdump oldmem areas */ + if (OLDMEM_BASE && from - OLDMEM_BASE < OLDMEM_SIZE) { + from -= OLDMEM_BASE; + len = min(count, OLDMEM_SIZE - from); + } else if (OLDMEM_BASE && from < OLDMEM_SIZE) { + len = min(count, OLDMEM_SIZE - from); + from += OLDMEM_BASE; + } else { + len = count; + } + if (is_vmalloc_or_module_addr(dst)) { + ra = load_real_addr(dst); + len = min(PAGE_SIZE - offset_in_page(ra), len); + } else { + ra = dst; + } + if (memcpy_real(ra, (void *) from, len)) + return -EFAULT; + } + dst += len; + src += len; + count -= len; } - return rc ? rc : csize; + return 0; } /* - * Copy one page from kdump "oldmem" - * - * For the kdump reserved memory this functions performs a swap operation: - * - [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] is mapped to [0 - OLDMEM_SIZE]. - * - [0 - OLDMEM_SIZE] is mapped to [OLDMEM_BASE - OLDMEM_BASE + OLDMEM_SIZE] + * Copy memory of the old, dumped system to a user space virtual address */ -static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize, - unsigned long src, int userbuf) - +int copy_oldmem_user(void __user *dst, void *src, size_t count) { + unsigned long from, len; int rc; - if (src < OLDMEM_SIZE) - src += OLDMEM_BASE; - else if (src > OLDMEM_BASE && - src < OLDMEM_BASE + OLDMEM_SIZE) - src -= OLDMEM_BASE; - if (userbuf) - rc = copy_to_user_real((void __force __user *) buf, - (void *) src, csize); - else - rc = copy_from_realmem(buf, (void *) src, csize); - return (rc == 0) ? rc : csize; + while (count) { + from = __pa(src); + if (!OLDMEM_BASE && from < sclp.hsa_size) { + /* Copy from zfcpdump HSA area */ + len = min(count, sclp.hsa_size - from); + rc = memcpy_hsa_user(dst, from, len); + if (rc) + return rc; + } else { + /* Check for swapped kdump oldmem areas */ + if (OLDMEM_BASE && from - OLDMEM_BASE < OLDMEM_SIZE) { + from -= OLDMEM_BASE; + len = min(count, OLDMEM_SIZE - from); + } else if (OLDMEM_BASE && from < OLDMEM_SIZE) { + len = min(count, OLDMEM_SIZE - from); + from += OLDMEM_BASE; + } else { + len = count; + } + rc = copy_to_user_real(dst, (void *) from, count); + if (rc) + return rc; + } + dst += len; + src += len; + count -= len; + } + return 0; } /* @@ -127,15 +138,17 @@ static ssize_t copy_oldmem_page_kdump(char *buf, size_t csize, ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize, unsigned long offset, int userbuf) { - unsigned long src; + void *src; + int rc; if (!csize) return 0; - src = (pfn << PAGE_SHIFT) + offset; - if (OLDMEM_BASE) - return copy_oldmem_page_kdump(buf, csize, src, userbuf); + src = (void *) (pfn << PAGE_SHIFT) + offset; + if (userbuf) + rc = copy_oldmem_user((void __force __user *) buf, src, csize); else - return copy_oldmem_page_zfcpdump(buf, csize, src, userbuf); + rc = copy_oldmem_kernel((void *) buf, src, csize); + return rc; } /* @@ -203,33 +216,6 @@ int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from, prot); } -/* - * Copy memory from old kernel - */ -int copy_from_oldmem(void *dest, void *src, size_t count) -{ - unsigned long copied = 0; - int rc; - - if (OLDMEM_BASE) { - if ((unsigned long) src < OLDMEM_SIZE) { - copied = min(count, OLDMEM_SIZE - (unsigned long) src); - rc = copy_from_realmem(dest, src + OLDMEM_BASE, copied); - if (rc) - return rc; - } - } else { - unsigned long hsa_end = sclp.hsa_size; - if ((unsigned long) src < hsa_end) { - copied = min(count, hsa_end - (unsigned long) src); - rc = memcpy_hsa(dest, (unsigned long) src, copied, 0); - if (rc) - return rc; - } - } - return copy_from_realmem(dest + copied, src + copied, count - copied); -} - /* * Alloc memory and panic in case of ENOMEM */ @@ -425,17 +411,18 @@ static void *get_vmcoreinfo_old(unsigned long *size) Elf64_Nhdr note; void *addr; - if (copy_from_oldmem(&addr, &S390_lowcore.vmcore_info, sizeof(addr))) + if (copy_oldmem_kernel(&addr, &S390_lowcore.vmcore_info, sizeof(addr))) return NULL; memset(nt_name, 0, sizeof(nt_name)); - if (copy_from_oldmem(¬e, addr, sizeof(note))) + if (copy_oldmem_kernel(¬e, addr, sizeof(note))) return NULL; - if (copy_from_oldmem(nt_name, addr + sizeof(note), sizeof(nt_name) - 1)) + if (copy_oldmem_kernel(nt_name, addr + sizeof(note), + sizeof(nt_name) - 1)) return NULL; if (strcmp(nt_name, "VMCOREINFO") != 0) return NULL; vmcoreinfo = kzalloc_panic(note.n_descsz); - if (copy_from_oldmem(vmcoreinfo, addr + 24, note.n_descsz)) + if (copy_oldmem_kernel(vmcoreinfo, addr + 24, note.n_descsz)) return NULL; *size = note.n_descsz; return vmcoreinfo; diff --git a/arch/s390/kernel/os_info.c b/arch/s390/kernel/os_info.c index d112fc66f993..87f05e475ae8 100644 --- a/arch/s390/kernel/os_info.c +++ b/arch/s390/kernel/os_info.c @@ -89,7 +89,7 @@ static void os_info_old_alloc(int nr, int align) goto fail; } buf_align = PTR_ALIGN(buf, align); - if (copy_from_oldmem(buf_align, (void *) addr, size)) { + if (copy_oldmem_kernel(buf_align, (void *) addr, size)) { msg = "copy failed"; goto fail_free; } @@ -122,14 +122,15 @@ static void os_info_old_init(void) return; if (!OLDMEM_BASE) goto fail; - if (copy_from_oldmem(&addr, &S390_lowcore.os_info, sizeof(addr))) + if (copy_oldmem_kernel(&addr, &S390_lowcore.os_info, sizeof(addr))) goto fail; if (addr == 0 || addr % PAGE_SIZE) goto fail; os_info_old = kzalloc(sizeof(*os_info_old), GFP_KERNEL); if (!os_info_old) goto fail; - if (copy_from_oldmem(os_info_old, (void *) addr, sizeof(*os_info_old))) + if (copy_oldmem_kernel(os_info_old, (void *) addr, + sizeof(*os_info_old))) goto fail_free; if (os_info_old->magic != OS_INFO_MAGIC) goto fail_free; diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 7ad070e984f2..5e04acdc6290 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -546,8 +546,8 @@ static void __init __smp_store_cpu_state(struct save_area_ext *sa_ext, if (is_boot_cpu) { /* Copy the registers of the boot CPU. */ - copy_oldmem_page(1, (void *) &sa_ext->sa, sizeof(sa_ext->sa), - SAVE_AREA_BASE - PAGE_SIZE, 0); + copy_oldmem_kernel(&sa_ext->sa, (void *) SAVE_AREA_BASE, + sizeof(sa_ext->sa)); if (MACHINE_HAS_VX) save_vx_regs_safe(sa_ext->vx_regs); return; diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 3ad3d538e432..4fa455787a77 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -64,7 +64,7 @@ static struct ipl_parameter_block *ipl_block; * @count: Size of buffer, which should be copied * @mode: Either TO_KERNEL or TO_USER */ -int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode) +static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode) { int offs, blk_num; static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); @@ -126,12 +126,26 @@ out: return 0; } -static int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) +/* + * Copy memory from HSA to user memory (not reentrant): + * + * @dest: Kernel or user buffer where memory should be copied to + * @src: Start address within HSA where data should be copied + * @count: Size of buffer, which should be copied + */ +int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) { return memcpy_hsa((void __force *) dest, src, count, TO_USER); } -static int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) +/* + * Copy memory from HSA to kernel memory (not reentrant): + * + * @dest: Kernel or user buffer where memory should be copied to + * @src: Start address within HSA where data should be copied + * @count: Size of buffer, which should be copied + */ +int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) { return memcpy_hsa(dest, src, count, TO_KERNEL); } -- cgit v1.2.3-59-g8ed1b From 019d6bec6d2842729c477f433b2330e9f52c0f1a Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 12 Oct 2015 10:51:54 +0200 Subject: s390/zcore: simplify memcpy_hsa Replace the three part copy logic int memcpy_hsa with a single loop around sclp_sdias_copy with appropriate offset and size calculations, and inline memcpy_hsa into memcpy_hsa_user and memcpy_hsa_kernel. Acked-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- drivers/s390/char/zcore.c | 101 +++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 68 deletions(-) diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 4fa455787a77..7d94c696c38b 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -34,8 +34,6 @@ #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) -#define TO_USER 1 -#define TO_KERNEL 0 #define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */ enum arch_id { @@ -56,88 +54,38 @@ static struct dentry *zcore_reipl_file; static struct dentry *zcore_hsa_file; static struct ipl_parameter_block *ipl_block; +static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE); + /* - * Copy memory from HSA to kernel or user memory (not reentrant): + * Copy memory from HSA to user memory (not reentrant): * - * @dest: Kernel or user buffer where memory should be copied to + * @dest: User buffer where memory should be copied to * @src: Start address within HSA where data should be copied * @count: Size of buffer, which should be copied - * @mode: Either TO_KERNEL or TO_USER */ -static int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode) +int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) { - int offs, blk_num; - static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); + unsigned long offset, bytes; if (!hsa_available) return -ENODATA; - if (count == 0) - return 0; - - /* copy first block */ - offs = 0; - if ((src % PAGE_SIZE) != 0) { - blk_num = src / PAGE_SIZE + 2; - if (sclp_sdias_copy(buf, blk_num, 1)) { - TRACE("sclp_sdias_copy() failed\n"); - return -EIO; - } - offs = min((PAGE_SIZE - (src % PAGE_SIZE)), count); - if (mode == TO_USER) { - if (copy_to_user((__force __user void*) dest, - buf + (src % PAGE_SIZE), offs)) - return -EFAULT; - } else - memcpy(dest, buf + (src % PAGE_SIZE), offs); - } - if (offs == count) - goto out; - /* copy middle */ - for (; (offs + PAGE_SIZE) <= count; offs += PAGE_SIZE) { - blk_num = (src + offs) / PAGE_SIZE + 2; - if (sclp_sdias_copy(buf, blk_num, 1)) { + while (count) { + if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) { TRACE("sclp_sdias_copy() failed\n"); return -EIO; } - if (mode == TO_USER) { - if (copy_to_user((__force __user void*) dest + offs, - buf, PAGE_SIZE)) - return -EFAULT; - } else - memcpy(dest + offs, buf, PAGE_SIZE); - } - if (offs == count) - goto out; - - /* copy last block */ - blk_num = (src + offs) / PAGE_SIZE + 2; - if (sclp_sdias_copy(buf, blk_num, 1)) { - TRACE("sclp_sdias_copy() failed\n"); - return -EIO; - } - if (mode == TO_USER) { - if (copy_to_user((__force __user void*) dest + offs, buf, - count - offs)) + offset = src % PAGE_SIZE; + bytes = min(PAGE_SIZE - offset, count); + if (copy_to_user(dest, hsa_buf + offset, bytes)) return -EFAULT; - } else - memcpy(dest + offs, buf, count - offs); -out: + src += bytes; + dest += bytes; + count -= bytes; + } return 0; } -/* - * Copy memory from HSA to user memory (not reentrant): - * - * @dest: Kernel or user buffer where memory should be copied to - * @src: Start address within HSA where data should be copied - * @count: Size of buffer, which should be copied - */ -int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) -{ - return memcpy_hsa((void __force *) dest, src, count, TO_USER); -} - /* * Copy memory from HSA to kernel memory (not reentrant): * @@ -147,7 +95,24 @@ int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) */ int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) { - return memcpy_hsa(dest, src, count, TO_KERNEL); + unsigned long offset, bytes; + + if (!hsa_available) + return -ENODATA; + + while (count) { + if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) { + TRACE("sclp_sdias_copy() failed\n"); + return -EIO; + } + offset = src % PAGE_SIZE; + bytes = min(PAGE_SIZE - offset, count); + memcpy(dest, hsa_buf + offset, bytes); + src += bytes; + dest += bytes; + count -= bytes; + } + return 0; } static int __init init_cpu_info(void) -- cgit v1.2.3-59-g8ed1b From d9a3a09af54d01ab8b0c320580f4f95328d4a7ac Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 23 Oct 2015 09:02:32 +0200 Subject: s390/kvm: remove dependency on struct save_area definition Replace the offsets based on the struct area_area with the offset constants from asm-offsets.c based on the struct _lowcore. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/asm-offsets.c | 1 + arch/s390/kvm/kvm-s390.c | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 9cd248f637c7..dc6c9c604543 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -181,6 +181,7 @@ int main(void) OFFSET(__LC_PSW_SAVE_AREA, _lowcore, psw_save_area); OFFSET(__LC_PREFIX_SAVE_AREA, _lowcore, prefixreg_save_area); OFFSET(__LC_FP_CREG_SAVE_AREA, _lowcore, fpt_creg_save_area); + OFFSET(__LC_TOD_PROGREG_SAVE_AREA, _lowcore, tod_progreg_save_area); OFFSET(__LC_CPU_TIMER_SAVE_AREA, _lowcore, cpu_timer_save_area); OFFSET(__LC_CLOCK_COMP_SAVE_AREA, _lowcore, clock_comp_save_area); OFFSET(__LC_AREGS_SAVE_AREA, _lowcore, access_regs_save_area); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 846589281b04..713a91a0622b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2270,37 +2270,37 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa) u64 clkcomp; int rc; + px = kvm_s390_get_prefix(vcpu); if (gpa == KVM_S390_STORE_STATUS_NOADDR) { if (write_guest_abs(vcpu, 163, &archmode, 1)) return -EFAULT; - gpa = SAVE_AREA_BASE; + gpa = 0; } else if (gpa == KVM_S390_STORE_STATUS_PREFIXED) { if (write_guest_real(vcpu, 163, &archmode, 1)) return -EFAULT; - gpa = kvm_s390_real_to_abs(vcpu, SAVE_AREA_BASE); - } - rc = write_guest_abs(vcpu, gpa + offsetof(struct save_area, fp_regs), + gpa = px; + } else + gpa -= __LC_FPREGS_SAVE_AREA; + rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA, vcpu->arch.guest_fpregs.fprs, 128); - rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, gp_regs), + rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA, vcpu->run->s.regs.gprs, 128); - rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, psw), + rc |= write_guest_abs(vcpu, gpa + __LC_PSW_SAVE_AREA, &vcpu->arch.sie_block->gpsw, 16); - px = kvm_s390_get_prefix(vcpu); - rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, pref_reg), + rc |= write_guest_abs(vcpu, gpa + __LC_PREFIX_SAVE_AREA, &px, 4); - rc |= write_guest_abs(vcpu, - gpa + offsetof(struct save_area, fp_ctrl_reg), + rc |= write_guest_abs(vcpu, gpa + __LC_FP_CREG_SAVE_AREA, &vcpu->arch.guest_fpregs.fpc, 4); - rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, tod_reg), + rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA, &vcpu->arch.sie_block->todpr, 4); - rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, timer), + rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA, &vcpu->arch.sie_block->cputm, 8); clkcomp = vcpu->arch.sie_block->ckc >> 8; - rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, clk_cmp), + rc |= write_guest_abs(vcpu, gpa + __LC_CLOCK_COMP_SAVE_AREA, &clkcomp, 8); - rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, acc_regs), + rc |= write_guest_abs(vcpu, gpa + __LC_AREGS_SAVE_AREA, &vcpu->run->s.regs.acrs, 64); - rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, ctrl_regs), + rc |= write_guest_abs(vcpu, gpa + __LC_CREGS_SAVE_AREA, &vcpu->arch.sie_block->gcr, 128); return rc ? -EFAULT : 0; } -- cgit v1.2.3-59-g8ed1b From f08b8414632c9f256e33f0a18104d8d5e103d204 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 23 Oct 2015 09:05:38 +0200 Subject: s390/dump: remove SAVE_AREA_BASE Replace the SAVE_AREA_BASE offset calculations in reipl.S with the assembler constant for the location of each register status area. Use __LC_FPREGS_SAVE_AREA instead of SAVE_AREA_BASE in the three remaining code locations and remove the definition of SAVE_AREA_BASE. Acked-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/asm-offsets.c | 1 - arch/s390/kernel/machine_kexec.c | 6 ++-- arch/s390/kernel/reipl.S | 65 ++++++++++++++++++++++------------------ arch/s390/kernel/smp.c | 4 +-- drivers/s390/char/zcore.c | 2 +- 5 files changed, 42 insertions(+), 36 deletions(-) diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index dc6c9c604543..ae7b565b6c4c 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -175,7 +175,6 @@ int main(void) /* hardware defined lowcore locations 0x1000 - 0x18ff */ OFFSET(__LC_VX_SAVE_AREA_ADDR, _lowcore, vector_save_area_addr); OFFSET(__LC_EXT_PARAMS2, _lowcore, ext_params2); - OFFSET(SAVE_AREA_BASE, _lowcore, floating_pt_save_area); OFFSET(__LC_FPREGS_SAVE_AREA, _lowcore, floating_pt_save_area); OFFSET(__LC_GPREGS_SAVE_AREA, _lowcore, gpregs_save_area); OFFSET(__LC_PSW_SAVE_AREA, _lowcore, psw_save_area); diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 991b16819b97..bf2cd699556f 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -44,11 +44,11 @@ static void setup_regs(void) int cpu, this_cpu; /* setup_regs is called with the prefix register = 0 */ - sa_0 = (struct save_area *) SAVE_AREA_BASE; + sa_0 = (struct save_area *) __LC_FPREGS_SAVE_AREA; /* Get status of this CPU out of absolute zero */ prefix = (unsigned long) S390_lowcore.prefixreg_save_area; - sa = (struct save_area *)(prefix + SAVE_AREA_BASE); + sa = (struct save_area *)(prefix + __LC_FPREGS_SAVE_AREA); memcpy(sa, sa_0, sizeof(struct save_area)); if (MACHINE_HAS_VX) { struct _lowcore *lc = (struct _lowcore *) prefix; @@ -63,7 +63,7 @@ static void setup_regs(void) if (smp_store_status(cpu)) continue; prefix = (unsigned long) S390_lowcore.prefixreg_save_area; - sa = (struct save_area *)(prefix + SAVE_AREA_BASE); + sa = (struct save_area *)(prefix + __LC_FPREGS_SAVE_AREA); memcpy(sa, sa_0, sizeof(struct save_area)); } } diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S index 52aab0bd84f8..b75a521e4fab 100644 --- a/arch/s390/kernel/reipl.S +++ b/arch/s390/kernel/reipl.S @@ -19,49 +19,56 @@ ENTRY(store_status) /* Save register one and load save area base */ stg %r1,__LC_SAVE_AREA_RESTART - lghi %r1,SAVE_AREA_BASE /* General purpose registers */ - stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - lg %r2,__LC_SAVE_AREA_RESTART - stg %r2,__LC_GPREGS_SAVE_AREA-SAVE_AREA_BASE+8(%r1) + lghi %r1,__LC_GPREGS_SAVE_AREA + stmg %r0,%r15,0(%r1) + mvc 8(8,%r1),__LC_SAVE_AREA_RESTART /* Control registers */ - stctg %c0,%c15,__LC_CREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) + lghi %r1,__LC_CREGS_SAVE_AREA + stctg %c0,%c15,0(%r1) /* Access registers */ - stam %a0,%a15,__LC_AREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) + lghi %r1,__LC_AREGS_SAVE_AREA + stam %a0,%a15,0(%r1) /* Floating point registers */ - std %f0, 0x00 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f1, 0x08 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f2, 0x10 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f3, 0x18 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f4, 0x20 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f5, 0x28 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f6, 0x30 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f7, 0x38 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f8, 0x40 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f9, 0x48 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f10,0x50 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f11,0x58 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f12,0x60 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f13,0x68 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f14,0x70 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) - std %f15,0x78 + __LC_FPREGS_SAVE_AREA-SAVE_AREA_BASE(%r1) + lghi %r1,__LC_FPREGS_SAVE_AREA + std %f0, 0x00(%r1) + std %f1, 0x08(%r1) + std %f2, 0x10(%r1) + std %f3, 0x18(%r1) + std %f4, 0x20(%r1) + std %f5, 0x28(%r1) + std %f6, 0x30(%r1) + std %f7, 0x38(%r1) + std %f8, 0x40(%r1) + std %f9, 0x48(%r1) + std %f10,0x50(%r1) + std %f11,0x58(%r1) + std %f12,0x60(%r1) + std %f13,0x68(%r1) + std %f14,0x70(%r1) + std %f15,0x78(%r1) /* Floating point control register */ - stfpc __LC_FP_CREG_SAVE_AREA-SAVE_AREA_BASE(%r1) + lghi %r1,__LC_FP_CREG_SAVE_AREA + stfpc 0(%r1) /* CPU timer */ - stpt __LC_CPU_TIMER_SAVE_AREA-SAVE_AREA_BASE(%r1) + lghi %r1,__LC_CPU_TIMER_SAVE_AREA + stpt 0(%r1) /* Saved prefix register */ + lghi %r1,__LC_PREFIX_SAVE_AREA larl %r2,dump_prefix_page - mvc __LC_PREFIX_SAVE_AREA-SAVE_AREA_BASE(4,%r1),0(%r2) + mvc 0(4,%r1),0(%r2) /* Clock comparator - seven bytes */ + lghi %r1,__LC_CLOCK_COMP_SAVE_AREA larl %r2,.Lclkcmp stckc 0(%r2) - mvc __LC_CLOCK_COMP_SAVE_AREA-SAVE_AREA_BASE + 1(7,%r1),1(%r2) + mvc 1(7,%r1),1(%r2) /* Program status word */ + lghi %r1,__LC_PSW_SAVE_AREA epsw %r2,%r3 - st %r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 0(%r1) - st %r3,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 4(%r1) + st %r2,0(%r1) + st %r3,4(%r1) larl %r2,store_status - stg %r2,__LC_PSW_SAVE_AREA-SAVE_AREA_BASE + 8(%r1) + stg %r2,8(%r1) br %r14 .section .bss diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 5e04acdc6290..d49a8cb404c2 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -546,7 +546,7 @@ static void __init __smp_store_cpu_state(struct save_area_ext *sa_ext, if (is_boot_cpu) { /* Copy the registers of the boot CPU. */ - copy_oldmem_kernel(&sa_ext->sa, (void *) SAVE_AREA_BASE, + copy_oldmem_kernel(&sa_ext->sa, (void *) __LC_FPREGS_SAVE_AREA, sizeof(sa_ext->sa)); if (MACHINE_HAS_VX) save_vx_regs_safe(sa_ext->vx_regs); @@ -554,7 +554,7 @@ static void __init __smp_store_cpu_state(struct save_area_ext *sa_ext, } /* Get the registers of a non-boot cpu. */ __pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL); - memcpy_real(&sa_ext->sa, lc + SAVE_AREA_BASE, sizeof(sa_ext->sa)); + memcpy_real(&sa_ext->sa, lc + __LC_FPREGS_SAVE_AREA, sizeof(sa_ext->sa)); if (!MACHINE_HAS_VX) return; /* Get the VX registers */ diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 7d94c696c38b..087da775c359 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -124,7 +124,7 @@ static int __init init_cpu_info(void) sa_ext = dump_save_areas.areas[0]; if (!sa_ext) return -ENOMEM; - if (memcpy_hsa_kernel(&sa_ext->sa, SAVE_AREA_BASE, + if (memcpy_hsa_kernel(&sa_ext->sa, __LC_FPREGS_SAVE_AREA, sizeof(struct save_area)) < 0) { TRACE("could not copy from HSA\n"); return -EIO; -- cgit v1.2.3-59-g8ed1b From 1a36a39e225d3558fb3776a3d3d7736cf1ec9f60 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Oct 2015 10:28:26 +0100 Subject: s390/dump: rework CPU register dump code To collect the CPU registers of the crashed system allocated a single page with memblock_alloc_base and use it as a copy buffer. Replace the stop-and-store-status sigp with a store-status-at-address sigp in smp_save_dump_cpus() and smp_store_status(). In both cases the target CPU is already stopped and store-status-at-address avoids the detour via the absolute zero page. For kexec simplify s390_reset_system and call store_status() before the prefix register of the boot CPU has been set to zero. Use STPX to store the prefix register and remove dump_prefix_page. Acked-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/fpu/internal.h | 10 +--- arch/s390/include/asm/ipl.h | 3 +- arch/s390/include/asm/reset.h | 3 +- arch/s390/include/asm/smp.h | 2 +- arch/s390/kernel/early.c | 9 +++ arch/s390/kernel/ipl.c | 17 +----- arch/s390/kernel/machine_kexec.c | 104 ++++++++++++++++++-------------- arch/s390/kernel/reipl.S | 37 ++++++------ arch/s390/kernel/setup.c | 2 + arch/s390/kernel/smp.c | 112 +++++++++++++++++++---------------- drivers/s390/char/zcore.c | 2 - drivers/s390/cio/cio.c | 2 +- 12 files changed, 158 insertions(+), 145 deletions(-) diff --git a/arch/s390/include/asm/fpu/internal.h b/arch/s390/include/asm/fpu/internal.h index 2559b16da525..ea91ddfe54eb 100644 --- a/arch/s390/include/asm/fpu/internal.h +++ b/arch/s390/include/asm/fpu/internal.h @@ -12,21 +12,13 @@ #include #include -static inline void save_vx_regs_safe(__vector128 *vxrs) +static inline void save_vx_regs(__vector128 *vxrs) { - unsigned long cr0, flags; - - flags = arch_local_irq_save(); - __ctl_store(cr0, 0, 0); - __ctl_set_bit(0, 17); - __ctl_set_bit(0, 18); asm volatile( " la 1,%0\n" " .word 0xe70f,0x1000,0x003e\n" /* vstm 0,15,0(1) */ " .word 0xe70f,0x1100,0x0c3e\n" /* vstm 16,31,256(1) */ : "=Q" (*(struct vx_array *) vxrs) : : "1"); - __ctl_load(cr0, 0, 0); - arch_local_irq_restore(flags); } static inline void convert_vx_to_fp(freg_t *fprs, __vector128 *vxrs) diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h index 86634e71b69f..1dc55db8cd81 100644 --- a/arch/s390/include/asm/ipl.h +++ b/arch/s390/include/asm/ipl.h @@ -87,7 +87,6 @@ struct ipl_parameter_block { * IPL validity flags */ extern u32 ipl_flags; -extern u32 dump_prefix_page; struct dump_save_areas { struct save_area_ext **areas; @@ -176,7 +175,7 @@ enum diag308_rc { extern int diag308(unsigned long subcode, void *addr); extern void diag308_reset(void); -extern void store_status(void); +extern void store_status(void (*fn)(void *), void *data); extern void lgr_info_log(void); #endif /* _ASM_S390_IPL_H */ diff --git a/arch/s390/include/asm/reset.h b/arch/s390/include/asm/reset.h index 72786067b300..fe11fa88a0e0 100644 --- a/arch/s390/include/asm/reset.h +++ b/arch/s390/include/asm/reset.h @@ -15,6 +15,5 @@ struct reset_call { extern void register_reset_call(struct reset_call *reset); extern void unregister_reset_call(struct reset_call *reset); -extern void s390_reset_system(void (*fn_pre)(void), - void (*fn_post)(void *), void *data); +extern void s390_reset_system(void); #endif /* _ASM_S390_RESET_H */ diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index 5df26b11cf47..0cc383b9be7f 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -18,6 +18,7 @@ extern struct mutex smp_cpu_state_mutex; extern unsigned int smp_cpu_mt_shift; extern unsigned int smp_cpu_mtid; +extern __vector128 __initdata boot_cpu_vector_save_area[__NUM_VXRS]; extern int __cpu_up(unsigned int cpu, struct task_struct *tidle); @@ -55,7 +56,6 @@ static inline int smp_store_status(int cpu) { return 0; } static inline int smp_vcpu_scheduled(int cpu) { return 1; } static inline void smp_yield_cpu(int cpu) { } static inline void smp_fill_possible_mask(void) { } -static inline void smp_save_dump_cpus(void) { } #endif /* CONFIG_SMP */ diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 3c31609df959..20a5caf6d981 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -335,6 +335,14 @@ static __init void detect_machine_facilities(void) } } +static inline void save_vector_registers(void) +{ +#ifdef CONFIG_CRASH_DUMP + if (test_facility(129)) + save_vx_regs(boot_cpu_vector_save_area); +#endif +} + static int __init disable_vector_extension(char *str) { S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX; @@ -451,6 +459,7 @@ void __init startup_init(void) detect_diag9c(); detect_diag44(); detect_machine_facilities(); + save_vector_registers(); setup_topology(); sclp_early_detect(); lockdep_on(); diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index b1f0a90f933b..26d58cf72573 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -2039,10 +2039,7 @@ static void do_reset_calls(void) reset->fn(); } -u32 dump_prefix_page; - -void s390_reset_system(void (*fn_pre)(void), - void (*fn_post)(void *), void *data) +void s390_reset_system(void) { struct _lowcore *lc; @@ -2051,9 +2048,6 @@ void s390_reset_system(void (*fn_pre)(void), /* Stack for interrupt/machine check handler */ lc->panic_stack = S390_lowcore.panic_stack; - /* Save prefix page address for dump case */ - dump_prefix_page = (u32)(unsigned long) lc; - /* Disable prefixing */ set_prefix(0); @@ -2077,14 +2071,5 @@ void s390_reset_system(void (*fn_pre)(void), S390_lowcore.subchannel_id = 0; S390_lowcore.subchannel_nr = 0; - /* Store status at absolute zero */ - store_status(); - - /* Call function before reset */ - if (fn_pre) - fn_pre(); do_reset_calls(); - /* Call function after reset */ - if (fn_post) - fn_post(data); } diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index bf2cd699556f..2f1b7217c25c 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -34,40 +34,6 @@ extern const unsigned long long relocate_kernel_len; #ifdef CONFIG_CRASH_DUMP -/* - * Initialize CPU ELF notes - */ -static void setup_regs(void) -{ - struct save_area *sa, *sa_0; - unsigned long prefix; - int cpu, this_cpu; - - /* setup_regs is called with the prefix register = 0 */ - sa_0 = (struct save_area *) __LC_FPREGS_SAVE_AREA; - - /* Get status of this CPU out of absolute zero */ - prefix = (unsigned long) S390_lowcore.prefixreg_save_area; - sa = (struct save_area *)(prefix + __LC_FPREGS_SAVE_AREA); - memcpy(sa, sa_0, sizeof(struct save_area)); - if (MACHINE_HAS_VX) { - struct _lowcore *lc = (struct _lowcore *) prefix; - save_vx_regs_safe((void *) lc->vector_save_area_addr); - } - - /* Get status of the other CPUs */ - this_cpu = smp_find_processor_id(stap()); - for_each_online_cpu(cpu) { - if (cpu == this_cpu) - continue; - if (smp_store_status(cpu)) - continue; - prefix = (unsigned long) S390_lowcore.prefixreg_save_area; - sa = (struct save_area *)(prefix + __LC_FPREGS_SAVE_AREA); - memcpy(sa, sa_0, sizeof(struct save_area)); - } -} - /* * PM notifier callback for kdump */ @@ -99,14 +65,66 @@ static int __init machine_kdump_pm_init(void) arch_initcall(machine_kdump_pm_init); /* - * Start kdump: We expect here that a store status has been done on our CPU + * Reset the system, copy boot CPU registers to absolute zero, + * and jump to the kdump image */ static void __do_machine_kdump(void *image) { - int (*start_kdump)(int) = (void *)((struct kimage *) image)->start; + int (*start_kdump)(int); + unsigned long prefix; + + /* store_status() saved the prefix register to lowcore */ + prefix = (unsigned long) S390_lowcore.prefixreg_save_area; + + /* Now do the reset */ + s390_reset_system(); + + /* + * Copy dump CPU store status info to absolute zero. + * This need to be done *after* s390_reset_system set the + * prefix register of this CPU to zero + */ + memcpy((void *) __LC_FPREGS_SAVE_AREA, + (void *)(prefix + __LC_FPREGS_SAVE_AREA), 512); __load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA); + start_kdump = (void *)((struct kimage *) image)->start; start_kdump(1); + + /* Die if start_kdump returns */ + disabled_wait((unsigned long) __builtin_return_address(0)); +} + +/* + * Start kdump: create a LGR log entry, store status of all CPUs and + * branch to __do_machine_kdump. + */ +static noinline void __machine_kdump(void *image) +{ + int this_cpu, cpu; + + lgr_info_log(); + /* Get status of the other CPUs */ + this_cpu = smp_find_processor_id(stap()); + for_each_online_cpu(cpu) { + if (cpu == this_cpu) + continue; + if (smp_store_status(cpu)) + continue; + } + /* Store status of the boot CPU */ + if (MACHINE_HAS_VX) + save_vx_regs((void *) &S390_lowcore.vector_save_area); + /* + * To create a good backchain for this CPU in the dump store_status + * is passed the address of a function. The address is saved into + * the PSW save area of the boot CPU and the function is invoked as + * a tail call of store_status. The backchain in the dump will look + * like this: + * restart_int_handler -> __machine_kexec -> __do_machine_kdump + * The call to store_status() will not return. + */ + store_status(__do_machine_kdump, image); } #endif @@ -229,10 +247,14 @@ static void __do_machine_kexec(void *data) relocate_kernel_t data_mover; struct kimage *image = data; + s390_reset_system(); data_mover = (relocate_kernel_t) page_to_phys(image->control_code_page); /* Call the moving routine */ (*data_mover)(&image->head, image->start); + + /* Die if kexec returns */ + disabled_wait((unsigned long) __builtin_return_address(0)); } /* @@ -245,14 +267,10 @@ static void __machine_kexec(void *data) tracing_off(); debug_locks_off(); #ifdef CONFIG_CRASH_DUMP - if (((struct kimage *) data)->type == KEXEC_TYPE_CRASH) { - - lgr_info_log(); - s390_reset_system(setup_regs, __do_machine_kdump, data); - } else + if (((struct kimage *) data)->type == KEXEC_TYPE_CRASH) + __machine_kdump(data); #endif - s390_reset_system(NULL, __do_machine_kexec, data); - disabled_wait((unsigned long) __builtin_return_address(0)); + __do_machine_kexec(data); } /* diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S index b75a521e4fab..89ea8c213d82 100644 --- a/arch/s390/kernel/reipl.S +++ b/arch/s390/kernel/reipl.S @@ -9,12 +9,11 @@ #include # -# store_status +# Issue "store status" for the current CPU to its prefix page +# and call passed function afterwards # -# Prerequisites to run this function: -# - Prefix register is set to zero -# - Original prefix register is stored in "dump_prefix_page" -# - Lowcore protection is off +# r2 = Function to be called after store status +# r3 = Parameter for function # ENTRY(store_status) /* Save register one and load save area base */ @@ -53,23 +52,23 @@ ENTRY(store_status) /* CPU timer */ lghi %r1,__LC_CPU_TIMER_SAVE_AREA stpt 0(%r1) - /* Saved prefix register */ + /* Store prefix register */ lghi %r1,__LC_PREFIX_SAVE_AREA - larl %r2,dump_prefix_page - mvc 0(4,%r1),0(%r2) + stpx 0(%r1) /* Clock comparator - seven bytes */ lghi %r1,__LC_CLOCK_COMP_SAVE_AREA - larl %r2,.Lclkcmp - stckc 0(%r2) - mvc 1(7,%r1),1(%r2) + larl %r4,.Lclkcmp + stckc 0(%r4) + mvc 1(7,%r1),1(%r4) /* Program status word */ lghi %r1,__LC_PSW_SAVE_AREA - epsw %r2,%r3 - st %r2,0(%r1) - st %r3,4(%r1) - larl %r2,store_status + epsw %r4,%r5 + st %r4,0(%r1) + st %r5,4(%r1) stg %r2,8(%r1) - br %r14 + lgr %r1,%r2 + lgr %r2,%r3 + br %r1 .section .bss .align 8 @@ -84,9 +83,11 @@ ENTRY(store_status) ENTRY(do_reipl_asm) basr %r13,0 .Lpg0: lpswe .Lnewpsw-.Lpg0(%r13) -.Lpg1: brasl %r14,store_status +.Lpg1: lgr %r3,%r2 + larl %r2,.Lstatus + brasl %r14,store_status - lctlg %c6,%c6,.Lall-.Lpg0(%r13) +.Lstatus: lctlg %c6,%c6,.Lall-.Lpg0(%r13) lgr %r1,%r2 mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13) stsch .Lschib-.Lpg0(%r13) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 8f5107d6ebb3..22756bb0819e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -865,11 +865,13 @@ void __init setup_arch(char **cmdline_p) check_initrd(); reserve_crashkernel(); +#ifdef CONFIG_CRASH_DUMP /* * Be aware that smp_save_dump_cpus() triggers a system reset. * Therefore CPU and device initialization should be done afterwards. */ smp_save_dump_cpus(); +#endif setup_resources(); setup_vmcoreinfo(); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index d49a8cb404c2..2a69077d482c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -80,6 +80,10 @@ EXPORT_SYMBOL(smp_cpu_mt_shift); unsigned int smp_cpu_mtid; EXPORT_SYMBOL(smp_cpu_mtid); +#ifdef CONFIG_CRASH_DUMP +__vector128 __initdata boot_cpu_vector_save_area[__NUM_VXRS]; +#endif + static unsigned int smp_max_threads __initdata = -1U; static int __init early_nosmt(char *s) @@ -105,8 +109,7 @@ DEFINE_MUTEX(smp_cpu_state_mutex); /* * Signal processor helper functions. */ -static inline int __pcpu_sigp_relax(u16 addr, u8 order, unsigned long parm, - u32 *status) +static inline int __pcpu_sigp_relax(u16 addr, u8 order, unsigned long parm) { int cc; @@ -538,53 +541,24 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); #ifdef CONFIG_CRASH_DUMP -static void __init __smp_store_cpu_state(struct save_area_ext *sa_ext, - u16 address, int is_boot_cpu) -{ - void *lc = (void *)(unsigned long) store_prefix(); - unsigned long vx_sa; - - if (is_boot_cpu) { - /* Copy the registers of the boot CPU. */ - copy_oldmem_kernel(&sa_ext->sa, (void *) __LC_FPREGS_SAVE_AREA, - sizeof(sa_ext->sa)); - if (MACHINE_HAS_VX) - save_vx_regs_safe(sa_ext->vx_regs); - return; - } - /* Get the registers of a non-boot cpu. */ - __pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL); - memcpy_real(&sa_ext->sa, lc + __LC_FPREGS_SAVE_AREA, sizeof(sa_ext->sa)); - if (!MACHINE_HAS_VX) - return; - /* Get the VX registers */ - vx_sa = memblock_alloc(PAGE_SIZE, PAGE_SIZE); - if (!vx_sa) - panic("could not allocate memory for VX save area\n"); - __pcpu_sigp_relax(address, SIGP_STORE_ADDITIONAL_STATUS, vx_sa, NULL); - memcpy(sa_ext->vx_regs, (void *) vx_sa, sizeof(sa_ext->vx_regs)); - memblock_free(vx_sa, PAGE_SIZE); -} - int smp_store_status(int cpu) { - unsigned long vx_sa; - struct pcpu *pcpu; + struct pcpu *pcpu = pcpu_devices + cpu; + unsigned long pa; - pcpu = pcpu_devices + cpu; - if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS, - 0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED) + pa = __pa(&pcpu->lowcore->floating_pt_save_area); + if (__pcpu_sigp_relax(pcpu->address, SIGP_STORE_STATUS_AT_ADDRESS, + pa) != SIGP_CC_ORDER_CODE_ACCEPTED) return -EIO; if (!MACHINE_HAS_VX) return 0; - vx_sa = __pa(pcpu->lowcore->vector_save_area_addr); - __pcpu_sigp_relax(pcpu->address, SIGP_STORE_ADDITIONAL_STATUS, - vx_sa, NULL); + pa = __pa(pcpu->lowcore->vector_save_area_addr); + if (__pcpu_sigp_relax(pcpu->address, SIGP_STORE_ADDITIONAL_STATUS, + pa) != SIGP_CC_ORDER_CODE_ACCEPTED) + return -EIO; return 0; } -#endif /* CONFIG_CRASH_DUMP */ - /* * Collect CPU state of the previous, crashed system. * There are four cases: @@ -593,7 +567,7 @@ int smp_store_status(int cpu) * The state for all CPUs except the boot CPU needs to be collected * with sigp stop-and-store-status. The boot CPU state is located in * the absolute lowcore of the memory stored in the HSA. The zcore code - * will allocate the save area and copy the boot CPU state from the HSA. + * will copy the boot CPU state from the HSA. * 2) stand-alone kdump for SCSI (zfcp dump with swapped memory) * condition: OLDMEM_BASE != NULL && ipl_info.type == IPL_TYPE_FCP_DUMP * The state for all CPUs except the boot CPU needs to be collected @@ -611,21 +585,49 @@ int smp_store_status(int cpu) * This case does not exist for s390 anymore, setup_arch explicitly * deactivates the elfcorehdr= kernel parameter */ +static __init void smp_save_cpu_vxrs(struct save_area_ext *sa_ext, u16 addr, + bool is_boot_cpu, unsigned long page) +{ + __vector128 *vxrs = (__vector128 *) page; + + if (is_boot_cpu) + vxrs = boot_cpu_vector_save_area; + else + __pcpu_sigp_relax(addr, SIGP_STORE_ADDITIONAL_STATUS, page); + memcpy(&sa_ext->vx_regs, vxrs, sizeof(sa_ext->vx_regs)); +} + +static __init void smp_save_cpu_regs(struct save_area_ext *sa_ext, u16 addr, + bool is_boot_cpu, unsigned long page) +{ + void *regs = (void *) page; + + if (is_boot_cpu) + copy_oldmem_kernel(regs, (void *) __LC_FPREGS_SAVE_AREA, 512); + else + __pcpu_sigp_relax(addr, SIGP_STORE_STATUS_AT_ADDRESS, page); + memcpy(&sa_ext->sa, regs, sizeof(sa_ext->sa)); +} + void __init smp_save_dump_cpus(void) { -#ifdef CONFIG_CRASH_DUMP int addr, cpu, boot_cpu_addr, max_cpu_addr; struct save_area_ext *sa_ext; + unsigned long page; bool is_boot_cpu; if (!(OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP)) /* No previous system present, normal boot. */ return; + /* Allocate a page as dumping area for the store status sigps */ + page = memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, 1UL << 31); + if (!page) + panic("could not allocate memory for save area\n"); /* Set multi-threading state to the previous system. */ pcpu_set_smt(sclp.mtid_prev); max_cpu_addr = SCLP_MAX_CORES << sclp.mtid_prev; for (cpu = 0, addr = 0; addr <= max_cpu_addr; addr++) { - if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0, NULL) == + if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0) == SIGP_CC_NOT_OPERATIONAL) continue; cpu += 1; @@ -634,7 +636,7 @@ void __init smp_save_dump_cpus(void) dump_save_areas.count = cpu; boot_cpu_addr = stap(); for (cpu = 0, addr = 0; addr <= max_cpu_addr; addr++) { - if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0, NULL) == + if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0) == SIGP_CC_NOT_OPERATIONAL) continue; sa_ext = (void *) memblock_alloc(sizeof(*sa_ext), 8); @@ -643,16 +645,24 @@ void __init smp_save_dump_cpus(void) panic("could not allocate memory for save area\n"); is_boot_cpu = (addr == boot_cpu_addr); cpu += 1; - if (is_boot_cpu && !OLDMEM_BASE) - /* Skip boot CPU for standard zfcp dump. */ - continue; - /* Get state for this CPU. */ - __smp_store_cpu_state(sa_ext, addr, is_boot_cpu); + if (MACHINE_HAS_VX) + /* Get the vector registers */ + smp_save_cpu_vxrs(sa_ext, addr, is_boot_cpu, page); + /* + * For a zfcp dump OLDMEM_BASE == NULL and the registers + * of the boot CPU are stored in the HSA. To retrieve + * these registers an SCLP request is required which is + * done by drivers/s390/char/zcore.c:init_cpu_info() + */ + if (!is_boot_cpu || OLDMEM_BASE) + /* Get the CPU registers */ + smp_save_cpu_regs(sa_ext, addr, is_boot_cpu, page); } + memblock_free(page, PAGE_SIZE); diag308_reset(); pcpu_set_smt(0); -#endif /* CONFIG_CRASH_DUMP */ } +#endif /* CONFIG_CRASH_DUMP */ void smp_cpu_set_polarization(int cpu, int val) { @@ -676,7 +686,7 @@ static struct sclp_core_info *smp_get_core_info(void) for (address = 0; address < (SCLP_MAX_CORES << smp_cpu_mt_shift); address += (1U << smp_cpu_mt_shift)) { - if (__pcpu_sigp_relax(address, SIGP_SENSE, 0, NULL) == + if (__pcpu_sigp_relax(address, SIGP_SENSE, 0) == SIGP_CC_NOT_OPERATIONAL) continue; info->core[info->configured].core_id = diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 087da775c359..bed191a39c5b 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -129,8 +129,6 @@ static int __init init_cpu_info(void) TRACE("could not copy from HSA\n"); return -EIO; } - if (MACHINE_HAS_VX) - save_vx_regs_safe(sa_ext->vx_regs); return 0; } diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 690b8547e828..e0d02952a7f4 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -917,7 +917,7 @@ void reipl_ccw_dev(struct ccw_dev_id *devid) { struct subchannel_id uninitialized_var(schid); - s390_reset_system(NULL, NULL, NULL); + s390_reset_system(); if (reipl_find_schid(devid, &schid) != 0) panic("IPL Device not found\n"); do_reipl_asm(*((__u32*)&schid)); -- cgit v1.2.3-59-g8ed1b From 1a2c5840acf9f657c9b580d4ee12a4c9db3429cb Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Oct 2015 10:59:15 +0100 Subject: s390/dump: cleanup CPU save area handling Introduce save_area_alloc(), save_area_boot_cpu(), save_area_add_regs() and save_area_add_vxrs to deal with storing the CPU state in case of a system dump. Remove struct save_area and save_area_ext, and create a new struct save_area as a local definition to arch/s390/kernel/crash_dump.c. Copy each individual field from the hardware status area to the save area, storing the minimum of required data. Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ipl.h | 11 +- arch/s390/include/asm/lowcore.h | 21 ---- arch/s390/kernel/crash_dump.c | 263 ++++++++++++++++++---------------------- arch/s390/kernel/smp.c | 37 +++--- drivers/s390/char/zcore.c | 11 +- 5 files changed, 145 insertions(+), 198 deletions(-) diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h index 1dc55db8cd81..6fc44dca193e 100644 --- a/arch/s390/include/asm/ipl.h +++ b/arch/s390/include/asm/ipl.h @@ -88,12 +88,11 @@ struct ipl_parameter_block { */ extern u32 ipl_flags; -struct dump_save_areas { - struct save_area_ext **areas; - int count; -}; - -extern struct dump_save_areas dump_save_areas; +struct save_area; +struct save_area * __init save_area_alloc(bool is_boot_cpu); +struct save_area * __init save_area_boot_cpu(void); +void __init save_area_add_regs(struct save_area *, void *regs); +void __init save_area_add_vxrs(struct save_area *, __vector128 *vxrs); extern void do_reipl(void); extern void do_halt(void); diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index afe1cfebf1a4..5dbbf199ba2e 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -16,27 +16,6 @@ #define LC_ORDER 1 #define LC_PAGES 2 -struct save_area { - u64 fp_regs[16]; - u64 gp_regs[16]; - u8 psw[16]; - u8 pad1[8]; - u32 pref_reg; - u32 fp_ctrl_reg; - u8 pad2[4]; - u32 tod_reg; - u64 timer; - u64 clk_cmp; - u8 pad3[8]; - u32 acc_regs[16]; - u64 ctrl_regs[16]; -} __packed; - -struct save_area_ext { - struct save_area sa; - __vector128 vx_regs[32]; -}; - struct _lowcore { __u8 pad_0x0000[0x0014-0x0000]; /* 0x0000 */ __u32 ipl_parmblock_ptr; /* 0x0014 */ diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 0d59c0705c4f..823ed6ab53c8 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,84 @@ static struct memblock_type oldmem_type = { .regions = &oldmem_region, }; -struct dump_save_areas dump_save_areas; +struct save_area { + struct list_head list; + u64 psw[2]; + u64 ctrs[16]; + u64 gprs[16]; + u32 acrs[16]; + u64 fprs[16]; + u32 fpc; + u32 prefix; + u64 todpreg; + u64 timer; + u64 todcmp; + u64 vxrs_low[16]; + __vector128 vxrs_high[16]; +}; + +static LIST_HEAD(dump_save_areas); + +/* + * Allocate a save area + */ +struct save_area * __init save_area_alloc(bool is_boot_cpu) +{ + struct save_area *sa; + + sa = (void *) memblock_alloc(sizeof(*sa), 8); + if (!sa) + return NULL; + if (is_boot_cpu) + list_add(&sa->list, &dump_save_areas); + else + list_add_tail(&sa->list, &dump_save_areas); + return sa; +} + +/* + * Return the address of the save area for the boot CPU + */ +struct save_area * __init save_area_boot_cpu(void) +{ + if (list_empty(&dump_save_areas)) + return NULL; + return list_first_entry(&dump_save_areas, struct save_area, list); +} + +/* + * Copy CPU registers into the save area + */ +void __init save_area_add_regs(struct save_area *sa, void *regs) +{ + struct _lowcore *lc; + + lc = (struct _lowcore *)(regs - __LC_FPREGS_SAVE_AREA); + memcpy(&sa->psw, &lc->psw_save_area, sizeof(sa->psw)); + memcpy(&sa->ctrs, &lc->cregs_save_area, sizeof(sa->ctrs)); + memcpy(&sa->gprs, &lc->gpregs_save_area, sizeof(sa->gprs)); + memcpy(&sa->acrs, &lc->access_regs_save_area, sizeof(sa->acrs)); + memcpy(&sa->fprs, &lc->floating_pt_save_area, sizeof(sa->fprs)); + memcpy(&sa->fpc, &lc->fpt_creg_save_area, sizeof(sa->fpc)); + memcpy(&sa->prefix, &lc->prefixreg_save_area, sizeof(sa->prefix)); + memcpy(&sa->todpreg, &lc->tod_progreg_save_area, sizeof(sa->todpreg)); + memcpy(&sa->timer, &lc->cpu_timer_save_area, sizeof(sa->timer)); + memcpy(&sa->todcmp, &lc->clock_comp_save_area, sizeof(sa->todcmp)); +} + +/* + * Copy vector registers into the save area + */ +void __init save_area_add_vxrs(struct save_area *sa, __vector128 *vxrs) +{ + int i; + + /* Copy lower halves of vector registers 0-15 */ + for (i = 0; i < 16; i++) + memcpy(&sa->vxrs_low[i], &vxrs[i].u[2], 8); + /* Copy vector registers 16-31 */ + memcpy(sa->vxrs_high, vxrs + 16, 16 * sizeof(__vector128)); +} /* * Return physical address for virtual address @@ -232,8 +310,8 @@ static void *kzalloc_panic(int len) /* * Initialize ELF note */ -static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len, - const char *name) +static void *nt_init_name(void *buf, Elf64_Word type, void *desc, int d_len, + const char *name) { Elf64_Nhdr *note; u64 len; @@ -253,137 +331,42 @@ static void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len, return PTR_ADD(buf, len); } -/* - * Initialize prstatus note - */ -static void *nt_prstatus(void *ptr, struct save_area *sa) +static inline void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len) { - struct elf_prstatus nt_prstatus; - static int cpu_nr = 1; - - memset(&nt_prstatus, 0, sizeof(nt_prstatus)); - memcpy(&nt_prstatus.pr_reg.gprs, sa->gp_regs, sizeof(sa->gp_regs)); - memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw)); - memcpy(&nt_prstatus.pr_reg.acrs, sa->acc_regs, sizeof(sa->acc_regs)); - nt_prstatus.pr_pid = cpu_nr; - cpu_nr++; - - return nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus), - "CORE"); + return nt_init_name(buf, type, desc, d_len, KEXEC_CORE_NOTE_NAME); } /* - * Initialize fpregset (floating point) note + * Fill ELF notes for one CPU with save area registers */ -static void *nt_fpregset(void *ptr, struct save_area *sa) +static void *fill_cpu_elf_notes(void *ptr, int cpu, struct save_area *sa) { + struct elf_prstatus nt_prstatus; elf_fpregset_t nt_fpregset; + /* Prepare prstatus note */ + memset(&nt_prstatus, 0, sizeof(nt_prstatus)); + memcpy(&nt_prstatus.pr_reg.gprs, sa->gprs, sizeof(sa->gprs)); + memcpy(&nt_prstatus.pr_reg.psw, sa->psw, sizeof(sa->psw)); + memcpy(&nt_prstatus.pr_reg.acrs, sa->acrs, sizeof(sa->acrs)); + nt_prstatus.pr_pid = cpu; + /* Prepare fpregset (floating point) note */ memset(&nt_fpregset, 0, sizeof(nt_fpregset)); - memcpy(&nt_fpregset.fpc, &sa->fp_ctrl_reg, sizeof(sa->fp_ctrl_reg)); - memcpy(&nt_fpregset.fprs, &sa->fp_regs, sizeof(sa->fp_regs)); - - return nt_init(ptr, NT_PRFPREG, &nt_fpregset, sizeof(nt_fpregset), - "CORE"); -} - -/* - * Initialize timer note - */ -static void *nt_s390_timer(void *ptr, struct save_area *sa) -{ - return nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer), - KEXEC_CORE_NOTE_NAME); -} - -/* - * Initialize TOD clock comparator note - */ -static void *nt_s390_tod_cmp(void *ptr, struct save_area *sa) -{ - return nt_init(ptr, NT_S390_TODCMP, &sa->clk_cmp, - sizeof(sa->clk_cmp), KEXEC_CORE_NOTE_NAME); -} - -/* - * Initialize TOD programmable register note - */ -static void *nt_s390_tod_preg(void *ptr, struct save_area *sa) -{ - return nt_init(ptr, NT_S390_TODPREG, &sa->tod_reg, - sizeof(sa->tod_reg), KEXEC_CORE_NOTE_NAME); -} - -/* - * Initialize control register note - */ -static void *nt_s390_ctrs(void *ptr, struct save_area *sa) -{ - return nt_init(ptr, NT_S390_CTRS, &sa->ctrl_regs, - sizeof(sa->ctrl_regs), KEXEC_CORE_NOTE_NAME); -} - -/* - * Initialize prefix register note - */ -static void *nt_s390_prefix(void *ptr, struct save_area *sa) -{ - return nt_init(ptr, NT_S390_PREFIX, &sa->pref_reg, - sizeof(sa->pref_reg), KEXEC_CORE_NOTE_NAME); -} - -/* - * Initialize vxrs high note (full 128 bit VX registers 16-31) - */ -static void *nt_s390_vx_high(void *ptr, __vector128 *vx_regs) -{ - return nt_init(ptr, NT_S390_VXRS_HIGH, &vx_regs[16], - 16 * sizeof(__vector128), KEXEC_CORE_NOTE_NAME); -} - -/* - * Initialize vxrs low note (lower halves of VX registers 0-15) - */ -static void *nt_s390_vx_low(void *ptr, __vector128 *vx_regs) -{ - Elf64_Nhdr *note; - u64 len; - int i; - - note = (Elf64_Nhdr *)ptr; - note->n_namesz = strlen(KEXEC_CORE_NOTE_NAME) + 1; - note->n_descsz = 16 * 8; - note->n_type = NT_S390_VXRS_LOW; - len = sizeof(Elf64_Nhdr); - - memcpy(ptr + len, KEXEC_CORE_NOTE_NAME, note->n_namesz); - len = roundup(len + note->n_namesz, 4); - - ptr += len; - /* Copy lower halves of SIMD registers 0-15 */ - for (i = 0; i < 16; i++) { - memcpy(ptr, &vx_regs[i].u[2], 8); - ptr += 8; - } - return ptr; -} - -/* - * Fill ELF notes for one CPU with save area registers - */ -static void *fill_cpu_elf_notes(void *ptr, struct save_area *sa, - __vector128 *vx_regs) -{ - ptr = nt_prstatus(ptr, sa); - ptr = nt_fpregset(ptr, sa); - ptr = nt_s390_timer(ptr, sa); - ptr = nt_s390_tod_cmp(ptr, sa); - ptr = nt_s390_tod_preg(ptr, sa); - ptr = nt_s390_ctrs(ptr, sa); - ptr = nt_s390_prefix(ptr, sa); - if (MACHINE_HAS_VX && vx_regs) { - ptr = nt_s390_vx_low(ptr, vx_regs); - ptr = nt_s390_vx_high(ptr, vx_regs); + memcpy(&nt_fpregset.fpc, &sa->fpc, sizeof(sa->fpc)); + memcpy(&nt_fpregset.fprs, &sa->fprs, sizeof(sa->fprs)); + /* Create ELF notes for the CPU */ + ptr = nt_init(ptr, NT_PRSTATUS, &nt_prstatus, sizeof(nt_prstatus)); + ptr = nt_init(ptr, NT_PRFPREG, &nt_fpregset, sizeof(nt_fpregset)); + ptr = nt_init(ptr, NT_S390_TIMER, &sa->timer, sizeof(sa->timer)); + ptr = nt_init(ptr, NT_S390_TODCMP, &sa->todcmp, sizeof(sa->todcmp)); + ptr = nt_init(ptr, NT_S390_TODPREG, &sa->todpreg, sizeof(sa->todpreg)); + ptr = nt_init(ptr, NT_S390_CTRS, &sa->ctrs, sizeof(sa->ctrs)); + ptr = nt_init(ptr, NT_S390_PREFIX, &sa->prefix, sizeof(sa->prefix)); + if (MACHINE_HAS_VX) { + ptr = nt_init(ptr, NT_S390_VXRS_HIGH, + &sa->vxrs_high, sizeof(sa->vxrs_high)); + ptr = nt_init(ptr, NT_S390_VXRS_LOW, + &sa->vxrs_low, sizeof(sa->vxrs_low)); } return ptr; } @@ -398,8 +381,7 @@ static void *nt_prpsinfo(void *ptr) memset(&prpsinfo, 0, sizeof(prpsinfo)); prpsinfo.pr_sname = 'R'; strcpy(prpsinfo.pr_fname, "vmlinux"); - return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo), - KEXEC_CORE_NOTE_NAME); + return nt_init(ptr, NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo)); } /* @@ -441,7 +423,7 @@ static void *nt_vmcoreinfo(void *ptr) vmcoreinfo = get_vmcoreinfo_old(&size); if (!vmcoreinfo) return ptr; - return nt_init(ptr, 0, vmcoreinfo, size, "VMCOREINFO"); + return nt_init_name(ptr, 0, vmcoreinfo, size, "VMCOREINFO"); } /* @@ -470,13 +452,12 @@ static void *ehdr_init(Elf64_Ehdr *ehdr, int mem_chunk_cnt) */ static int get_cpu_cnt(void) { - int i, cpus = 0; + struct save_area *sa; + int cpus = 0; - for (i = 0; i < dump_save_areas.count; i++) { - if (dump_save_areas.areas[i]->sa.pref_reg == 0) - continue; - cpus++; - } + list_for_each_entry(sa, &dump_save_areas, list) + if (sa->prefix != 0) + cpus++; return cpus; } @@ -521,18 +502,16 @@ static void loads_init(Elf64_Phdr *phdr, u64 loads_offset) */ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset) { - struct save_area_ext *sa_ext; + struct save_area *sa; void *ptr_start = ptr; - int i; + int cpu; ptr = nt_prpsinfo(ptr); - for (i = 0; i < dump_save_areas.count; i++) { - sa_ext = dump_save_areas.areas[i]; - if (sa_ext->sa.pref_reg == 0) - continue; - ptr = fill_cpu_elf_notes(ptr, &sa_ext->sa, sa_ext->vx_regs); - } + cpu = 1; + list_for_each_entry(sa, &dump_save_areas, list) + if (sa->prefix != 0) + ptr = fill_cpu_elf_notes(ptr, cpu++, sa); ptr = nt_vmcoreinfo(ptr); memset(phdr, 0, sizeof(*phdr)); phdr->p_type = PT_NOTE; diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 2a69077d482c..9da95d8dfc62 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -585,7 +585,7 @@ int smp_store_status(int cpu) * This case does not exist for s390 anymore, setup_arch explicitly * deactivates the elfcorehdr= kernel parameter */ -static __init void smp_save_cpu_vxrs(struct save_area_ext *sa_ext, u16 addr, +static __init void smp_save_cpu_vxrs(struct save_area *sa, u16 addr, bool is_boot_cpu, unsigned long page) { __vector128 *vxrs = (__vector128 *) page; @@ -594,10 +594,10 @@ static __init void smp_save_cpu_vxrs(struct save_area_ext *sa_ext, u16 addr, vxrs = boot_cpu_vector_save_area; else __pcpu_sigp_relax(addr, SIGP_STORE_ADDITIONAL_STATUS, page); - memcpy(&sa_ext->vx_regs, vxrs, sizeof(sa_ext->vx_regs)); + save_area_add_vxrs(sa, vxrs); } -static __init void smp_save_cpu_regs(struct save_area_ext *sa_ext, u16 addr, +static __init void smp_save_cpu_regs(struct save_area *sa, u16 addr, bool is_boot_cpu, unsigned long page) { void *regs = (void *) page; @@ -606,13 +606,13 @@ static __init void smp_save_cpu_regs(struct save_area_ext *sa_ext, u16 addr, copy_oldmem_kernel(regs, (void *) __LC_FPREGS_SAVE_AREA, 512); else __pcpu_sigp_relax(addr, SIGP_STORE_STATUS_AT_ADDRESS, page); - memcpy(&sa_ext->sa, regs, sizeof(sa_ext->sa)); + save_area_add_regs(sa, regs); } void __init smp_save_dump_cpus(void) { - int addr, cpu, boot_cpu_addr, max_cpu_addr; - struct save_area_ext *sa_ext; + int addr, boot_cpu_addr, max_cpu_addr; + struct save_area *sa; unsigned long page; bool is_boot_cpu; @@ -625,29 +625,20 @@ void __init smp_save_dump_cpus(void) panic("could not allocate memory for save area\n"); /* Set multi-threading state to the previous system. */ pcpu_set_smt(sclp.mtid_prev); - max_cpu_addr = SCLP_MAX_CORES << sclp.mtid_prev; - for (cpu = 0, addr = 0; addr <= max_cpu_addr; addr++) { - if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0) == - SIGP_CC_NOT_OPERATIONAL) - continue; - cpu += 1; - } - dump_save_areas.areas = (void *)memblock_alloc(sizeof(void *) * cpu, 8); - dump_save_areas.count = cpu; boot_cpu_addr = stap(); - for (cpu = 0, addr = 0; addr <= max_cpu_addr; addr++) { + max_cpu_addr = SCLP_MAX_CORES << sclp.mtid_prev; + for (addr = 0; addr <= max_cpu_addr; addr++) { if (__pcpu_sigp_relax(addr, SIGP_SENSE, 0) == SIGP_CC_NOT_OPERATIONAL) continue; - sa_ext = (void *) memblock_alloc(sizeof(*sa_ext), 8); - dump_save_areas.areas[cpu] = sa_ext; - if (!sa_ext) - panic("could not allocate memory for save area\n"); is_boot_cpu = (addr == boot_cpu_addr); - cpu += 1; + /* Allocate save area */ + sa = save_area_alloc(is_boot_cpu); + if (!sa) + panic("could not allocate memory for save area\n"); if (MACHINE_HAS_VX) /* Get the vector registers */ - smp_save_cpu_vxrs(sa_ext, addr, is_boot_cpu, page); + smp_save_cpu_vxrs(sa, addr, is_boot_cpu, page); /* * For a zfcp dump OLDMEM_BASE == NULL and the registers * of the boot CPU are stored in the HSA. To retrieve @@ -656,7 +647,7 @@ void __init smp_save_dump_cpus(void) */ if (!is_boot_cpu || OLDMEM_BASE) /* Get the CPU registers */ - smp_save_cpu_regs(sa_ext, addr, is_boot_cpu, page); + smp_save_cpu_regs(sa, addr, is_boot_cpu, page); } memblock_free(page, PAGE_SIZE); diag308_reset(); diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index bed191a39c5b..5043ecfa1fbc 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -117,18 +117,17 @@ int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) static int __init init_cpu_info(void) { - struct save_area_ext *sa_ext; + struct save_area *sa; /* get info for boot cpu from lowcore, stored in the HSA */ - - sa_ext = dump_save_areas.areas[0]; - if (!sa_ext) + sa = save_area_boot_cpu(); + if (!sa) return -ENOMEM; - if (memcpy_hsa_kernel(&sa_ext->sa, __LC_FPREGS_SAVE_AREA, - sizeof(struct save_area)) < 0) { + if (memcpy_hsa_kernel(hsa_buf, __LC_FPREGS_SAVE_AREA, 512) < 0) { TRACE("could not copy from HSA\n"); return -EIO; } + save_area_add_regs(sa, hsa_buf); /* vx registers are saved in smp.c */ return 0; } -- cgit v1.2.3-59-g8ed1b From db1c45154a82195ad0b4d45d0e330ebac6883b70 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 12 Nov 2015 12:51:17 +0100 Subject: s390/spinlock: avoid diagnose loop The spinlock implementation calls the diagnose 0x9c / 0x44 immediately if the SIGP sense running reported the target CPU as not running. The diagnose 0x9c is a hint to the hypervisor to schedule the target CPU in preference to the source CPU that issued the diagnose. It can happen that on return from the diagnose the target CPU has not been scheduled yet, e.g. if the target logical CPU is on another physical CPU and the hypervisor did not want to migrate the logical CPU. Avoid the immediate repeat of the diagnose instruction, instead do the retry loop before the next invocation of diagnose 0x9c. Reviewed-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/lib/spinlock.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 427aa44b3505..0a68fe04a9e1 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -41,8 +41,9 @@ void arch_spin_lock_wait(arch_spinlock_t *lp) { unsigned int cpu = SPINLOCK_LOCKVAL; unsigned int owner; - int count; + int count, first_diag; + first_diag = 1; while (1) { owner = ACCESS_ONCE(lp->lock); /* Try to get the lock if it is free. */ @@ -51,9 +52,10 @@ void arch_spin_lock_wait(arch_spinlock_t *lp) return; continue; } - /* Check if the lock owner is running. */ - if (!smp_vcpu_scheduled(~owner)) { + /* First iteration: check if the lock owner is running. */ + if (first_diag && !smp_vcpu_scheduled(~owner)) { smp_yield_cpu(~owner); + first_diag = 0; continue; } /* Loop for a while on the lock value. */ @@ -67,10 +69,13 @@ void arch_spin_lock_wait(arch_spinlock_t *lp) continue; /* * For multiple layers of hypervisors, e.g. z/VM + LPAR - * yield the CPU if the lock is still unavailable. + * yield the CPU unconditionally. For LPAR rely on the + * sense running status. */ - if (!MACHINE_IS_LPAR) + if (!MACHINE_IS_LPAR || !smp_vcpu_scheduled(~owner)) { smp_yield_cpu(~owner); + first_diag = 0; + } } } EXPORT_SYMBOL(arch_spin_lock_wait); @@ -79,9 +84,10 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) { unsigned int cpu = SPINLOCK_LOCKVAL; unsigned int owner; - int count; + int count, first_diag; local_irq_restore(flags); + first_diag = 1; while (1) { owner = ACCESS_ONCE(lp->lock); /* Try to get the lock if it is free. */ @@ -92,8 +98,9 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) local_irq_restore(flags); } /* Check if the lock owner is running. */ - if (!smp_vcpu_scheduled(~owner)) { + if (first_diag && !smp_vcpu_scheduled(~owner)) { smp_yield_cpu(~owner); + first_diag = 0; continue; } /* Loop for a while on the lock value. */ @@ -107,10 +114,13 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) continue; /* * For multiple layers of hypervisors, e.g. z/VM + LPAR - * yield the CPU if the lock is still unavailable. + * yield the CPU unconditionally. For LPAR rely on the + * sense running status. */ - if (!MACHINE_IS_LPAR) + if (!MACHINE_IS_LPAR || !smp_vcpu_scheduled(~owner)) { smp_yield_cpu(~owner); + first_diag = 0; + } } } EXPORT_SYMBOL(arch_spin_lock_wait_flags); -- cgit v1.2.3-59-g8ed1b From 406123517b5b3cd5855774f80d685cf393c950f6 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 15 Oct 2015 10:47:18 +0200 Subject: s390: get_user_pages_fast() might sleep Let's annotate it correctly, so we directly get a warning if we ever were to use it in atomic/preempt_disable/spinlock environment. Acked-by: Heiko Carstens Signed-off-by: David Hildenbrand Signed-off-by: Martin Schwidefsky --- arch/s390/mm/gup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 12bbf0e8478f..21c74a71e2ab 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -233,6 +233,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, struct mm_struct *mm = current->mm; int nr, ret; + might_sleep(); start &= PAGE_MASK; nr = __get_user_pages_fast(start, nr_pages, write, pages); if (nr == nr_pages) -- cgit v1.2.3-59-g8ed1b From 69eea95c48857c9dfcac120d6acea43027627b28 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Mon, 16 Nov 2015 14:35:48 +0100 Subject: s390/pci_dma: fix DMA table corruption with > 4 TB main memory DMA addresses returned from map_page() are calculated by using an iommu bitmap plus a start_dma offset. The size of this bitmap is based on the main memory size. If we have more than (4 TB - start_dma) main memory, the DMA address calculation will also produce addresses > 4 TB. Such addresses cannot be inserted in the 3-level DMA page table, instead the entries modulo 4 TB will be overwritten. Fix this by restricting the iommu bitmap size to (4 TB - start_dma). Also set zdev->end_dma to the actual end address of the usable range, instead of the theoretical maximum as reported by the hardware, which fixes a sanity check in dma_map() and also the IOMMU API domain geometry aperture calculation. Signed-off-by: Gerald Schaefer Reviewed-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/pci_dma.h | 2 ++ arch/s390/pci/pci.c | 3 +-- arch/s390/pci/pci_dma.c | 19 ++++++++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/arch/s390/include/asm/pci_dma.h b/arch/s390/include/asm/pci_dma.h index 1aac41e83ea1..92df3eb8d14e 100644 --- a/arch/s390/include/asm/pci_dma.h +++ b/arch/s390/include/asm/pci_dma.h @@ -23,6 +23,8 @@ enum zpci_ioat_dtype { #define ZPCI_IOTA_FS_2G 2 #define ZPCI_KEY (PAGE_DEFAULT_KEY << 5) +#define ZPCI_TABLE_SIZE_RT (1UL << 42) + #define ZPCI_IOTA_STO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_ST) #define ZPCI_IOTA_RTTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RT) #define ZPCI_IOTA_RSTO_FLAG (ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RS) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 7ef12a3ace3a..11d4f277e9f6 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -701,8 +701,7 @@ static int zpci_restore(struct device *dev) goto out; zpci_map_resources(pdev); - zpci_register_ioat(zdev, 0, zdev->start_dma + PAGE_OFFSET, - zdev->start_dma + zdev->iommu_size - 1, + zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, (u64) zdev->dma_table); out: diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index d348f2c09a1e..3a40f718baef 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -458,7 +458,19 @@ int zpci_dma_init_device(struct zpci_dev *zdev) goto out_clean; } - zdev->iommu_size = (unsigned long) high_memory - PAGE_OFFSET; + /* + * Restrict the iommu bitmap size to the minimum of the following: + * - main memory size + * - 3-level pagetable address limit minus start_dma offset + * - DMA address range allowed by the hardware (clp query pci fn) + * + * Also set zdev->end_dma to the actual end address of the usable + * range, instead of the theoretical maximum as reported by hardware. + */ + zdev->iommu_size = min3((u64) high_memory, + ZPCI_TABLE_SIZE_RT - zdev->start_dma, + zdev->end_dma - zdev->start_dma + 1); + zdev->end_dma = zdev->start_dma + zdev->iommu_size - 1; zdev->iommu_pages = zdev->iommu_size >> PAGE_SHIFT; zdev->iommu_bitmap = vzalloc(zdev->iommu_pages / 8); if (!zdev->iommu_bitmap) { @@ -466,10 +478,7 @@ int zpci_dma_init_device(struct zpci_dev *zdev) goto out_reg; } - rc = zpci_register_ioat(zdev, - 0, - zdev->start_dma + PAGE_OFFSET, - zdev->start_dma + zdev->iommu_size - 1, + rc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, (u64) zdev->dma_table); if (rc) goto out_reg; -- cgit v1.2.3-59-g8ed1b From a6e975c5f8fd8652fc5ab754236ec155a228d452 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 16 Nov 2015 14:45:40 +0100 Subject: s390: Delete unnecessary checks before the function call "debug_unregister" The debug_unregister() function performs also input parameter validation. Thus the test around the calls is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc_sch.c | 3 +-- drivers/s390/cio/cio.c | 9 +++------ drivers/s390/cio/qdio_debug.c | 6 ++---- drivers/s390/crypto/zcrypt_api.c | 6 ++---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 213159dec89e..378c57178bb8 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -185,8 +185,7 @@ static int __init chsc_init_dbfs(void) debug_set_level(chsc_debug_log_id, 2); return 0; out: - if (chsc_debug_msg_id) - debug_unregister(chsc_debug_msg_id); + debug_unregister(chsc_debug_msg_id); return -ENOMEM; } diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index e0d02952a7f4..2d18205526b6 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -76,12 +76,9 @@ static int __init cio_debug_init(void) return 0; out_unregister: - if (cio_debug_msg_id) - debug_unregister(cio_debug_msg_id); - if (cio_debug_trace_id) - debug_unregister(cio_debug_trace_id); - if (cio_debug_crw_id) - debug_unregister(cio_debug_crw_id); + debug_unregister(cio_debug_msg_id); + debug_unregister(cio_debug_trace_id); + debug_unregister(cio_debug_crw_id); return -1; } diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index f1f3baa8e6e4..b6fc147f83d8 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -366,8 +366,6 @@ void qdio_debug_exit(void) { qdio_clear_dbf_list(); debugfs_remove(debugfs_root); - if (qdio_dbf_setup) - debug_unregister(qdio_dbf_setup); - if (qdio_dbf_error) - debug_unregister(qdio_dbf_error); + debug_unregister(qdio_dbf_setup); + debug_unregister(qdio_dbf_error); } diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 9f8fa42c062c..5d3d04c040c2 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -1428,10 +1428,8 @@ int __init zcrypt_debug_init(void) void zcrypt_debug_exit(void) { debugfs_remove(debugfs_root); - if (zcrypt_dbf_common) - debug_unregister(zcrypt_dbf_common); - if (zcrypt_dbf_devices) - debug_unregister(zcrypt_dbf_devices); + debug_unregister(zcrypt_dbf_common); + debug_unregister(zcrypt_dbf_devices); } /** -- cgit v1.2.3-59-g8ed1b From 155eeb66d2d1e58c8d4d58d47d8f8b02263d508d Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Wed, 4 Nov 2015 09:01:34 +0100 Subject: s390/sclp_cpi: remove sclp_cpi module in favor of sysfs interface Since commit c05ffc4f2b20 ("[S390] sclp: sysfs interface for SCLP cpi"), which was made 2008 the user can specify a system and sysplex name through the /sys/firmware/cpi interface. In addition to sysplex and system name, the user can also override the system type and system version. Because the syfs interface is easier to use and allows the settings to be updated, the sclp_cpi module becomes obsolete and can be removed. Signed-off-by: Hendrik Brueckner Acked-by: Christian Borntraeger Acked-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/Kconfig | 13 ------------- drivers/s390/char/Makefile | 1 - drivers/s390/char/sclp_cpi.c | 40 ---------------------------------------- 3 files changed, 54 deletions(-) delete mode 100644 drivers/s390/char/sclp_cpi.c diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index eaca3e006301..1f9078fdaf8c 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig @@ -78,19 +78,6 @@ config SCLP_VT220_CONSOLE Include support for using an IBM SCLP VT220-compatible terminal as a Linux system console. -config SCLP_CPI - def_tristate m - prompt "Control-Program Identification" - depends on S390 - help - This option enables the hardware console interface for system - identification. This is commonly used for workload management and - gives you a nice name for the system on the service element. - Please select this option as a module since built-in operation is - completely untested. - You should only select this option if you know what you are doing, - need this feature and intend to run your kernel in LPAR. - config SCLP_ASYNC def_tristate m prompt "Support for Call Home via Asynchronous SCLP Records" diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index 8a2632ba88dc..dd2f7c832e5e 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_TN3215) += con3215.o obj-$(CONFIG_SCLP_TTY) += sclp_tty.o obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o -obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o obj-$(CONFIG_SCLP_ASYNC) += sclp_async.o obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c deleted file mode 100644 index d70d8c20229c..000000000000 --- a/drivers/s390/char/sclp_cpi.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SCLP control programm identification - * - * Copyright IBM Corp. 2001, 2007 - * Author(s): Martin Peschke - * Michael Ernst - */ - -#include -#include -#include -#include -#include "sclp_cpi_sys.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Identify this operating system instance " - "to the System z hardware"); -MODULE_AUTHOR("Martin Peschke , " - "Michael Ernst "); - -static char *system_name = ""; -static char *sysplex_name = ""; - -module_param(system_name, charp, 0); -MODULE_PARM_DESC(system_name, "e.g. hostname - max. 8 characters"); -module_param(sysplex_name, charp, 0); -MODULE_PARM_DESC(sysplex_name, "if applicable - max. 8 characters"); - -static int __init cpi_module_init(void) -{ - return sclp_cpi_set_data(system_name, sysplex_name, "LINUX", - LINUX_VERSION_CODE); -} - -static void __exit cpi_module_exit(void) -{ -} - -module_init(cpi_module_init); -module_exit(cpi_module_exit); -- cgit v1.2.3-59-g8ed1b From 561e103002696a17907ac5bbccec551e32de3b7f Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 18 Nov 2015 17:00:10 +0100 Subject: s390/dis: Fix printing of the register numbers Since commit b006f19b055f ("lib/vsprintf.c: handle invalid format specifiers more robustly") I get errors like [...] Krnl Code: 00000000004e2410: c00400000000 brcl 0,4e2410 Please remove unsupported %r in format string [ 8.179483] ------------[ cut here ]------------ [ 8.179484] WARNING: at lib/vsprintf.c:1781 Turns out that our disassembler relied on %r not being used as format string. Let's do the proper escaping of our decode buffers. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/dis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index 8140d10c6785..8cb9bfdd3ea8 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c @@ -2015,7 +2015,7 @@ void show_code(struct pt_regs *regs) *ptr++ = '\t'; ptr += print_insn(ptr, code + start, addr); start += opsize; - printk(buffer); + printk("%s", buffer); ptr = buffer; ptr += sprintf(ptr, "\n "); hops++; @@ -2042,7 +2042,7 @@ void print_fn_code(unsigned char *code, unsigned long len) ptr += print_insn(ptr, code, (unsigned long) code); *ptr++ = '\n'; *ptr++ = 0; - printk(buffer); + printk("%s", buffer); code += opsize; len -= opsize; } -- cgit v1.2.3-59-g8ed1b From 3f975df69dba78834471b7133dcb8c8ddf7f986a Mon Sep 17 00:00:00 2001 From: Sascha Silbe Date: Tue, 24 Nov 2015 16:28:55 +0100 Subject: s390/sclp: Add VT220 support to early sclp console When running under qemu with the default configuration (-nographic), there is only a VT220 SCLP console, no line-mode SCLP console. Add VT220 support to the early SCLP console so the user has a chance to see critical error messages during early boot. None of the existing users of _sclp_print_early() check the return code. Instead of trying to come up with return code semantics when printing to multiple consoles (any or all of which may fail), we just drop the return code entirely. Tested on z/VM (line mode console) and LPAR (VT220 and line mode console). Tested on qemu/KVM with VT220 console and / or line mode console. Signed-off-by: Sascha Silbe Reviewed-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/sclp.h | 2 +- arch/s390/kernel/sclp.c | 65 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 2ca9c7bc50db..cb691602f295 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -80,6 +80,6 @@ int sclp_pci_deconfigure(u32 fid); int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count); int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count); void sclp_early_detect(void); -int _sclp_print_early(const char *); +void _sclp_print_early(const char *); #endif /* _ASM_S390_SCLP_H */ diff --git a/arch/s390/kernel/sclp.c b/arch/s390/kernel/sclp.c index 9fe7781a45cd..d88db40bdf15 100644 --- a/arch/s390/kernel/sclp.c +++ b/arch/s390/kernel/sclp.c @@ -9,7 +9,11 @@ #include #include +#define EVTYP_VT220MSG_MASK 0x00000040 +#define EVTYP_MSG_MASK 0x40000000 + static char _sclp_work_area[4096] __aligned(PAGE_SIZE); +static bool have_vt220, have_linemode; static void _sclp_wait_int(void) { @@ -68,7 +72,7 @@ static int _sclp_setup(int disable) 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned int *masks; @@ -82,13 +86,13 @@ static int _sclp_setup(int disable) rc = _sclp_servc(0x00780005, _sclp_work_area); if (rc) return rc; - if ((masks[0] & masks[3]) != masks[0] || - (masks[1] & masks[2]) != masks[1]) - return -EIO; + have_vt220 = masks[2] & EVTYP_VT220MSG_MASK; + have_linemode = masks[2] & EVTYP_MSG_MASK; return 0; } -static int _sclp_print(const char *str) +/* Output multi-line text using SCLP Message interface. */ +static void _sclp_print_lm(const char *str) { static unsigned char write_head[] = { /* sccb header */ @@ -143,18 +147,49 @@ static int _sclp_print(const char *str) } while (ch != 0); /* SCLP write data */ - return _sclp_servc(0x00760005, _sclp_work_area); + _sclp_servc(0x00760005, _sclp_work_area); } -int _sclp_print_early(const char *str) +/* Output multi-line text (plus a newline) using SCLP VT220 + * interface. + */ +static void _sclp_print_vt220(const char *str) { - int rc; + static unsigned char const write_head[] = { + /* sccb header */ + 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* evbuf header */ + 0x00, 0x06, + 0x1a, 0x00, 0x00, 0x00, + }; + size_t len = strlen(str); - rc = _sclp_setup(0); - if (rc) - return rc; - rc = _sclp_print(str); - if (rc) - return rc; - return _sclp_setup(1); + if (sizeof(write_head) + len >= sizeof(_sclp_work_area)) + len = sizeof(_sclp_work_area) - sizeof(write_head) - 1; + + memcpy(_sclp_work_area, write_head, sizeof(write_head)); + memcpy(_sclp_work_area + sizeof(write_head), str, len); + _sclp_work_area[sizeof(write_head) + len] = '\n'; + + /* Update length fields in evbuf and sccb headers */ + *(unsigned short *)(_sclp_work_area + 8) += len + 1; + *(unsigned short *)(_sclp_work_area + 0) += len + 1; + + /* SCLP write data */ + (void)_sclp_servc(0x00760005, _sclp_work_area); +} + +/* Output one or more lines of text on the SCLP console (VT220 and / + * or line-mode). All lines get terminated; no need for a trailing LF. + */ +void _sclp_print_early(const char *str) +{ + if (_sclp_setup(0) != 0) + return; + if (have_linemode) + _sclp_print_lm(str); + if (have_vt220) + _sclp_print_vt220(str); + _sclp_setup(1); } -- cgit v1.2.3-59-g8ed1b From b8eecf36a47bc5e9569f513a3888d03d82985fbb Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Wed, 25 Nov 2015 11:54:36 +0100 Subject: s390: add 'install' target to 'make help' Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/s390/Makefile b/arch/s390/Makefile index e8d4423e4f85..647bd14b223e 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -129,4 +129,8 @@ archclean: define archhelp echo '* image - Kernel image for IPL ($(boot)/image)' echo '* bzImage - Compressed kernel image for IPL ($(boot)/bzImage)' + echo ' install - Install kernel using' + echo ' (your) ~/bin/$(INSTALLKERNEL) or' + echo ' (distribution) /sbin/$(INSTALLKERNEL) or' + echo ' install to $$(INSTALL_PATH)' endef -- cgit v1.2.3-59-g8ed1b From 9eb31be33cf84266abd61de0f6d3d1fe609587cf Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 26 Nov 2015 09:25:35 +0100 Subject: s390: remove is_32bit_task() helper is_32bit_task() used to be helpful when we still had CONFIG_32BIT. Since that is gone, it is nowadays identical to is_compat_task(). So remove it. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/compat.h | 2 +- arch/s390/include/asm/elf.h | 9 +++++---- arch/s390/include/asm/thread_info.h | 2 -- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index d350ed9d0fbb..352f7bdaf11f 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -284,7 +284,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr) static inline int is_compat_task(void) { - return is_32bit_task(); + return test_thread_flag(TIF_31BIT); } static inline void __user *arch_compat_alloc_user_space(long len) diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 7730e5b9e7e2..fabebe1e45d9 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -126,6 +126,7 @@ typedef s390_regs elf_gregset_t; typedef s390_fp_regs compat_elf_fpregset_t; typedef s390_compat_regs compat_elf_gregset_t; +#include #include /* for task_struct */ #include @@ -159,7 +160,7 @@ extern unsigned int vdso_enabled; the loader. We need to make sure that it is out of the way of the program that it will "exec", and that there is sufficient room for the brk. 64-bit tasks are aligned to 4GB. */ -#define ELF_ET_DYN_BASE (is_32bit_task() ? \ +#define ELF_ET_DYN_BASE (is_compat_task() ? \ (STACK_TOP / 3 * 2) : \ (STACK_TOP / 3 * 2) & ~((1UL << 32) - 1)) @@ -212,9 +213,9 @@ do { \ * of up to 1GB. For 31-bit processes the virtual address space is limited, * use no alignment and limit the randomization to 8MB. */ -#define BRK_RND_MASK (is_32bit_task() ? 0x7ffUL : 0x3ffffUL) -#define MMAP_RND_MASK (is_32bit_task() ? 0x7ffUL : 0x3ff80UL) -#define MMAP_ALIGN_MASK (is_32bit_task() ? 0 : 0x7fUL) +#define BRK_RND_MASK (is_compat_task() ? 0x7ffUL : 0x3ffffUL) +#define MMAP_RND_MASK (is_compat_task() ? 0x7ffUL : 0x3ff80UL) +#define MMAP_ALIGN_MASK (is_compat_task() ? 0 : 0x7fUL) #define STACK_RND_MASK MMAP_RND_MASK #define ARCH_DLINFO \ diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 692b9247c019..2fffc2c27581 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -96,6 +96,4 @@ void arch_release_task_struct(struct task_struct *tsk); #define _TIF_31BIT _BITUL(TIF_31BIT) #define _TIF_SINGLE_STEP _BITUL(TIF_SINGLE_STEP) -#define is_32bit_task() (test_thread_flag(TIF_31BIT)) - #endif /* _ASM_THREAD_INFO_H */ -- cgit v1.2.3-59-g8ed1b From c6f70d3b8a32fdec60d3f78cb59423f056f16688 Mon Sep 17 00:00:00 2001 From: Jochen Schweflinghaus Date: Thu, 26 Nov 2015 19:13:01 +0100 Subject: s390/sclp: add open for business support Provide a user space interface and an enhancement to the sclp device driver which allows to send an 'Open for Business' event from the operating system to the Support Element. The 'Open for Business' event is used to signal the Support Element that the operating system (or an application running on top of it) is up and running. Signed-off-by: Jochen Schweflinghaus Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/Kconfig | 8 ++++ drivers/s390/char/sclp_config.c | 102 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 1f9078fdaf8c..b3f1c458905f 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig @@ -112,6 +112,14 @@ config HMC_DRV transfer cache size from it's default value 0.5MB to N bytes. If N is zero, then no caching is performed. +config SCLP_OFB + def_bool n + prompt "Support for Open-for-Business SCLP Event" + depends on S390 + help + This option enables the Open-for-Business interface to the s390 + Service Element. + config S390_TAPE def_tristate m prompt "S/390 tape device support" diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c index 944156207477..2ced50ccca63 100644 --- a/drivers/s390/char/sclp_config.c +++ b/drivers/s390/char/sclp_config.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include "sclp.h" @@ -20,8 +22,22 @@ struct conf_mgm_data { u8 ev_qualifier; } __attribute__((packed)); +#define OFB_DATA_MAX 64 + +struct sclp_ofb_evbuf { + struct evbuf_header header; + struct conf_mgm_data cm_data; + char ev_data[OFB_DATA_MAX]; +} __packed; + +struct sclp_ofb_sccb { + struct sccb_header header; + struct sclp_ofb_evbuf ofb_evbuf; +} __packed; + #define EV_QUAL_CPU_CHANGE 1 #define EV_QUAL_CAP_CHANGE 3 +#define EV_QUAL_OPEN4BUSINESS 5 static struct work_struct sclp_cpu_capability_work; static struct work_struct sclp_cpu_change_work; @@ -63,15 +79,99 @@ static void sclp_conf_receiver_fn(struct evbuf_header *evbuf) static struct sclp_register sclp_conf_register = { +#ifdef CONFIG_SCLP_OFB + .send_mask = EVTYP_CONFMGMDATA_MASK, +#endif .receive_mask = EVTYP_CONFMGMDATA_MASK, .receiver_fn = sclp_conf_receiver_fn, }; +#ifdef CONFIG_SCLP_OFB +static int sclp_ofb_send_req(char *ev_data, size_t len) +{ + static DEFINE_MUTEX(send_mutex); + struct sclp_ofb_sccb *sccb; + int rc, response; + + if (len > OFB_DATA_MAX) + return -EINVAL; + sccb = (struct sclp_ofb_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!sccb) + return -ENOMEM; + /* Setup SCCB for Control-Program Identification */ + sccb->header.length = sizeof(struct sclp_ofb_sccb); + sccb->ofb_evbuf.header.length = sizeof(struct sclp_ofb_evbuf); + sccb->ofb_evbuf.header.type = EVTYP_CONFMGMDATA; + sccb->ofb_evbuf.cm_data.ev_qualifier = EV_QUAL_OPEN4BUSINESS; + memcpy(sccb->ofb_evbuf.ev_data, ev_data, len); + + if (!(sclp_conf_register.sclp_receive_mask & EVTYP_CONFMGMDATA_MASK)) + pr_warn("SCLP receiver did not register to receive " + "Configuration Management Data Events.\n"); + + mutex_lock(&send_mutex); + rc = sclp_sync_request(SCLP_CMDW_WRITE_EVENT_DATA, sccb); + mutex_unlock(&send_mutex); + if (rc) + goto out; + response = sccb->header.response_code; + if (response != 0x0020) { + pr_err("Open for Business request failed with response code " + "0x%04x\n", response); + rc = -EIO; + } +out: + free_page((unsigned long)sccb); + return rc; +} + +static ssize_t sysfs_ofb_data_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + int rc; + + rc = sclp_ofb_send_req(buf, count); + return rc ?: count; +} + +static struct bin_attribute ofb_bin_attr = { + .attr = { + .name = "event_data", + .mode = S_IWUSR, + }, + .write = sysfs_ofb_data_write, +}; +#endif + +static int __init sclp_ofb_setup(void) +{ +#ifdef CONFIG_SCLP_OFB + struct kset *ofb_kset; + int rc; + + ofb_kset = kset_create_and_add("ofb", NULL, firmware_kobj); + if (!ofb_kset) + return -ENOMEM; + rc = sysfs_create_bin_file(&ofb_kset->kobj, &ofb_bin_attr); + if (rc) { + kset_unregister(ofb_kset); + return rc; + } +#endif + return 0; +} + static int __init sclp_conf_init(void) { + int rc; + INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify); INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify); - return sclp_register(&sclp_conf_register); + rc = sclp_register(&sclp_conf_register); + if (rc) + return rc; + return sclp_ofb_setup(); } __initcall(sclp_conf_init); -- cgit v1.2.3-59-g8ed1b From 419123f900dac58fb27ce5285b21074f5300095a Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 19 Nov 2015 11:09:45 +0100 Subject: s390/spinlock: do not yield to a CPU in udelay/mdelay It does not make sense to try to relinquish the time slice with diag 0x9c to a CPU in a state that does not allow to schedule the CPU. The scenario where this can happen is a CPU waiting in udelay/mdelay while holding a spin-lock. Add a CIF bit to tag a CPU in enabled wait and use it to detect that the yield of a CPU will not be successful and skip the diagnose call. Reviewed-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/processor.h | 12 ++++++++++++ arch/s390/kernel/entry.S | 2 ++ arch/s390/lib/spinlock.c | 25 +++++++++++++++++-------- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index b16c3d0a1b9f..5592c94ebe31 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -18,12 +18,14 @@ #define CIF_NOHZ_DELAY 2 /* delay HZ disable for a tick */ #define CIF_FPU 3 /* restore FPU registers */ #define CIF_IGNORE_IRQ 4 /* ignore interrupt (for udelay) */ +#define CIF_ENABLED_WAIT 5 /* in enabled wait state */ #define _CIF_MCCK_PENDING _BITUL(CIF_MCCK_PENDING) #define _CIF_ASCE _BITUL(CIF_ASCE) #define _CIF_NOHZ_DELAY _BITUL(CIF_NOHZ_DELAY) #define _CIF_FPU _BITUL(CIF_FPU) #define _CIF_IGNORE_IRQ _BITUL(CIF_IGNORE_IRQ) +#define _CIF_ENABLED_WAIT _BITUL(CIF_ENABLED_WAIT) #ifndef __ASSEMBLY__ @@ -52,6 +54,16 @@ static inline int test_cpu_flag(int flag) return !!(S390_lowcore.cpu_flags & (1UL << flag)); } +/* + * Test CIF flag of another CPU. The caller needs to ensure that + * CPU hotplug can not happen, e.g. by disabling preemption. + */ +static inline int test_cpu_flag_of(int flag, int cpu) +{ + struct _lowcore *lc = lowcore_ptr[cpu]; + return !!(lc->cpu_flags & (1UL << flag)); +} + #define arch_needs_cpu() test_cpu_flag(CIF_NOHZ_DELAY) /* diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 857b6526d298..cd5a191381b9 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -764,6 +764,7 @@ ENTRY(psw_idle) .insn rsy,0xeb0000000017,%r1,5,__SF_EMPTY+16(%r15) .Lpsw_idle_stcctm: #endif + oi __LC_CPU_FLAGS+7,_CIF_ENABLED_WAIT STCK __CLOCK_IDLE_ENTER(%r2) stpt __TIMER_IDLE_ENTER(%r2) .Lpsw_idle_lpsw: @@ -1146,6 +1147,7 @@ cleanup_critical: .quad .Lio_done - 4 .Lcleanup_idle: + ni __LC_CPU_FLAGS+7,255-_CIF_ENABLED_WAIT # copy interrupt clock & cpu timer mvc __CLOCK_IDLE_EXIT(8,%r2),__LC_INT_CLOCK mvc __TIMER_IDLE_EXIT(8,%r2),__LC_ASYNC_ENTER_TIMER diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 0a68fe04a9e1..d4549c964589 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -37,6 +37,15 @@ static inline void _raw_compare_and_delay(unsigned int *lock, unsigned int old) asm(".insn rsy,0xeb0000000022,%0,0,%1" : : "d" (old), "Q" (*lock)); } +static inline int cpu_is_preempted(int cpu) +{ + if (test_cpu_flag_of(CIF_ENABLED_WAIT, cpu)) + return 0; + if (smp_vcpu_scheduled(cpu)) + return 0; + return 1; +} + void arch_spin_lock_wait(arch_spinlock_t *lp) { unsigned int cpu = SPINLOCK_LOCKVAL; @@ -53,7 +62,7 @@ void arch_spin_lock_wait(arch_spinlock_t *lp) continue; } /* First iteration: check if the lock owner is running. */ - if (first_diag && !smp_vcpu_scheduled(~owner)) { + if (first_diag && cpu_is_preempted(~owner)) { smp_yield_cpu(~owner); first_diag = 0; continue; @@ -72,7 +81,7 @@ void arch_spin_lock_wait(arch_spinlock_t *lp) * yield the CPU unconditionally. For LPAR rely on the * sense running status. */ - if (!MACHINE_IS_LPAR || !smp_vcpu_scheduled(~owner)) { + if (!MACHINE_IS_LPAR || cpu_is_preempted(~owner)) { smp_yield_cpu(~owner); first_diag = 0; } @@ -98,7 +107,7 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) local_irq_restore(flags); } /* Check if the lock owner is running. */ - if (first_diag && !smp_vcpu_scheduled(~owner)) { + if (first_diag && cpu_is_preempted(~owner)) { smp_yield_cpu(~owner); first_diag = 0; continue; @@ -117,7 +126,7 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) * yield the CPU unconditionally. For LPAR rely on the * sense running status. */ - if (!MACHINE_IS_LPAR || !smp_vcpu_scheduled(~owner)) { + if (!MACHINE_IS_LPAR || cpu_is_preempted(~owner)) { smp_yield_cpu(~owner); first_diag = 0; } @@ -155,7 +164,7 @@ void _raw_read_lock_wait(arch_rwlock_t *rw) owner = 0; while (1) { if (count-- <= 0) { - if (owner && !smp_vcpu_scheduled(~owner)) + if (owner && cpu_is_preempted(~owner)) smp_yield_cpu(~owner); count = spin_retry; } @@ -201,7 +210,7 @@ void _raw_write_lock_wait(arch_rwlock_t *rw, unsigned int prev) owner = 0; while (1) { if (count-- <= 0) { - if (owner && !smp_vcpu_scheduled(~owner)) + if (owner && cpu_is_preempted(~owner)) smp_yield_cpu(~owner); count = spin_retry; } @@ -231,7 +240,7 @@ void _raw_write_lock_wait(arch_rwlock_t *rw) owner = 0; while (1) { if (count-- <= 0) { - if (owner && !smp_vcpu_scheduled(~owner)) + if (owner && cpu_is_preempted(~owner)) smp_yield_cpu(~owner); count = spin_retry; } @@ -275,7 +284,7 @@ void arch_lock_relax(unsigned int cpu) { if (!cpu) return; - if (MACHINE_IS_LPAR && smp_vcpu_scheduled(~cpu)) + if (MACHINE_IS_LPAR && !cpu_is_preempted(~cpu)) return; smp_yield_cpu(~cpu); } -- cgit v1.2.3-59-g8ed1b From 9552a66fe622ed53b87278a90917a37a5245e68a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 24 Nov 2015 12:18:22 +0100 Subject: s390/facilities: use stfl mnemonic instead of insn magic Now that 31 bit support is gone, the assembler always knows about the stfl instruction. Therefore lets use a readable mnemonic. Also remove the not needed extable entry for the inline assembly and fix the output constraint. Signed-off-by: Heiko Carstens Reviewed-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/facility.h | 6 ++---- arch/s390/kernel/head.S | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index 0aa6a7ed95a3..b4f99d22ba04 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -44,10 +44,8 @@ static inline void stfle(u64 *stfle_fac_list, int size) preempt_disable(); asm volatile( - " .insn s,0xb2b10000,0(0)\n" /* stfl */ - "0:\n" - EX_TABLE(0b, 0b) - : "+m" (S390_lowcore.stfl_fac_list)); + " stfl 0(0)\n" + : "=m" (S390_lowcore.stfl_fac_list)); nr = 4; /* bytes stored by stfl */ memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); if (S390_lowcore.stfl_fac_list & 0x01000000) { diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 301ee9c70688..d893d5aeb307 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -306,7 +306,7 @@ ENTRY(startup_kdump) mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13) xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} - .insn s,0xb2b10000,0 # store facilities @ __LC_STFL_FAC_LIST + stfl 0(%r0) # store facilities @ __LC_STFL_FAC_LIST tm __LC_STFL_FAC_LIST,0x01 # stfle available ? jz 0f la %r0,1 -- cgit v1.2.3-59-g8ed1b From 76cdd44c2e56ffabc297494c090c6babc8985998 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 24 Nov 2015 12:33:07 +0100 Subject: s390/facilities: always use lowcore's stfle field for storing facility bits head.s contains an stfle instruction which stores it result at the storage location that is assigned to the stfl instruction. This is currently no problem, since we only care about one double word. However if the number of double words in the ALS bitfield grows the current code is not very stable. E.g. before issuing the stfle command the memory to which it stores must be cleared, since the instruction may or may not clear memory contents where no bits are set. In order to simplify the code a bit always use the storage location that we reserved for the stfle result. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/asm-offsets.c | 1 + arch/s390/kernel/head.S | 10 +++++----- arch/s390/kernel/head64.S | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index ae7b565b6c4c..d8d18f8d8b77 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -120,6 +120,7 @@ int main(void) OFFSET(__LC_IO_INT_PARM, _lowcore, io_int_parm); OFFSET(__LC_IO_INT_WORD, _lowcore, io_int_word); OFFSET(__LC_STFL_FAC_LIST, _lowcore, stfl_fac_list); + OFFSET(__LC_STFLE_FAC_LIST, _lowcore, stfle_fac_list); OFFSET(__LC_MCCK_CODE, _lowcore, mcck_interruption_code); OFFSET(__LC_MCCK_FAIL_STOR_ADDR, _lowcore, failing_storage_address); OFFSET(__LC_LAST_BREAK, _lowcore, breaking_event_addr); diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index d893d5aeb307..d28a14849126 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -300,19 +300,19 @@ ENTRY(startup_kdump) xc 0x200(256),0x200 # partially clear lowcore xc 0x300(256),0x300 xc 0xe00(256),0xe00 + xc 0xf00(256),0xf00 lctlg %c0,%c15,0x200(%r0) # initialize control registers stck __LC_LAST_UPDATE_CLOCK spt 6f-.LPG0(%r13) mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13) - xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST - # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} stfl 0(%r0) # store facilities @ __LC_STFL_FAC_LIST - tm __LC_STFL_FAC_LIST,0x01 # stfle available ? + mvc __LC_STFLE_FAC_LIST(4),__LC_STFL_FAC_LIST + tm __LC_STFLE_FAC_LIST,0x01 # stfle available ? jz 0f la %r0,1 - .insn s,0xb2b00000,__LC_STFL_FAC_LIST # store facility list extended + .insn s,0xb2b00000,__LC_STFLE_FAC_LIST # store facility list extended # verify if all required facilities are supported by the machine -0: la %r1,__LC_STFL_FAC_LIST +0: la %r1,__LC_STFLE_FAC_LIST la %r2,3f+8-.LPG0(%r13) l %r3,0(%r2) 1: l %r0,0(%r1) diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 58b719fa8067..c5febe84eba6 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -16,7 +16,7 @@ __HEAD ENTRY(startup_continue) - tm __LC_STFL_FAC_LIST+6,0x80 # LPP available ? + tm __LC_STFLE_FAC_LIST+6,0x80 # LPP available ? jz 0f xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid mvi __LC_LPP,0x80 # and set LPP_MAGIC -- cgit v1.2.3-59-g8ed1b From c30f6828fed9d33c2d54dfaf3621717c56f9c779 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 2 Feb 2015 07:08:44 +0100 Subject: s390/facilities: add helper tool to generate facility lists Modifying the architecture level set facility lists was always very error prone. Given the numbering of the facility bits within the Principles of Operation, where the most significant bit number is 0, it happened a lot of times that wrong bits were set or cleared. Therefore this patch adds a tool "gen_facilities" which generates include/generated/facilites.h. The definition of the bits to be set is contained within arch/s390/include/asm/facilities_src.h and can be easily extended to e.g. also generate such lists for the KVM module. The generated file looks like this: #define FACILITIES_ALS _AC(0xc1006450f0040000,UL) #define FACILITIES_ALS_DWORDS 1 The facility bits defined in this patch match 1:1 to the current masks that can be found in head.S. That is if the tool gets executed with -march=z990 then the generated masks will equal the masks in head.S for CONFIG_MARCH_Z990. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Makefile | 5 +++ arch/s390/include/asm/facilities_src.h | 67 ++++++++++++++++++++++++++++++++++ arch/s390/include/asm/facility.h | 5 +++ arch/s390/tools/.gitignore | 1 + arch/s390/tools/Makefile | 15 ++++++++ arch/s390/tools/gen_facilities.c | 67 ++++++++++++++++++++++++++++++++++ 6 files changed, 160 insertions(+) create mode 100644 arch/s390/include/asm/facilities_src.h create mode 100644 arch/s390/tools/.gitignore create mode 100644 arch/s390/tools/Makefile create mode 100644 arch/s390/tools/gen_facilities.c diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 647bd14b223e..224b42734f0d 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -106,6 +106,7 @@ drivers-y += drivers/s390/ drivers-$(CONFIG_OPROFILE) += arch/s390/oprofile/ boot := arch/s390/boot +tools := arch/s390/tools all: image bzImage @@ -124,6 +125,10 @@ vdso_install: archclean: $(Q)$(MAKE) $(clean)=$(boot) + $(Q)$(MAKE) $(clean)=$(tools) + +archprepare: + $(Q)$(MAKE) $(build)=$(tools) include/generated/facilities.h # Don't use tabs in echo arguments define archhelp diff --git a/arch/s390/include/asm/facilities_src.h b/arch/s390/include/asm/facilities_src.h new file mode 100644 index 000000000000..4555fa69a29e --- /dev/null +++ b/arch/s390/include/asm/facilities_src.h @@ -0,0 +1,67 @@ +/* + * Copyright IBM Corp. 2015 + */ + +#ifndef S390_GEN_FACILITIES_C +#error "This file can only be included by gen_facilities.c" +#endif + +#include + +struct facility_def { + char *name; + int *bits; +}; + +static struct facility_def facility_defs[] = { + { + /* + * FACILITIES_ALS contains the list of facilities that are + * required to run a kernel that is compiled e.g. with + * -march=. + */ + .name = "FACILITIES_ALS", + .bits = (int[]){ +#ifdef CONFIG_HAVE_MARCH_Z900_FEATURES + 0, /* N3 instructions */ + 1, /* z/Arch mode installed */ +#endif +#ifdef CONFIG_HAVE_MARCH_Z990_FEATURES + 18, /* long displacement facility */ +#endif +#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES + 7, /* stfle */ + 16, /* extended translation facility 2 */ + 17, /* message security assist */ + 20, /* HFP-multiply-and-add */ + 21, /* extended-immediate facility */ + 22, /* extended-translation facility 3 */ + 23, /* HFP-unnormalized-extension */ + 24, /* ETF2-enhancement */ + 25, /* store clock fast */ + 30, /* ETF3-enhancement */ +#endif +#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES + 26, /* parsing enhancement facility */ + 27, /* mvcos */ + 32, /* compare and swap and store */ + 33, /* compare and swap and store 2 */ + 34, /* general extension facility */ + 35, /* execute extensions */ + 41, /* floating point support enhancement */ + 42, /* DFP facility */ + 44, /* PFPO */ +#endif +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES + 37, /* floating point extension */ + 45, /* fast-BCR, etc. */ +#endif +#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES + 48, /* decimal floating point zoned */ + 49, /* misc-instruction-extensions */ + 52, /* interlocked facility 2 */ +#endif + -1 /* END */ + } + }, +}; diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index b4f99d22ba04..007163f91856 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -7,6 +7,10 @@ #ifndef __ASM_FACILITY_H #define __ASM_FACILITY_H +#include + +#ifndef __ASSEMBLY__ + #include #include #include @@ -62,4 +66,5 @@ static inline void stfle(u64 *stfle_fac_list, int size) preempt_enable(); } +#endif /* __ASSEMBLY__ */ #endif /* __ASM_FACILITY_H */ diff --git a/arch/s390/tools/.gitignore b/arch/s390/tools/.gitignore new file mode 100644 index 000000000000..72a4b2cf1365 --- /dev/null +++ b/arch/s390/tools/.gitignore @@ -0,0 +1 @@ +gen_facilities diff --git a/arch/s390/tools/Makefile b/arch/s390/tools/Makefile new file mode 100644 index 000000000000..6d9814c9df2b --- /dev/null +++ b/arch/s390/tools/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for s390 specific build tools +# + +hostprogs-y += gen_facilities +HOSTCFLAGS_gen_facilities.o += -Wall $(LINUXINCLUDE) + +define filechk_facilities.h + $(obj)/gen_facilities +endef + +$(obj)/gen_facilities.o: $(srctree)/arch/s390/tools/gen_facilities.c + +include/generated/facilities.h: $(obj)/gen_facilities FORCE + $(call filechk,facilities.h) diff --git a/arch/s390/tools/gen_facilities.c b/arch/s390/tools/gen_facilities.c new file mode 100644 index 000000000000..e2660d27889b --- /dev/null +++ b/arch/s390/tools/gen_facilities.c @@ -0,0 +1,67 @@ +/* + * Simple program to generate defines out of facility lists that use the bit + * numbering scheme from the Princples of Operations: most significant bit + * has bit number 0. + * + * Copyright IBM Corp. 2015 + * + */ + +#define S390_GEN_FACILITIES_C + +#include +#include +#include +#include +#include + +static void print_facility_list(struct facility_def *def) +{ + unsigned int high, bit, dword, i; + unsigned long long *array; + + array = calloc(1, 8); + if (!array) + exit(EXIT_FAILURE); + high = 0; + for (i = 0; def->bits[i] != -1; i++) { + bit = 63 - (def->bits[i] & 63); + dword = def->bits[i] / 64; + if (dword > high) { + array = realloc(array, (dword + 1) * 8); + if (!array) + exit(EXIT_FAILURE); + memset(array + high + 1, 0, (dword - high) * 8); + high = dword; + } + array[dword] |= 1ULL << bit; + } + printf("#define %s ", def->name); + for (i = 0; i <= high; i++) + printf("_AC(0x%016llx,UL)%c", array[i], i < high ? ',' : '\n'); + printf("#define %s_DWORDS %d\n", def->name, high + 1); + free(array); +} + +static void print_facility_lists(void) +{ + unsigned int i; + + for (i = 0; i < sizeof(facility_defs) / sizeof(facility_defs[0]); i++) + print_facility_list(&facility_defs[i]); +} + +int main(int argc, char **argv) +{ + printf("#ifndef __ASM_S390_FACILITIES__\n"); + printf("#define __ASM_S390_FACILITIES__\n"); + printf("/*\n"); + printf(" * DO NOT MODIFY.\n"); + printf(" *\n"); + printf(" * This file was generated by %s\n", __FILE__); + printf(" */\n\n"); + printf("#include \n\n"); + print_facility_lists(); + printf("\n#endif\n"); + return 0; +} -- cgit v1.2.3-59-g8ed1b From 0358ecf7327f0cb206b14138353e1cbe612c5d64 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 24 Nov 2015 12:47:14 +0100 Subject: s390/facilities: make use of generated facility list Change head.S to make use of the generated facility list. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/head.S | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index d28a14849126..fcaefb041364 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -309,18 +310,18 @@ ENTRY(startup_kdump) mvc __LC_STFLE_FAC_LIST(4),__LC_STFL_FAC_LIST tm __LC_STFLE_FAC_LIST,0x01 # stfle available ? jz 0f - la %r0,1 + lghi %r0,FACILITIES_ALS_DWORDS-1 .insn s,0xb2b00000,__LC_STFLE_FAC_LIST # store facility list extended # verify if all required facilities are supported by the machine 0: la %r1,__LC_STFLE_FAC_LIST la %r2,3f+8-.LPG0(%r13) - l %r3,0(%r2) -1: l %r0,0(%r1) - n %r0,4(%r2) - cl %r0,4(%r2) + lhi %r3,FACILITIES_ALS_DWORDS +1: lg %r0,0(%r1) + ng %r0,0(%r2) + clg %r0,0(%r2) jne 2f - la %r1,4(%r1) - la %r2,4(%r2) + la %r1,8(%r1) + la %r2,8(%r2) ahi %r3,-1 jnz 1b j 4f @@ -340,24 +341,10 @@ ENTRY(startup_kdump) 3: .long 0x000a0000,0x8badcccc # List of facilities that are required. If not all facilities are present -# the kernel will crash. Format is number of facility words with bits set, -# followed by the facility words. +# the kernel will crash. + + .quad FACILITIES_ALS -#if defined(CONFIG_MARCH_Z13) - .long 2, 0xc100eff2, 0xf46cc800 -#elif defined(CONFIG_MARCH_ZEC12) - .long 2, 0xc100eff2, 0xf46cc800 -#elif defined(CONFIG_MARCH_Z196) - .long 2, 0xc100eff2, 0xf46c0000 -#elif defined(CONFIG_MARCH_Z10) - .long 2, 0xc100eff2, 0xf0680000 -#elif defined(CONFIG_MARCH_Z9_109) - .long 1, 0xc100efc2 -#elif defined(CONFIG_MARCH_Z990) - .long 1, 0xc0002000 -#elif defined(CONFIG_MARCH_Z900) - .long 1, 0xc0000000 -#endif 4: /* Continue with startup code in head64.S */ jg startup_continue -- cgit v1.2.3-59-g8ed1b From 185edd4431f0dfd48a465e19ccc3280b08e9fa1a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 24 Nov 2015 13:11:18 +0100 Subject: s390/facilities: remove unneeded facility bits The facility lists contain a lot of bits which are not necessary to run the kernel. Therefore remove them and keep only those bits which are required for the kernel. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/facilities_src.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/s390/include/asm/facilities_src.h b/arch/s390/include/asm/facilities_src.h index 4555fa69a29e..493e88b4941c 100644 --- a/arch/s390/include/asm/facilities_src.h +++ b/arch/s390/include/asm/facilities_src.h @@ -31,33 +31,21 @@ static struct facility_def facility_defs[] = { #endif #ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES 7, /* stfle */ - 16, /* extended translation facility 2 */ 17, /* message security assist */ - 20, /* HFP-multiply-and-add */ 21, /* extended-immediate facility */ - 22, /* extended-translation facility 3 */ - 23, /* HFP-unnormalized-extension */ - 24, /* ETF2-enhancement */ 25, /* store clock fast */ - 30, /* ETF3-enhancement */ #endif #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES - 26, /* parsing enhancement facility */ 27, /* mvcos */ 32, /* compare and swap and store */ 33, /* compare and swap and store 2 */ 34, /* general extension facility */ 35, /* execute extensions */ - 41, /* floating point support enhancement */ - 42, /* DFP facility */ - 44, /* PFPO */ #endif #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES - 37, /* floating point extension */ 45, /* fast-BCR, etc. */ #endif #ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES - 48, /* decimal floating point zoned */ 49, /* misc-instruction-extensions */ 52, /* interlocked facility 2 */ #endif -- cgit v1.2.3-59-g8ed1b From 6ab6c31a5450b73133e04c3976469d6d72f55df3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 24 Nov 2015 13:48:27 +0100 Subject: s390/facilities: optimize test_facility() test_facility() can be optimized for bits which must be set anyway, due to the check in head.S. This removes a couple of superfluous runtime checks. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/facility.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index 007163f91856..09b406db7529 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -34,6 +34,12 @@ static inline int __test_facility(unsigned long nr, void *facilities) */ static inline int test_facility(unsigned long nr) { + unsigned long facilities_als[] = { FACILITIES_ALS }; + + if (__builtin_constant_p(nr) && nr < sizeof(facilities_als) * 8) { + if (__test_facility(nr, &facilities_als)) + return 1; + } return __test_facility(nr, &S390_lowcore.stfle_fac_list); } -- cgit v1.2.3-59-g8ed1b From f3d05f9de75e233d8f1090af91fc6c23ddc600e8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 25 Nov 2015 12:54:46 +0100 Subject: s390/facilities: add z13 als bit If configured for z13 assume the kernel makes use of the instructions that are part of the load-and-zero-rightmost-byte facility and load/store-on-condition facility 2. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/facilities_src.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390/include/asm/facilities_src.h b/arch/s390/include/asm/facilities_src.h index 493e88b4941c..4917728e5828 100644 --- a/arch/s390/include/asm/facilities_src.h +++ b/arch/s390/include/asm/facilities_src.h @@ -48,6 +48,9 @@ static struct facility_def facility_defs[] = { #ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES 49, /* misc-instruction-extensions */ 52, /* interlocked facility 2 */ +#endif +#ifdef CONFIG_HAVE_MARCH_Z13_FEATURES + 53, /* load-and-zero-rightmost-byte, etc. */ #endif -1 /* END */ } -- cgit v1.2.3-59-g8ed1b From a7e137eb94b6abd180050cf0b42e8b3db7efbf5f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 5 Nov 2015 14:03:27 +0100 Subject: kbuild: add AFLAGS_REMOVE_(basename).o option It is already possible to remove CFLAGS with the CFLAGS_REMOVE option that was introduced with commit 656ee82cc855 ("kbuild: create new CFLAGS_REMOVE_(basename).o option"). However it is not possible to remove AFLAGS for assembler files. So this patch just adds the AFLAGS_REMOVE option which works the same like CFLAGS_REMOVE. Signed-off-by: Heiko Carstens Acked-by: Michal Marek Signed-off-by: Martin Schwidefsky --- scripts/Makefile.lib | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 79e86613712f..26a48d76eb9d 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -104,8 +104,9 @@ modname_flags = $(if $(filter 1,$(words $(modname))),\ orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \ $(ccflags-y) $(CFLAGS_$(basetarget).o) _c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags)) -_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \ +orig_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \ $(asflags-y) $(AFLAGS_$(basetarget).o) +_a_flags = $(filter-out $(AFLAGS_REMOVE_$(basetarget).o), $(orig_a_flags)) _cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F)) # -- cgit v1.2.3-59-g8ed1b From 6527f6e0cb6a14c3938140f609d2fde59f4299fc Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 5 Nov 2015 14:03:32 +0100 Subject: s390: compile head.S always with -march=z900 head.S on s390 contains some sanity checks if the kernel will run on a machine or if the machine is too old, e.g. if the kernel contains instructions not available on the machine. If so, it will emit an error message to the console before it stops execution. Therefore head.S contains only instructions which are availanble with the earliest machine generation (z900). In order to make sure we don't accidently add instructions which are not available on z900, always compile with -march=z900. This makes sure compilation will fail if wrong instructions are used. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index dc167a23b920..e9a328d42610 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -34,8 +34,10 @@ CFLAGS_sysinfo.o += -w # CFLAGS_REMOVE_sclp.o = $(CC_FLAGS_FTRACE) ifneq ($(CC_FLAGS_MARCH),-march=z900) -CFLAGS_REMOVE_sclp.o += $(CC_FLAGS_MARCH) -CFLAGS_sclp.o += -march=z900 +CFLAGS_REMOVE_sclp.o += $(CC_FLAGS_MARCH) +CFLAGS_sclp.o += -march=z900 +AFLAGS_REMOVE_head.o += $(CC_FLAGS_MARCH) +AFLAGS_head.o += -march=z900 endif GCOV_PROFILE_sclp.o := n -- cgit v1.2.3-59-g8ed1b From f9101e639cf7e707b9a379737ea1b66a16e82097 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 7 Dec 2015 11:03:30 +0100 Subject: s390/traps: Remove unused variable location is assigned but never used. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/traps.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 1b18118bbc06..d69d648759c9 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -260,11 +260,8 @@ void vector_exception(struct pt_regs *regs) void data_exception(struct pt_regs *regs) { - __u16 __user *location; int signal = 0; - location = get_trap_ip(regs); - save_fpu_regs(); if (current->thread.fpu.fpc & FPC_DXC_MASK) signal = SIGFPE; -- cgit v1.2.3-59-g8ed1b From 292d8d71576c471e53eb7342ea6130f0241145e8 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 7 Dec 2015 12:50:03 +0100 Subject: s390/fault: remove unused variable address is assigned but never used. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index ec1a30d0d11a..1b903f6ad54a 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -254,7 +254,6 @@ static noinline void do_sigsegv(struct pt_regs *regs, int si_code) static noinline void do_no_context(struct pt_regs *regs) { const struct exception_table_entry *fixup; - unsigned long address; /* Are we prepared to handle this kernel fault? */ fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); @@ -267,7 +266,6 @@ static noinline void do_no_context(struct pt_regs *regs) * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ - address = regs->int_parm_long & __FAIL_ADDR_MASK; if (!user_space_fault(regs)) printk(KERN_ALERT "Unable to handle kernel pointer dereference" " in virtual kernel address space\n"); -- cgit v1.2.3-59-g8ed1b From 90f405e859840abe1ebf64a836a61e300c11e1c9 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 7 Dec 2015 12:52:20 +0100 Subject: s390/extmem: remove unused variable findseg_scode is assigned, but never used. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/mm/extmem.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 18fccc303db7..a1bf4ad8925d 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -94,7 +94,7 @@ 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, findseg_scode; +static int loadshr_scode, loadnsr_scode; static int segext_scode, purgeseg_scode; static int scode_set; @@ -130,7 +130,6 @@ dcss_set_subcodes(void) loadshr_scode = DCSS_LOADSHRX; loadnsr_scode = DCSS_LOADNSRX; purgeseg_scode = DCSS_PURGESEG; - findseg_scode = DCSS_FINDSEGX; segext_scode = DCSS_SEGEXTX; return 0; } @@ -138,7 +137,6 @@ dcss_set_subcodes(void) loadshr_scode = DCSS_LOADNOLY; loadnsr_scode = DCSS_LOADNSR; purgeseg_scode = DCSS_PURGESEG; - findseg_scode = DCSS_FINDSEG; segext_scode = DCSS_SEGEXT; return 0; } -- cgit v1.2.3-59-g8ed1b From e527aec434b59745654d3b34a3aa7ce3392a85a5 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 7 Dec 2015 13:08:48 +0100 Subject: s390/sysinfo: Remove unused variables max_mnest and rc are never used. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/sysinfo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 99babea026ca..efacda2fc568 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -111,8 +111,7 @@ static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info) static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info) { - static int max_mnest; - int i, rc; + int i; seq_putc(m, '\n'); if (!MACHINE_HAS_TOPOLOGY) -- cgit v1.2.3-59-g8ed1b From 3dbc78d3a179d99611111d2d86d4283f1f4f82b4 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 8 Dec 2015 14:10:12 +0100 Subject: s390/smp: save timestamp on external calls This is supposed to make debugging easier: if within a dump we can see that an external call or emergency signal IPI is pending but all cpus are idle, we have no idea for how long the interrupt is outstanding. Therefore save a timestamp into the per cpu pcpu array of the target cpu whenever such an IPI is sent. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 9da95d8dfc62..654c36ec0c60 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -66,6 +66,7 @@ static DEFINE_PER_CPU(struct cpu *, cpu_device); struct pcpu { struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ unsigned long ec_mask; /* bit mask for ec_xxx functions */ + unsigned long ec_clk; /* sigp timestamp for ec_xxx */ signed char state; /* physical cpu state */ signed char polarization; /* physical polarization */ u16 address; /* physical cpu address */ @@ -174,6 +175,7 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) if (test_and_set_bit(ec_bit, &pcpu->ec_mask)) return; order = pcpu_running(pcpu) ? SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL; + pcpu->ec_clk = get_tod_clock_fast(); pcpu_sigp_retry(pcpu, order, 0); } -- cgit v1.2.3-59-g8ed1b From d7ae65aec0dac187d29a2963ac46574aad840a20 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Tue, 15 Dec 2015 09:26:30 +0100 Subject: s390/setup: cleanup machine flags Over time some machine flags got unused (e.g. MACHINE_FLAG_MVPG) or are available on all 64bit systems (MACHINE_FLAG_CSP, MACHINE_FLAG_IEEE) - let's remove them. Reorder the other ones to match the order of the MACHINE_HAS_* macros and renumber all bits to avoid holes. Also fix the comment about where the flags are detected. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/setup.h | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 23537661da0e..69837225119e 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -12,27 +12,24 @@ #define PARMAREA 0x10400 /* - * Machine features detected in head.S + * Machine features detected in early.c */ #define MACHINE_FLAG_VM _BITUL(0) -#define MACHINE_FLAG_IEEE _BITUL(1) -#define MACHINE_FLAG_CSP _BITUL(2) -#define MACHINE_FLAG_MVPG _BITUL(3) -#define MACHINE_FLAG_DIAG44 _BITUL(4) +#define MACHINE_FLAG_KVM _BITUL(1) +#define MACHINE_FLAG_LPAR _BITUL(2) +#define MACHINE_FLAG_DIAG9C _BITUL(3) +#define MACHINE_FLAG_ESOP _BITUL(4) #define MACHINE_FLAG_IDTE _BITUL(5) -#define MACHINE_FLAG_DIAG9C _BITUL(6) -#define MACHINE_FLAG_KVM _BITUL(8) -#define MACHINE_FLAG_ESOP _BITUL(9) -#define MACHINE_FLAG_EDAT1 _BITUL(10) -#define MACHINE_FLAG_EDAT2 _BITUL(11) -#define MACHINE_FLAG_LPAR _BITUL(12) -#define MACHINE_FLAG_LPP _BITUL(13) -#define MACHINE_FLAG_TOPOLOGY _BITUL(14) -#define MACHINE_FLAG_TE _BITUL(15) -#define MACHINE_FLAG_TLB_LC _BITUL(17) -#define MACHINE_FLAG_VX _BITUL(18) -#define MACHINE_FLAG_CAD _BITUL(19) +#define MACHINE_FLAG_DIAG44 _BITUL(6) +#define MACHINE_FLAG_EDAT1 _BITUL(7) +#define MACHINE_FLAG_EDAT2 _BITUL(8) +#define MACHINE_FLAG_LPP _BITUL(9) +#define MACHINE_FLAG_TOPOLOGY _BITUL(10) +#define MACHINE_FLAG_TE _BITUL(11) +#define MACHINE_FLAG_TLB_LC _BITUL(12) +#define MACHINE_FLAG_VX _BITUL(13) +#define MACHINE_FLAG_CAD _BITUL(14) #define LPP_MAGIC _BITUL(31) #define LPP_PFAULT_PID_MASK _AC(0xffffffff, UL) -- cgit v1.2.3-59-g8ed1b From 62e65da994768e0d599d78dd2cebef5716ffb0ae Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 18 Dec 2015 12:58:47 +0100 Subject: s390/cio: Remove unused inline assemblies There is no longer a need to maintain two versions of the same inline assembly - one with exception handling, and one without - so get rid of the duplicates and adjust names accordingly. This applies to stsch_err and msch_err which are now renamed to stsch and msch respectively, while the original msch function is removed. Signed-off-by: Peter Oberparleiter Acked-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc_sch.c | 2 +- drivers/s390/cio/cio.c | 24 ++++++++++++------------ drivers/s390/cio/css.c | 2 +- drivers/s390/cio/device_fsm.c | 2 +- drivers/s390/cio/ioasm.h | 17 +---------------- 5 files changed, 16 insertions(+), 31 deletions(-) diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 378c57178bb8..b6f12c2bb114 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -133,7 +133,7 @@ static int chsc_subchannel_prepare(struct subchannel *sch) * since we don't have a way to clear the subchannel and * cannot disable it with a request running. */ - cc = stsch_err(sch->schid, &schib); + cc = stsch(sch->schid, &schib); if (!cc && scsw_stctl(&schib.scsw)) return -EAGAIN; return 0; diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 2d18205526b6..5f5c24030405 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -345,18 +345,18 @@ int cio_commit_config(struct subchannel *sch) struct schib schib; struct irb irb; - if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib)) + if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) return -ENODEV; for (retry = 0; retry < 5; retry++) { /* copy desired changes to local schib */ cio_apply_config(sch, &schib); - ccode = msch_err(sch->schid, &schib); + ccode = msch(sch->schid, &schib); if (ccode < 0) /* -EIO if msch gets a program check. */ return ccode; switch (ccode) { case 0: /* successful */ - if (stsch_err(sch->schid, &schib) || + if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) return -ENODEV; if (cio_check_config(sch, &schib)) { @@ -391,7 +391,7 @@ int cio_update_schib(struct subchannel *sch) { struct schib schib; - if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib)) + if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) return -ENODEV; memcpy(&sch->schib, &schib, sizeof(schib)); @@ -500,7 +500,7 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) * If stsch gets an exception, it means the current subchannel set * is not valid. */ - ccode = stsch_err(schid, &sch->schib); + ccode = stsch(schid, &sch->schib); if (ccode) { err = (ccode == 3) ? -ENXIO : ccode; goto out; @@ -616,7 +616,7 @@ static int cio_test_for_console(struct subchannel_id schid, void *data) { struct schib schib; - if (stsch_err(schid, &schib) != 0) + if (stsch(schid, &schib) != 0) return -ENXIO; if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv && (schib.pmcw.dev == console_devno)) { @@ -635,7 +635,7 @@ static int cio_get_console_sch_no(void) if (console_irq != -1) { /* VM provided us with the irq number of the console. */ schid.sch_no = console_irq; - if (stsch_err(schid, &schib) != 0 || + if (stsch(schid, &schib) != 0 || (schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv) return -1; console_devno = schib.pmcw.dev; @@ -705,10 +705,10 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) cc = 0; for (retry=0;retry<3;retry++) { schib->pmcw.ena = 0; - cc = msch_err(schid, schib); + cc = msch(schid, schib); if (cc) return (cc==3?-ENODEV:-EBUSY); - if (stsch_err(schid, schib) || !css_sch_is_valid(schib)) + if (stsch(schid, schib) || !css_sch_is_valid(schib)) return -ENODEV; if (!schib->pmcw.ena) return 0; @@ -755,7 +755,7 @@ static int stsch_reset(struct subchannel_id schid, struct schib *addr) pgm_check_occured = 0; s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; - rc = stsch_err(schid, addr); + rc = stsch(schid, addr); s390_base_pgm_handler_fn = NULL; /* The program check handler could have changed pgm_check_occured. */ @@ -792,7 +792,7 @@ static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) /* No default clear strategy */ break; } - stsch_err(schid, &schib); + stsch(schid, &schib); __disable_subchannel_easy(schid, &schib); } out: @@ -940,7 +940,7 @@ int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo) if (__chsc_enable_facility(&sda_area, CHSC_SDA_OC_MSS)) return -ENODEV; } - if (stsch_err(schid, &schib)) + if (stsch(schid, &schib)) return -ENODEV; if (schib.pmcw.st != SUBCHANNEL_TYPE_IO) return -ENODEV; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 489e703dc82d..3d2b20ee613f 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -390,7 +390,7 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow) /* Will be done on the slow path. */ return -EAGAIN; } - if (stsch_err(schid, &schib)) { + if (stsch(schid, &schib)) { /* Subchannel is not provided. */ return -ENXIO; } diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 92e03b42e661..8327d47e08b6 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -44,7 +44,7 @@ static void ccw_timeout_log(struct ccw_device *cdev) sch = to_subchannel(cdev->dev.parent); private = to_io_private(sch); orb = &private->orb; - cc = stsch_err(sch->schid, &schib); + cc = stsch(sch->schid, &schib); printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, " "device information:\n", get_tod_clock()); diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index 4d80fc67a06b..be6e2f5e11f7 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -25,7 +25,7 @@ struct tpi_info { * Some S390 specific IO instructions as inline */ -static inline int stsch_err(struct subchannel_id schid, struct schib *addr) +static inline int stsch(struct subchannel_id schid, struct schib *addr) { register struct subchannel_id reg1 asm ("1") = schid; int ccode = -EIO; @@ -43,21 +43,6 @@ static inline int stsch_err(struct subchannel_id schid, struct schib *addr) } static inline int msch(struct subchannel_id schid, struct schib *addr) -{ - register struct subchannel_id reg1 asm ("1") = schid; - int ccode; - - asm volatile( - " msch 0(%2)\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1), "a" (addr), "m" (*addr) - : "cc"); - return ccode; -} - -static inline int msch_err(struct subchannel_id schid, struct schib *addr) { register struct subchannel_id reg1 asm ("1") = schid; int ccode = -EIO; -- cgit v1.2.3-59-g8ed1b From ac357c4105ef6b2d44227aa349850a3c1a2994a5 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 18 Dec 2015 12:59:28 +0100 Subject: s390/cio: Fix incorrect xsch opcode specification The numeric representation of the xsch instruction was incorrectly specified, resulting in reserved fields of the instruction opcode potentially being set to a non-zero value. While this doesn't currently cause any problem, a future architecture might make use of these fields so that the current specification could result in an exception or unwanted side-effects. Fix this by using the xsch instruction code for which support in binutils was added in 2003. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/io_sch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index b108f4a5c7dd..789ce783d3e1 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h @@ -205,7 +205,7 @@ static inline int xsch(struct subchannel_id schid) int ccode; asm volatile( - " .insn rre,0xb2760000,%1,0\n" + " xsch\n" " ipm %0\n" " srl %0,28" : "=d" (ccode) -- cgit v1.2.3-59-g8ed1b From 2ab59de7c5ce7c5ed6db07278554901d43fe80a0 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 18 Dec 2015 12:59:32 +0100 Subject: s390/cio: Consolidate inline assemblies and related data definitions Replace the current semi-arbitrary distribution of inline assemblies: - Inline assemblies used by CIO go into ioasm.h - Data definitions used by inline assemblies go into cio.h Beyond cleaning up the current structure this is also required for use of tracepoints in inline assemblies introduced by a follow-on patch. Signed-off-by: Peter Oberparleiter Acked-by: Sebastian Ott Acked-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/crw.h | 14 --------- drivers/s390/cio/cio.h | 12 ++++++++ drivers/s390/cio/crw.c | 1 + drivers/s390/cio/io_sch.h | 45 --------------------------- drivers/s390/cio/ioasm.h | 75 ++++++++++++++++++++++++++++++++++++--------- 5 files changed, 73 insertions(+), 74 deletions(-) diff --git a/arch/s390/include/asm/crw.h b/arch/s390/include/asm/crw.h index 7c31d3e25cd1..bcb9cd2a730a 100644 --- a/arch/s390/include/asm/crw.h +++ b/arch/s390/include/asm/crw.h @@ -52,18 +52,4 @@ void crw_wait_for_channel_report(void); #define CRW_ERC_PERRI 0x07 /* perm. error, facility init */ #define CRW_ERC_PMOD 0x08 /* installed parameters modified */ -static inline int stcrw(struct crw *pcrw) -{ - int ccode; - - asm volatile( - " stcrw 0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (ccode), "=m" (*pcrw) - : "a" (pcrw) - : "cc" ); - return ccode; -} - #endif /* _ASM_S390_CRW_H */ diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index a01376ae1749..93de0b46b489 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -45,6 +45,18 @@ struct pmcw { /* ... in an operand exception. */ } __attribute__ ((packed)); +/* I/O-Interruption Code as stored by TEST PENDING INTERRUPTION (TPI). */ +struct tpi_info { + struct subchannel_id schid; + u32 intparm; + u32 adapter_IO:1; + u32 :1; + u32 isc:3; + u32 :27; + u32 type:3; + u32 :12; +} __packed __aligned(4); + /* Target SCHIB configuration. */ struct schib_config { u64 mba; diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c index 0f8a25f98b10..3d3cd402b376 100644 --- a/drivers/s390/cio/crw.c +++ b/drivers/s390/cio/crw.c @@ -14,6 +14,7 @@ #include #include #include +#include "ioasm.h" static DEFINE_MUTEX(crw_handler_mutex); static crw_handler_t crw_handlers[NR_RSCS]; diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index 789ce783d3e1..8975060af96c 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h @@ -169,49 +169,4 @@ struct ccw_device_private { enum interruption_class int_class; }; -static inline int rsch(struct subchannel_id schid) -{ - register struct subchannel_id reg1 asm("1") = schid; - int ccode; - - asm volatile( - " rsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc", "memory"); - return ccode; -} - -static inline int hsch(struct subchannel_id schid) -{ - register struct subchannel_id reg1 asm("1") = schid; - int ccode; - - asm volatile( - " hsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); - return ccode; -} - -static inline int xsch(struct subchannel_id schid) -{ - register struct subchannel_id reg1 asm("1") = schid; - int ccode; - - asm volatile( - " xsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); - return ccode; -} - #endif diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index be6e2f5e11f7..dce25500812a 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -3,24 +3,10 @@ #include #include +#include #include "orb.h" #include "cio.h" -/* - * TPI info structure - */ -struct tpi_info { - struct subchannel_id schid; - __u32 intparm; /* interruption parameter */ - __u32 adapter_IO : 1; - __u32 reserved2 : 1; - __u32 isc : 3; - __u32 reserved3 : 12; - __u32 int_type : 3; - __u32 reserved4 : 12; -} __attribute__ ((packed)); - - /* * Some S390 specific IO instructions as inline */ @@ -149,4 +135,63 @@ static inline int rchp(struct chp_id chpid) return ccode; } +static inline int rsch(struct subchannel_id schid) +{ + register struct subchannel_id reg1 asm("1") = schid; + int ccode; + + asm volatile( + " rsch\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode) + : "d" (reg1) + : "cc", "memory"); + return ccode; +} + +static inline int hsch(struct subchannel_id schid) +{ + register struct subchannel_id reg1 asm("1") = schid; + int ccode; + + asm volatile( + " hsch\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode) + : "d" (reg1) + : "cc"); + return ccode; +} + +static inline int xsch(struct subchannel_id schid) +{ + register struct subchannel_id reg1 asm("1") = schid; + int ccode; + + asm volatile( + " xsch\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode) + : "d" (reg1) + : "cc"); + return ccode; +} + +static inline int stcrw(struct crw *crw) +{ + int ccode; + + asm volatile( + " stcrw 0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + : "=d" (ccode), "=m" (*crw) + : "a" (crw) + : "cc"); + return ccode; +} + #endif -- cgit v1.2.3-59-g8ed1b From 42248979d5705e056b509cdcfb548e40f708cba8 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 18 Dec 2015 12:59:36 +0100 Subject: s390/cio: Introduce common I/O layer tracepoints Add tracepoints to interrupt handler and core inline assemblies used by the s390 common I/O layer. These tracepoints can be used to monitor and validate hardware and hypervisor requests and responses. Signed-off-by: Peter Oberparleiter Reviewed-by: Sebastian Ott Reviewed-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/Makefile | 5 +- drivers/s390/cio/airq.c | 1 + drivers/s390/cio/cio.c | 2 + drivers/s390/cio/ioasm.h | 25 ++++ drivers/s390/cio/trace.c | 24 +++ drivers/s390/cio/trace.h | 363 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 419 insertions(+), 1 deletion(-) create mode 100644 drivers/s390/cio/trace.c create mode 100644 drivers/s390/cio/trace.h diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile index 8c4a386e97f6..2c7cf0b3c5a0 100644 --- a/drivers/s390/cio/Makefile +++ b/drivers/s390/cio/Makefile @@ -2,8 +2,11 @@ # Makefile for the S/390 common i/o drivers # +# The following is required for define_trace.h to find ./trace.h +CFLAGS_trace.o := -I$(src) + obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o \ - fcx.o itcw.o crw.o ccwreq.o + fcx.o itcw.o crw.o ccwreq.o trace.o ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o obj-y += ccw_device.o cmf.o diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 56eb4ee4deba..99b5db469097 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -89,6 +89,7 @@ static irqreturn_t do_airq_interrupt(int irq, void *dummy) set_cpu_flag(CIF_NOHZ_DELAY); tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + trace_s390_cio_adapter_int(tpi_info); head = &airq_lists[tpi_info->isc]; rcu_read_lock(); hlist_for_each_entry_rcu(airq, head, list) diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5f5c24030405..39a8ae54e9c1 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -41,6 +41,7 @@ #include "blacklist.h" #include "cio_debug.h" #include "chp.h" +#include "trace.h" debug_info_t *cio_debug_msg_id; debug_info_t *cio_debug_trace_id; @@ -539,6 +540,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy) set_cpu_flag(CIF_NOHZ_DELAY); tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + trace_s390_cio_interrupt(tpi_info); irb = this_cpu_ptr(&cio_irb); sch = (struct subchannel *)(unsigned long) tpi_info->intparm; if (!sch) { diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index dce25500812a..11e255a4fbad 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -6,6 +6,7 @@ #include #include "orb.h" #include "cio.h" +#include "trace.h" /* * Some S390 specific IO instructions as inline @@ -25,6 +26,8 @@ static inline int stsch(struct subchannel_id schid, struct schib *addr) : "+d" (ccode), "=m" (*addr) : "d" (reg1), "a" (addr) : "cc"); + trace_s390_cio_stsch(schid, addr, ccode); + return ccode; } @@ -42,6 +45,8 @@ static inline int msch(struct subchannel_id schid, struct schib *addr) : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc"); + trace_s390_cio_msch(schid, addr, ccode); + return ccode; } @@ -57,6 +62,8 @@ static inline int tsch(struct subchannel_id schid, struct irb *addr) : "=d" (ccode), "=m" (*addr) : "d" (reg1), "a" (addr) : "cc"); + trace_s390_cio_tsch(schid, addr, ccode); + return ccode; } @@ -74,6 +81,8 @@ static inline int ssch(struct subchannel_id schid, union orb *addr) : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc", "memory"); + trace_s390_cio_ssch(schid, addr, ccode); + return ccode; } @@ -89,6 +98,8 @@ static inline int csch(struct subchannel_id schid) : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_csch(schid, ccode); + return ccode; } @@ -103,6 +114,8 @@ static inline int tpi(struct tpi_info *addr) : "=d" (ccode), "=m" (*addr) : "a" (addr) : "cc"); + trace_s390_cio_tpi(addr, ccode); + return ccode; } @@ -118,6 +131,8 @@ static inline int chsc(void *chsc_area) : "=d" (cc), "=m" (*(addr_type *) chsc_area) : "d" (chsc_area), "m" (*(addr_type *) chsc_area) : "cc"); + trace_s390_cio_chsc(chsc_area, cc); + return cc; } @@ -132,6 +147,8 @@ static inline int rchp(struct chp_id chpid) " ipm %0\n" " srl %0,28" : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_rchp(chpid, ccode); + return ccode; } @@ -147,6 +164,8 @@ static inline int rsch(struct subchannel_id schid) : "=d" (ccode) : "d" (reg1) : "cc", "memory"); + trace_s390_cio_rsch(schid, ccode); + return ccode; } @@ -162,6 +181,8 @@ static inline int hsch(struct subchannel_id schid) : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_hsch(schid, ccode); + return ccode; } @@ -177,6 +198,8 @@ static inline int xsch(struct subchannel_id schid) : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_xsch(schid, ccode); + return ccode; } @@ -191,6 +214,8 @@ static inline int stcrw(struct crw *crw) : "=d" (ccode), "=m" (*crw) : "a" (crw) : "cc"); + trace_s390_cio_stcrw(crw, ccode); + return ccode; } diff --git a/drivers/s390/cio/trace.c b/drivers/s390/cio/trace.c new file mode 100644 index 000000000000..8e706669ac8b --- /dev/null +++ b/drivers/s390/cio/trace.c @@ -0,0 +1,24 @@ +/* + * Tracepoint definitions for s390_cio + * + * Copyright IBM Corp. 2015 + * Author(s): Peter Oberparleiter + */ + +#include +#include "cio.h" + +#define CREATE_TRACE_POINTS +#include "trace.h" + +EXPORT_TRACEPOINT_SYMBOL(s390_cio_stsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_msch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_tsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_tpi); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_ssch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_csch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_hsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_xsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_rsch); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_rchp); +EXPORT_TRACEPOINT_SYMBOL(s390_cio_chsc); diff --git a/drivers/s390/cio/trace.h b/drivers/s390/cio/trace.h new file mode 100644 index 000000000000..5b807a09f21b --- /dev/null +++ b/drivers/s390/cio/trace.h @@ -0,0 +1,363 @@ +/* + * Tracepoint header for the s390 Common I/O layer (CIO) + * + * Copyright IBM Corp. 2015 + * Author(s): Peter Oberparleiter + */ + +#include +#include +#include +#include +#include "cio.h" +#include "orb.h" + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM s390 + +#if !defined(_TRACE_S390_CIO_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_S390_CIO_H + +#include + +DECLARE_EVENT_CLASS(s390_class_schib, + TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc), + TP_ARGS(schid, schib, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + __field(u16, devno) + __field_struct(struct schib, schib) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = schid.cssid; + __entry->ssid = schid.ssid; + __entry->schno = schid.sch_no; + __entry->devno = schib->pmcw.dev; + __entry->schib = *schib; + __entry->cc = cc; + ), + TP_printk("schid=%x.%x.%04x cc=%d ena=%d st=%d dnv=%d dev=%04x " + "lpm=0x%02x pnom=0x%02x lpum=0x%02x pim=0x%02x pam=0x%02x " + "pom=0x%02x chpids=%016llx", + __entry->cssid, __entry->ssid, __entry->schno, __entry->cc, + __entry->schib.pmcw.ena, __entry->schib.pmcw.st, + __entry->schib.pmcw.dnv, __entry->schib.pmcw.dev, + __entry->schib.pmcw.lpm, __entry->schib.pmcw.pnom, + __entry->schib.pmcw.lpum, __entry->schib.pmcw.pim, + __entry->schib.pmcw.pam, __entry->schib.pmcw.pom, + *((u64 *) __entry->schib.pmcw.chpid) + ) +); + +/** + * s390_cio_stsch - Store Subchannel instruction (STSCH) was performed + * @schid: Subchannel ID + * @schib: Subchannel-Information block + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schib, s390_cio_stsch, + TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc), + TP_ARGS(schid, schib, cc) +); + +/** + * s390_cio_msch - Modify Subchannel instruction (MSCH) was performed + * @schid: Subchannel ID + * @schib: Subchannel-Information block + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schib, s390_cio_msch, + TP_PROTO(struct subchannel_id schid, struct schib *schib, int cc), + TP_ARGS(schid, schib, cc) +); + +/** + * s390_cio_tsch - Test Subchannel instruction (TSCH) was performed + * @schid: Subchannel ID + * @irb: Interruption-Response Block + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_tsch, + TP_PROTO(struct subchannel_id schid, struct irb *irb, int cc), + TP_ARGS(schid, irb, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + __field_struct(struct irb, irb) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = schid.cssid; + __entry->ssid = schid.ssid; + __entry->schno = schid.sch_no; + __entry->irb = *irb; + __entry->cc = cc; + ), + TP_printk("schid=%x.%x.%04x cc=%d dcc=%d pno=%d fctl=0x%x actl=0x%x " + "stctl=0x%x dstat=0x%x cstat=0x%x", + __entry->cssid, __entry->ssid, __entry->schno, __entry->cc, + scsw_cc(&__entry->irb.scsw), scsw_pno(&__entry->irb.scsw), + scsw_fctl(&__entry->irb.scsw), scsw_actl(&__entry->irb.scsw), + scsw_stctl(&__entry->irb.scsw), + scsw_dstat(&__entry->irb.scsw), scsw_cstat(&__entry->irb.scsw) + ) +); + +/** + * s390_cio_tpi - Test Pending Interruption instruction (TPI) was performed + * @addr: Address of the I/O interruption code or %NULL + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_tpi, + TP_PROTO(struct tpi_info *addr, int cc), + TP_ARGS(addr, cc), + TP_STRUCT__entry( + __field(int, cc) + __field_struct(struct tpi_info, tpi_info) + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + ), + TP_fast_assign( + __entry->cc = cc; + if (cc != 0) + memset(&__entry->tpi_info, 0, sizeof(struct tpi_info)); + else if (addr) + __entry->tpi_info = *addr; + else { + memcpy(&__entry->tpi_info, &S390_lowcore.subchannel_id, + sizeof(struct tpi_info)); + } + __entry->cssid = __entry->tpi_info.schid.cssid; + __entry->ssid = __entry->tpi_info.schid.ssid; + __entry->schno = __entry->tpi_info.schid.sch_no; + ), + TP_printk("schid=%x.%x.%04x cc=%d a=%d isc=%d type=%d", + __entry->cssid, __entry->ssid, __entry->schno, __entry->cc, + __entry->tpi_info.adapter_IO, __entry->tpi_info.isc, + __entry->tpi_info.type + ) +); + +/** + * s390_cio_ssch - Start Subchannel instruction (SSCH) was performed + * @schid: Subchannel ID + * @orb: Operation-Request Block + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_ssch, + TP_PROTO(struct subchannel_id schid, union orb *orb, int cc), + TP_ARGS(schid, orb, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + __field_struct(union orb, orb) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = schid.cssid; + __entry->ssid = schid.ssid; + __entry->schno = schid.sch_no; + __entry->orb = *orb; + __entry->cc = cc; + ), + TP_printk("schid=%x.%x.%04x cc=%d", __entry->cssid, __entry->ssid, + __entry->schno, __entry->cc + ) +); + +DECLARE_EVENT_CLASS(s390_class_schid, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = schid.cssid; + __entry->ssid = schid.ssid; + __entry->schno = schid.sch_no; + __entry->cc = cc; + ), + TP_printk("schid=%x.%x.%04x cc=%d", __entry->cssid, __entry->ssid, + __entry->schno, __entry->cc + ) +); + +/** + * s390_cio_csch - Clear Subchannel instruction (CSCH) was performed + * @schid: Subchannel ID + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schid, s390_cio_csch, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc) +); + +/** + * s390_cio_hsch - Halt Subchannel instruction (HSCH) was performed + * @schid: Subchannel ID + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schid, s390_cio_hsch, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc) +); + +/** + * s390_cio_xsch - Cancel Subchannel instruction (XSCH) was performed + * @schid: Subchannel ID + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schid, s390_cio_xsch, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc) +); + +/** + * s390_cio_rsch - Resume Subchannel instruction (RSCH) was performed + * @schid: Subchannel ID + * @cc: Condition code + */ +DEFINE_EVENT(s390_class_schid, s390_cio_rsch, + TP_PROTO(struct subchannel_id schid, int cc), + TP_ARGS(schid, cc) +); + +/** + * s390_cio_rchp - Reset Channel Path (RCHP) instruction was performed + * @chpid: Channel-Path Identifier + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_rchp, + TP_PROTO(struct chp_id chpid, int cc), + TP_ARGS(chpid, cc), + TP_STRUCT__entry( + __field(u8, cssid) + __field(u8, id) + __field(int, cc) + ), + TP_fast_assign( + __entry->cssid = chpid.cssid; + __entry->id = chpid.id; + __entry->cc = cc; + ), + TP_printk("chpid=%x.%02x cc=%d", __entry->cssid, __entry->id, + __entry->cc + ) +); + +#define CHSC_MAX_REQUEST_LEN 64 +#define CHSC_MAX_RESPONSE_LEN 64 + +/** + * s390_cio_chsc - Channel Subsystem Call (CHSC) instruction was performed + * @chsc: CHSC block + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_chsc, + TP_PROTO(struct chsc_header *chsc, int cc), + TP_ARGS(chsc, cc), + TP_STRUCT__entry( + __field(int, cc) + __field(u16, code) + __field(u16, rcode) + __array(u8, request, CHSC_MAX_REQUEST_LEN) + __array(u8, response, CHSC_MAX_RESPONSE_LEN) + ), + TP_fast_assign( + __entry->cc = cc; + __entry->code = chsc->code; + memcpy(&entry->request, chsc, + min_t(u16, chsc->length, CHSC_MAX_REQUEST_LEN)); + chsc = (struct chsc_header *) ((char *) chsc + chsc->length); + __entry->rcode = chsc->code; + memcpy(&entry->response, chsc, + min_t(u16, chsc->length, CHSC_MAX_RESPONSE_LEN)); + ), + TP_printk("code=0x%04x cc=%d rcode=0x%04x", __entry->code, + __entry->cc, __entry->rcode) +); + +/** + * s390_cio_interrupt - An I/O interrupt occurred + * @tpi_info: Address of the I/O interruption code + */ +TRACE_EVENT(s390_cio_interrupt, + TP_PROTO(struct tpi_info *tpi_info), + TP_ARGS(tpi_info), + TP_STRUCT__entry( + __field_struct(struct tpi_info, tpi_info) + __field(u8, cssid) + __field(u8, ssid) + __field(u16, schno) + ), + TP_fast_assign( + __entry->tpi_info = *tpi_info; + __entry->cssid = __entry->tpi_info.schid.cssid; + __entry->ssid = __entry->tpi_info.schid.ssid; + __entry->schno = __entry->tpi_info.schid.sch_no; + ), + TP_printk("schid=%x.%x.%04x isc=%d type=%d", + __entry->cssid, __entry->ssid, __entry->schno, + __entry->tpi_info.isc, __entry->tpi_info.type + ) +); + +/** + * s390_cio_adapter_int - An adapter interrupt occurred + * @tpi_info: Address of the I/O interruption code + */ +TRACE_EVENT(s390_cio_adapter_int, + TP_PROTO(struct tpi_info *tpi_info), + TP_ARGS(tpi_info), + TP_STRUCT__entry( + __field_struct(struct tpi_info, tpi_info) + ), + TP_fast_assign( + __entry->tpi_info = *tpi_info; + ), + TP_printk("isc=%d", __entry->tpi_info.isc) +); + +/** + * s390_cio_stcrw - Store Channel Report Word (STCRW) was performed + * @crw: Channel Report Word + * @cc: Condition code + */ +TRACE_EVENT(s390_cio_stcrw, + TP_PROTO(struct crw *crw, int cc), + TP_ARGS(crw, cc), + TP_STRUCT__entry( + __field_struct(struct crw, crw) + __field(int, cc) + ), + TP_fast_assign( + __entry->crw = *crw; + __entry->cc = cc; + ), + TP_printk("cc=%d slct=%d oflw=%d chn=%d rsc=%d anc=%d erc=0x%x " + "rsid=0x%x", + __entry->cc, __entry->crw.slct, __entry->crw.oflw, + __entry->crw.chn, __entry->crw.rsc, __entry->crw.anc, + __entry->crw.erc, __entry->crw.rsid + ) +); + +#endif /* _TRACE_S390_CIO_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +#include -- cgit v1.2.3-59-g8ed1b From 11b64c8acca05d7e50a873e0e8758b75d6d6650f Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 18 Dec 2015 12:59:40 +0100 Subject: s390/cio: Change I/O instructions from inline to normal functions Adding tracepoints to inline functions adds tracepoint invocation code for each instance where the function is inlined. The resulting increase in kernel code size can have negative impact: - More cache misses in instruction cache - Reduced amount of DMA-capable memory Therefore change all functions implementing I/O instructions from inline to normal functions. Bloat-o-meter summary after change (using performance_defconfig): add/remove: 24/2 grow/shrink: 4/39 up/down: 2205/-4858 (-2653) Signed-off-by: Peter Oberparleiter Acked-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/Makefile | 2 +- drivers/s390/cio/ioasm.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/s390/cio/ioasm.h | 220 +++------------------------------------------ 3 files changed, 238 insertions(+), 208 deletions(-) create mode 100644 drivers/s390/cio/ioasm.c diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile index 2c7cf0b3c5a0..3ab9aedeb84a 100644 --- a/drivers/s390/cio/Makefile +++ b/drivers/s390/cio/Makefile @@ -6,7 +6,7 @@ CFLAGS_trace.o := -I$(src) obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o \ - fcx.o itcw.o crw.o ccwreq.o trace.o + fcx.o itcw.o crw.o ccwreq.o trace.o ioasm.o ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o obj-y += ccw_device.o cmf.o diff --git a/drivers/s390/cio/ioasm.c b/drivers/s390/cio/ioasm.c new file mode 100644 index 000000000000..98984818618f --- /dev/null +++ b/drivers/s390/cio/ioasm.c @@ -0,0 +1,224 @@ +/* + * Channel subsystem I/O instructions. + */ + +#include + +#include +#include +#include + +#include "ioasm.h" +#include "orb.h" +#include "cio.h" + +int stsch(struct subchannel_id schid, struct schib *addr) +{ + register struct subchannel_id reg1 asm ("1") = schid; + int ccode = -EIO; + + asm volatile( + " stsch 0(%3)\n" + "0: ipm %0\n" + " srl %0,28\n" + "1:\n" + EX_TABLE(0b, 1b) + : "+d" (ccode), "=m" (*addr) + : "d" (reg1), "a" (addr) + : "cc"); + trace_s390_cio_stsch(schid, addr, ccode); + + return ccode; +} +EXPORT_SYMBOL(stsch); + +int msch(struct subchannel_id schid, struct schib *addr) +{ + register struct subchannel_id reg1 asm ("1") = schid; + int ccode = -EIO; + + asm volatile( + " msch 0(%2)\n" + "0: ipm %0\n" + " srl %0,28\n" + "1:\n" + EX_TABLE(0b, 1b) + : "+d" (ccode) + : "d" (reg1), "a" (addr), "m" (*addr) + : "cc"); + trace_s390_cio_msch(schid, addr, ccode); + + return ccode; +} + +int tsch(struct subchannel_id schid, struct irb *addr) +{ + register struct subchannel_id reg1 asm ("1") = schid; + int ccode; + + asm volatile( + " tsch 0(%3)\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode), "=m" (*addr) + : "d" (reg1), "a" (addr) + : "cc"); + trace_s390_cio_tsch(schid, addr, ccode); + + return ccode; +} + +int ssch(struct subchannel_id schid, union orb *addr) +{ + register struct subchannel_id reg1 asm("1") = schid; + int ccode = -EIO; + + asm volatile( + " ssch 0(%2)\n" + "0: ipm %0\n" + " srl %0,28\n" + "1:\n" + EX_TABLE(0b, 1b) + : "+d" (ccode) + : "d" (reg1), "a" (addr), "m" (*addr) + : "cc", "memory"); + trace_s390_cio_ssch(schid, addr, ccode); + + return ccode; +} +EXPORT_SYMBOL(ssch); + +int csch(struct subchannel_id schid) +{ + register struct subchannel_id reg1 asm("1") = schid; + int ccode; + + asm volatile( + " csch\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode) + : "d" (reg1) + : "cc"); + trace_s390_cio_csch(schid, ccode); + + return ccode; +} +EXPORT_SYMBOL(csch); + +int tpi(struct tpi_info *addr) +{ + int ccode; + + asm volatile( + " tpi 0(%2)\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode), "=m" (*addr) + : "a" (addr) + : "cc"); + trace_s390_cio_tpi(addr, ccode); + + return ccode; +} + +int chsc(void *chsc_area) +{ + typedef struct { char _[4096]; } addr_type; + int cc; + + asm volatile( + " .insn rre,0xb25f0000,%2,0\n" + " ipm %0\n" + " srl %0,28\n" + : "=d" (cc), "=m" (*(addr_type *) chsc_area) + : "d" (chsc_area), "m" (*(addr_type *) chsc_area) + : "cc"); + trace_s390_cio_chsc(chsc_area, cc); + + return cc; +} +EXPORT_SYMBOL(chsc); + +int rchp(struct chp_id chpid) +{ + register struct chp_id reg1 asm ("1") = chpid; + int ccode; + + asm volatile( + " lr 1,%1\n" + " rchp\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode) : "d" (reg1) : "cc"); + trace_s390_cio_rchp(chpid, ccode); + + return ccode; +} + +int rsch(struct subchannel_id schid) +{ + register struct subchannel_id reg1 asm("1") = schid; + int ccode; + + asm volatile( + " rsch\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode) + : "d" (reg1) + : "cc", "memory"); + trace_s390_cio_rsch(schid, ccode); + + return ccode; +} + +int hsch(struct subchannel_id schid) +{ + register struct subchannel_id reg1 asm("1") = schid; + int ccode; + + asm volatile( + " hsch\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode) + : "d" (reg1) + : "cc"); + trace_s390_cio_hsch(schid, ccode); + + return ccode; +} + +int xsch(struct subchannel_id schid) +{ + register struct subchannel_id reg1 asm("1") = schid; + int ccode; + + asm volatile( + " xsch\n" + " ipm %0\n" + " srl %0,28" + : "=d" (ccode) + : "d" (reg1) + : "cc"); + trace_s390_cio_xsch(schid, ccode); + + return ccode; +} + +int stcrw(struct crw *crw) +{ + int ccode; + + asm volatile( + " stcrw 0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + : "=d" (ccode), "=m" (*crw) + : "a" (crw) + : "cc"); + trace_s390_cio_stcrw(crw, ccode); + + return ccode; +} diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index 11e255a4fbad..b31ee6bff1e4 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h @@ -9,214 +9,20 @@ #include "trace.h" /* - * Some S390 specific IO instructions as inline + * Some S390 specific IO instructions */ -static inline int stsch(struct subchannel_id schid, struct schib *addr) -{ - register struct subchannel_id reg1 asm ("1") = schid; - int ccode = -EIO; - - asm volatile( - " stsch 0(%3)\n" - "0: ipm %0\n" - " srl %0,28\n" - "1:\n" - EX_TABLE(0b,1b) - : "+d" (ccode), "=m" (*addr) - : "d" (reg1), "a" (addr) - : "cc"); - trace_s390_cio_stsch(schid, addr, ccode); - - return ccode; -} - -static inline int msch(struct subchannel_id schid, struct schib *addr) -{ - register struct subchannel_id reg1 asm ("1") = schid; - int ccode = -EIO; - - asm volatile( - " msch 0(%2)\n" - "0: ipm %0\n" - " srl %0,28\n" - "1:\n" - EX_TABLE(0b,1b) - : "+d" (ccode) - : "d" (reg1), "a" (addr), "m" (*addr) - : "cc"); - trace_s390_cio_msch(schid, addr, ccode); - - return ccode; -} - -static inline int tsch(struct subchannel_id schid, struct irb *addr) -{ - register struct subchannel_id reg1 asm ("1") = schid; - int ccode; - - asm volatile( - " tsch 0(%3)\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode), "=m" (*addr) - : "d" (reg1), "a" (addr) - : "cc"); - trace_s390_cio_tsch(schid, addr, ccode); - - return ccode; -} - -static inline int ssch(struct subchannel_id schid, union orb *addr) -{ - register struct subchannel_id reg1 asm("1") = schid; - int ccode = -EIO; - - asm volatile( - " ssch 0(%2)\n" - "0: ipm %0\n" - " srl %0,28\n" - "1:\n" - EX_TABLE(0b, 1b) - : "+d" (ccode) - : "d" (reg1), "a" (addr), "m" (*addr) - : "cc", "memory"); - trace_s390_cio_ssch(schid, addr, ccode); - - return ccode; -} - -static inline int csch(struct subchannel_id schid) -{ - register struct subchannel_id reg1 asm("1") = schid; - int ccode; - - asm volatile( - " csch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); - trace_s390_cio_csch(schid, ccode); - - return ccode; -} - -static inline int tpi(struct tpi_info *addr) -{ - int ccode; - - asm volatile( - " tpi 0(%2)\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode), "=m" (*addr) - : "a" (addr) - : "cc"); - trace_s390_cio_tpi(addr, ccode); - - return ccode; -} - -static inline int chsc(void *chsc_area) -{ - typedef struct { char _[4096]; } addr_type; - int cc; - - asm volatile( - " .insn rre,0xb25f0000,%2,0\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (cc), "=m" (*(addr_type *) chsc_area) - : "d" (chsc_area), "m" (*(addr_type *) chsc_area) - : "cc"); - trace_s390_cio_chsc(chsc_area, cc); - - return cc; -} - -static inline int rchp(struct chp_id chpid) -{ - register struct chp_id reg1 asm ("1") = chpid; - int ccode; - - asm volatile( - " lr 1,%1\n" - " rchp\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) : "d" (reg1) : "cc"); - trace_s390_cio_rchp(chpid, ccode); - - return ccode; -} - -static inline int rsch(struct subchannel_id schid) -{ - register struct subchannel_id reg1 asm("1") = schid; - int ccode; - - asm volatile( - " rsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc", "memory"); - trace_s390_cio_rsch(schid, ccode); - - return ccode; -} - -static inline int hsch(struct subchannel_id schid) -{ - register struct subchannel_id reg1 asm("1") = schid; - int ccode; - - asm volatile( - " hsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); - trace_s390_cio_hsch(schid, ccode); - - return ccode; -} - -static inline int xsch(struct subchannel_id schid) -{ - register struct subchannel_id reg1 asm("1") = schid; - int ccode; - - asm volatile( - " xsch\n" - " ipm %0\n" - " srl %0,28" - : "=d" (ccode) - : "d" (reg1) - : "cc"); - trace_s390_cio_xsch(schid, ccode); - - return ccode; -} - -static inline int stcrw(struct crw *crw) -{ - int ccode; - - asm volatile( - " stcrw 0(%2)\n" - " ipm %0\n" - " srl %0,28\n" - : "=d" (ccode), "=m" (*crw) - : "a" (crw) - : "cc"); - trace_s390_cio_stcrw(crw, ccode); - - return ccode; -} +int stsch(struct subchannel_id schid, struct schib *addr); +int msch(struct subchannel_id schid, struct schib *addr); +int tsch(struct subchannel_id schid, struct irb *addr); +int ssch(struct subchannel_id schid, union orb *addr); +int csch(struct subchannel_id schid); +int tpi(struct tpi_info *addr); +int chsc(void *chsc_area); +int rchp(struct chp_id chpid); +int rsch(struct subchannel_id schid); +int hsch(struct subchannel_id schid); +int xsch(struct subchannel_id schid); +int stcrw(struct crw *crw); #endif -- cgit v1.2.3-59-g8ed1b From 8cb708f3d35e78f00528caf2f681900d2c7883b8 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 20 Dec 2015 12:15:52 +0100 Subject: s390/cio: add NULL test Add NULL test on call to kzalloc. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x; identifier fld; @@ * x = kzalloc(...); ... when != x == NULL x->fld // Signed-off-by: Julia Lawall Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/con3215.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 0fc3fe5fd5b8..7d82bbcb12df 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -922,6 +922,8 @@ static int __init con3215_init(void) spin_lock_init(&raw3215_freelist_lock); for (i = 0; i < NR_3215_REQ; i++) { req = kzalloc(sizeof(struct raw3215_req), GFP_KERNEL | GFP_DMA); + if (!req) + return -ENOMEM; req->next = raw3215_freelist; raw3215_freelist = req; } -- cgit v1.2.3-59-g8ed1b From c967e1df169d033b2da74e979e91b6e297e194fa Mon Sep 17 00:00:00 2001 From: Aya Mahfouz Date: Sun, 13 Dec 2015 20:51:49 +0200 Subject: s390/hmcdrv: constify hmcdrv_ftp_ops structs Constifies hmcdrv_ftp_ops structures in s390's char driver since they are not modified after their initialization. Detected and found using Coccinelle. Suggested-by: Julia Lawall Signed-off-by: Aya Mahfouz Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/hmcdrv_ftp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/s390/char/hmcdrv_ftp.c b/drivers/s390/char/hmcdrv_ftp.c index d4b61d9088fb..8cb7d8fbadd6 100644 --- a/drivers/s390/char/hmcdrv_ftp.c +++ b/drivers/s390/char/hmcdrv_ftp.c @@ -37,7 +37,7 @@ struct hmcdrv_ftp_ops { static enum hmcdrv_ftp_cmdid hmcdrv_ftp_cmd_getid(const char *cmd, int len); static int hmcdrv_ftp_parse(char *cmd, struct hmcdrv_ftp_cmdspec *ftp); -static struct hmcdrv_ftp_ops *hmcdrv_ftp_funcs; /* current operations */ +static const struct hmcdrv_ftp_ops *hmcdrv_ftp_funcs; /* current operations */ static DEFINE_MUTEX(hmcdrv_ftp_mutex); /* mutex for hmcdrv_ftp_funcs */ static unsigned hmcdrv_ftp_refcnt; /* start/shutdown reference counter */ @@ -290,13 +290,13 @@ ssize_t hmcdrv_ftp_cmd(char __kernel *cmd, loff_t offset, */ int hmcdrv_ftp_startup(void) { - static struct hmcdrv_ftp_ops hmcdrv_ftp_zvm = { + static const struct hmcdrv_ftp_ops hmcdrv_ftp_zvm = { .startup = diag_ftp_startup, .shutdown = diag_ftp_shutdown, .transfer = diag_ftp_cmd }; - static struct hmcdrv_ftp_ops hmcdrv_ftp_lpar = { + static const struct hmcdrv_ftp_ops hmcdrv_ftp_lpar = { .startup = sclp_ftp_startup, .shutdown = sclp_ftp_shutdown, .transfer = sclp_ftp_cmd -- cgit v1.2.3-59-g8ed1b From cf61393f4aa30f4c2a11cf2437d49ff4de6eb4fb Mon Sep 17 00:00:00 2001 From: Pierre Morel Date: Mon, 21 Dec 2015 15:31:06 +0100 Subject: s390/con3270: testing return kzalloc retval Return value from kzalloc is not tested and using a null pointer would lead to crash. Even if this should not happen at this moment, we may let the system decide if there is a better choice. Signed-off-by: Pierre Morel Signed-off-by: Martin Schwidefsky --- drivers/s390/char/con3270.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 7c511add5aa7..4d7a9badfede 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -606,6 +606,8 @@ con3270_init(void) return PTR_ERR(rp); condev = kzalloc(sizeof(struct con3270), GFP_KERNEL | GFP_DMA); + if (!condev) + return -ENOMEM; condev->view.dev = rp; condev->read = raw3270_request_alloc(0); -- cgit v1.2.3-59-g8ed1b From c6fc7b6f8ca5d3d59446ce4ee870569355cfb04a Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Tue, 22 Dec 2015 13:34:38 +0100 Subject: s390/dasd: fix failfast for disconnected devices Enabling failfast should let request fail immediately if either an error occurred or the device gets disconnected. For disconnected devices new requests are not fetches from the block queue and therefore failfast is not triggered. Fix by letting the DASD driver fetch requests for disconnected devices with failfast active. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index a263c10359e1..41605dac8309 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2556,8 +2556,12 @@ static void __dasd_process_request_queue(struct dasd_block *block) return; } - /* if device ist stopped do not fetch new requests */ - if (basedev->stopped) + /* + * if device is stopped do not fetch new requests + * except failfast is active which will let requests fail + * immediately in __dasd_block_start_head() + */ + if (basedev->stopped && !(basedev->features & DASD_FEATURE_FAILFAST)) return; /* Now we try to fetch requests from the request queue */ -- cgit v1.2.3-59-g8ed1b From c095a94932ceee19fe36942aa49df7276f9e30b5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 28 Dec 2015 12:53:51 +0100 Subject: s390/Kconfig: remove pointless 64 bit dependencies s390 is always 64 bit. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 3a55f493c7da..d66a7c47faf3 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -166,8 +166,7 @@ config SCHED_OMIT_FRAME_POINTER config PGTABLE_LEVELS int - default 4 if 64BIT - default 2 + default 4 source "init/Kconfig" @@ -403,7 +402,7 @@ config NODES_SPAN_OTHER_NODES config NUMA bool "NUMA support" - depends on SMP && 64BIT && SCHED_TOPOLOGY + depends on SMP && SCHED_TOPOLOGY default n help Enable NUMA support -- cgit v1.2.3-59-g8ed1b From 9236b4dd6bfabefcf2063544083a66cd5f3a738d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 28 Dec 2015 13:20:43 +0100 Subject: s390: get rid of CONFIG_SCHED_MC and CONFIG_SCHED_BOOK Use CONFIG_TOPOLOGY which selects CONFIG_SCHED_* all over the place to reduce the random usage of the previous config options. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 6 +++--- arch/s390/include/asm/topology.h | 6 +++--- arch/s390/kernel/Makefile | 2 +- arch/s390/kernel/sysinfo.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index d66a7c47faf3..6d0ae7d30724 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -389,9 +389,6 @@ config HOTPLUG_CPU can be controlled through /sys/devices/system/cpu/cpu#. Say N if you want to disable CPU hotplug. -config SCHED_SMT - def_bool n - # Some NUMA nodes have memory ranges that span # other nodes. Even though a pfn is valid and # between a node's start and end pfns, it may not @@ -462,6 +459,9 @@ config EMU_SIZE endmenu +config SCHED_SMT + def_bool n + config SCHED_MC def_bool n diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index 94fc55fc72ce..6b53962e807e 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h @@ -7,7 +7,7 @@ struct sysinfo_15_1_x; struct cpu; -#ifdef CONFIG_SCHED_BOOK +#ifdef CONFIG_SCHED_TOPOLOGY struct cpu_topology_s390 { unsigned short thread_id; @@ -40,13 +40,13 @@ void store_topology(struct sysinfo_15_1_x *info); void topology_expect_change(void); const struct cpumask *cpu_coregroup_mask(int cpu); -#else /* CONFIG_SCHED_BOOK */ +#else /* CONFIG_SCHED_TOPOLOGY */ static inline void topology_schedule_update(void) { } static inline int topology_cpu_init(struct cpu *cpu) { return 0; } static inline void topology_expect_change(void) { } -#endif /* CONFIG_SCHED_BOOK */ +#endif /* CONFIG_SCHED_TOPOLOGY */ #define POLARIZATION_UNKNOWN (-1) #define POLARIZATION_HRZ (0) diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index e9a328d42610..2f5586ab8a6a 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -52,7 +52,7 @@ extra-y += head.o head64.o vmlinux.lds obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SCHED_BOOK) += topology.o +obj-$(CONFIG_SCHED_TOPOLOGY) += topology.o obj-$(CONFIG_HIBERNATION) += suspend.o swsusp.o obj-$(CONFIG_AUDIT) += audit.o compat-obj-$(CONFIG_AUDIT) += compat_audit.o diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index efacda2fc568..0512f944eaf3 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -122,7 +122,7 @@ static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info) for (i = 0; i < TOPOLOGY_NR_MAG; i++) seq_printf(m, " %d", info->mag[i]); seq_putc(m, '\n'); -#ifdef CONFIG_SCHED_MC +#ifdef CONFIG_SCHED_TOPOLOGY store_topology(info); seq_printf(m, "CPU Topology SW: "); for (i = 0; i < TOPOLOGY_NR_MAG; i++) -- cgit v1.2.3-59-g8ed1b From 7022ec496005b47257b8c0a1c1a40df92df7c79f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 30 Dec 2015 13:42:37 +0100 Subject: s390/sysinfo: add missing SYSIB 1.2.2 multithreading fields Add missing multithreading fields of SYSIB 1.2.2 (Basic-Machine CPUs) to the output of /proc/sysinfo. Also use bitfields for SYSIB 2.2.2 to simplify the C code a bit. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/sysinfo.h | 17 +++++++++++++---- arch/s390/kernel/sysinfo.c | 15 ++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index f7054a892d9e..2728114d5484 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h @@ -56,7 +56,12 @@ struct sysinfo_1_2_2 { char format; char reserved_0[1]; unsigned short acc_offset; - char reserved_1[20]; + unsigned char mt_installed :1; + unsigned char :2; + unsigned char mt_stid :5; + unsigned char :3; + unsigned char mt_gtid :5; + char reserved_1[18]; unsigned int nominal_cap; unsigned int secondary_cap; unsigned int capability; @@ -92,9 +97,13 @@ struct sysinfo_2_2_2 { char name[8]; unsigned int caf; char reserved_2[8]; - unsigned char mt_installed; - unsigned char mt_general; - unsigned char mt_psmtid; + unsigned char mt_installed :1; + unsigned char :2; + unsigned char mt_stid :5; + unsigned char :3; + unsigned char mt_gtid :5; + unsigned char :3; + unsigned char mt_psmtid :5; char reserved_3[5]; unsigned short cpus_dedicated; unsigned short cpus_shared; diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 0512f944eaf3..f7dba3887a54 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -144,6 +144,10 @@ static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info) seq_printf(m, "CPUs Configured: %d\n", info->cpus_configured); seq_printf(m, "CPUs Standby: %d\n", info->cpus_standby); seq_printf(m, "CPUs Reserved: %d\n", info->cpus_reserved); + if (info->mt_installed) { + seq_printf(m, "CPUs G-MTID: %d\n", info->mt_gtid); + seq_printf(m, "CPUs S-MTID: %d\n", info->mt_stid); + } /* * Sigh 2. According to the specification the alternate * capability field is a 32 bit floating point number @@ -193,13 +197,10 @@ static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info) seq_printf(m, "LPAR CPUs Reserved: %d\n", info->cpus_reserved); seq_printf(m, "LPAR CPUs Dedicated: %d\n", info->cpus_dedicated); seq_printf(m, "LPAR CPUs Shared: %d\n", info->cpus_shared); - if (info->mt_installed & 0x80) { - seq_printf(m, "LPAR CPUs G-MTID: %d\n", - info->mt_general & 0x1f); - seq_printf(m, "LPAR CPUs S-MTID: %d\n", - info->mt_installed & 0x1f); - seq_printf(m, "LPAR CPUs PS-MTID: %d\n", - info->mt_psmtid & 0x1f); + if (info->mt_installed) { + seq_printf(m, "LPAR CPUs G-MTID: %d\n", info->mt_gtid); + seq_printf(m, "LPAR CPUs S-MTID: %d\n", info->mt_stid); + seq_printf(m, "LPAR CPUs PS-MTID: %d\n", info->mt_psmtid); } } -- cgit v1.2.3-59-g8ed1b From cb951785a78c68bf802f5e3d9016b0205ddd24c2 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 31 Dec 2015 09:58:02 +0100 Subject: s390/ptrace: get rid of long longs in psw_bits The long longs were introduced by me in order to have a working definition of the struct psw_bits also in 31 bit mode. Since that is gone also get rid of the long longs. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ptrace.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 37cbc50947f2..f00cd35c8ac4 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -24,25 +24,25 @@ PSW_MASK_PSTATE | PSW_ASC_PRIMARY) struct psw_bits { - unsigned long long : 1; - unsigned long long r : 1; /* PER-Mask */ - unsigned long long : 3; - unsigned long long t : 1; /* DAT Mode */ - unsigned long long i : 1; /* Input/Output Mask */ - unsigned long long e : 1; /* External Mask */ - unsigned long long key : 4; /* PSW Key */ - unsigned long long : 1; - unsigned long long m : 1; /* Machine-Check Mask */ - unsigned long long w : 1; /* Wait State */ - unsigned long long p : 1; /* Problem State */ - unsigned long long as : 2; /* Address Space Control */ - unsigned long long cc : 2; /* Condition Code */ - unsigned long long pm : 4; /* Program Mask */ - unsigned long long ri : 1; /* Runtime Instrumentation */ - unsigned long long : 6; - unsigned long long eaba : 2; /* Addressing Mode */ - unsigned long long : 31; - unsigned long long ia : 64;/* Instruction Address */ + unsigned long : 1; + unsigned long r : 1; /* PER-Mask */ + unsigned long : 3; + unsigned long t : 1; /* DAT Mode */ + unsigned long i : 1; /* Input/Output Mask */ + unsigned long e : 1; /* External Mask */ + unsigned long key : 4; /* PSW Key */ + unsigned long : 1; + unsigned long m : 1; /* Machine-Check Mask */ + unsigned long w : 1; /* Wait State */ + unsigned long p : 1; /* Problem State */ + unsigned long as : 2; /* Address Space Control */ + unsigned long cc : 2; /* Condition Code */ + unsigned long pm : 4; /* Program Mask */ + unsigned long ri : 1; /* Runtime Instrumentation */ + unsigned long : 6; + unsigned long eaba : 2; /* Addressing Mode */ + unsigned long : 31; + unsigned long ia : 64; /* Instruction Address */ }; enum { -- cgit v1.2.3-59-g8ed1b From 423d5b364c108c00d98e3da9f72d598e8f2ef948 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 31 Dec 2015 10:07:21 +0100 Subject: s390/mem_detect: use unsigned longs The memory detection code historically had to use unsigned long long since the machine reported the true memory size (>4GB) even if the virtual machine was running in ESA/390 mode. Since the old code is gone use unsigned long everywhere and also get rid of an unused ADDR2G define. (this patch converts all long longs within sclp_info to longs) There are many more possible conversions, however that can be done if somebody touches the corresponding code. Since people started to convert unrelated long types to long longs because of the types within struct sclp_info convert this now. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/sclp.h | 8 ++++---- arch/s390/mm/mem_detect.c | 7 ++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index cb691602f295..5e3da0414b47 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -57,12 +57,12 @@ struct sclp_info { unsigned int mtid; unsigned int mtid_cp; unsigned int mtid_prev; - unsigned long long rzm; - unsigned long long rnmax; - unsigned long long hamax; + unsigned long rzm; + unsigned long rnmax; + unsigned long hamax; unsigned int max_cores; unsigned long hsa_size; - unsigned long long facilities; + unsigned long facilities; }; extern struct sclp_info sclp; diff --git a/arch/s390/mm/mem_detect.c b/arch/s390/mm/mem_detect.c index e00f0d5d296d..d612cc3eec6a 100644 --- a/arch/s390/mm/mem_detect.c +++ b/arch/s390/mm/mem_detect.c @@ -14,8 +14,6 @@ #include #include -#define ADDR2G (1ULL << 31) - #define CHUNK_READ_WRITE 0 #define CHUNK_READ_ONLY 1 @@ -27,15 +25,14 @@ static inline void memblock_physmem_add(phys_addr_t start, phys_addr_t size) void __init detect_memory_memblock(void) { - unsigned long long memsize, rnmax, rzm; - unsigned long addr, size; + unsigned long memsize, rnmax, rzm, addr, size; int type; rzm = sclp.rzm; rnmax = sclp.rnmax; memsize = rzm * rnmax; if (!rzm) - rzm = 1ULL << 17; + rzm = 1UL << 17; max_physmem_end = memsize; addr = 0; /* keep memblock lists close to the kernel */ -- cgit v1.2.3-59-g8ed1b From c667aeacc16e0de9e205faa93f57121d6f691973 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 31 Dec 2015 10:29:00 +0100 Subject: s390: rename struct _lowcore to struct lowcore Finally get rid of the leading underscore. I tried this already two or three years ago, however Michael Holzheu objected since this would break the crash utility (again). However Michael integrated support for the new name into the crash utility back then, so it doesn't break if the name will be changed now. So finally get rid of the ever confusing leading underscore. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/lowcore.h | 6 +- arch/s390/include/asm/processor.h | 2 +- arch/s390/include/asm/vdso.h | 4 +- arch/s390/kernel/asm-offsets.c | 174 +++++++++++++++++++------------------- arch/s390/kernel/crash_dump.c | 4 +- arch/s390/kernel/ipl.c | 4 +- arch/s390/kernel/setup.c | 6 +- arch/s390/kernel/smp.c | 16 ++-- arch/s390/kernel/vdso.c | 6 +- arch/s390/kvm/interrupt.c | 4 +- arch/s390/kvm/priv.c | 2 +- arch/s390/mm/maccess.c | 4 +- 12 files changed, 116 insertions(+), 116 deletions(-) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 5dbbf199ba2e..d79ba7cf75b0 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -16,7 +16,7 @@ #define LC_ORDER 1 #define LC_PAGES 2 -struct _lowcore { +struct lowcore { __u8 pad_0x0000[0x0014-0x0000]; /* 0x0000 */ __u32 ipl_parmblock_ptr; /* 0x0014 */ __u8 pad_0x0018[0x0080-0x0018]; /* 0x0018 */ @@ -183,9 +183,9 @@ struct _lowcore { __u8 vector_save_area[1024]; /* 0x1c00 */ } __packed; -#define S390_lowcore (*((struct _lowcore *) 0)) +#define S390_lowcore (*((struct lowcore *) 0)) -extern struct _lowcore *lowcore_ptr[]; +extern struct lowcore *lowcore_ptr[]; static inline void set_prefix(__u32 address) { diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 5592c94ebe31..f16debf6a612 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -60,7 +60,7 @@ static inline int test_cpu_flag(int flag) */ static inline int test_cpu_flag_of(int flag, int cpu) { - struct _lowcore *lc = lowcore_ptr[cpu]; + struct lowcore *lc = lowcore_ptr[cpu]; return !!(lc->cpu_flags & (1UL << flag)); } diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h index 787acd4f9668..f9b02d300d60 100644 --- a/arch/s390/include/asm/vdso.h +++ b/arch/s390/include/asm/vdso.h @@ -42,8 +42,8 @@ struct vdso_per_cpu_data { extern struct vdso_data *vdso_data; -int vdso_alloc_per_cpu(struct _lowcore *lowcore); -void vdso_free_per_cpu(struct _lowcore *lowcore); +int vdso_alloc_per_cpu(struct lowcore *lowcore); +void vdso_free_per_cpu(struct lowcore *lowcore); #endif /* __ASSEMBLY__ */ #endif /* __S390_VDSO_H__ */ diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index d8d18f8d8b77..d5916ef9c619 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -97,96 +97,96 @@ int main(void) OFFSET(__TIMER_IDLE_EXIT, s390_idle_data, timer_idle_exit); BLANK(); /* hardware defined lowcore locations 0x000 - 0x1ff */ - OFFSET(__LC_EXT_PARAMS, _lowcore, ext_params); - OFFSET(__LC_EXT_CPU_ADDR, _lowcore, ext_cpu_addr); - OFFSET(__LC_EXT_INT_CODE, _lowcore, ext_int_code); - OFFSET(__LC_SVC_ILC, _lowcore, svc_ilc); - OFFSET(__LC_SVC_INT_CODE, _lowcore, svc_code); - OFFSET(__LC_PGM_ILC, _lowcore, pgm_ilc); - OFFSET(__LC_PGM_INT_CODE, _lowcore, pgm_code); - OFFSET(__LC_DATA_EXC_CODE, _lowcore, data_exc_code); - OFFSET(__LC_MON_CLASS_NR, _lowcore, mon_class_num); - OFFSET(__LC_PER_CODE, _lowcore, per_code); - OFFSET(__LC_PER_ATMID, _lowcore, per_atmid); - OFFSET(__LC_PER_ADDRESS, _lowcore, per_address); - OFFSET(__LC_EXC_ACCESS_ID, _lowcore, exc_access_id); - OFFSET(__LC_PER_ACCESS_ID, _lowcore, per_access_id); - OFFSET(__LC_OP_ACCESS_ID, _lowcore, op_access_id); - OFFSET(__LC_AR_MODE_ID, _lowcore, ar_mode_id); - OFFSET(__LC_TRANS_EXC_CODE, _lowcore, trans_exc_code); - OFFSET(__LC_MON_CODE, _lowcore, monitor_code); - OFFSET(__LC_SUBCHANNEL_ID, _lowcore, subchannel_id); - OFFSET(__LC_SUBCHANNEL_NR, _lowcore, subchannel_nr); - OFFSET(__LC_IO_INT_PARM, _lowcore, io_int_parm); - OFFSET(__LC_IO_INT_WORD, _lowcore, io_int_word); - OFFSET(__LC_STFL_FAC_LIST, _lowcore, stfl_fac_list); - OFFSET(__LC_STFLE_FAC_LIST, _lowcore, stfle_fac_list); - OFFSET(__LC_MCCK_CODE, _lowcore, mcck_interruption_code); - OFFSET(__LC_MCCK_FAIL_STOR_ADDR, _lowcore, failing_storage_address); - OFFSET(__LC_LAST_BREAK, _lowcore, breaking_event_addr); - OFFSET(__LC_RST_OLD_PSW, _lowcore, restart_old_psw); - OFFSET(__LC_EXT_OLD_PSW, _lowcore, external_old_psw); - OFFSET(__LC_SVC_OLD_PSW, _lowcore, svc_old_psw); - OFFSET(__LC_PGM_OLD_PSW, _lowcore, program_old_psw); - OFFSET(__LC_MCK_OLD_PSW, _lowcore, mcck_old_psw); - OFFSET(__LC_IO_OLD_PSW, _lowcore, io_old_psw); - OFFSET(__LC_RST_NEW_PSW, _lowcore, restart_psw); - OFFSET(__LC_EXT_NEW_PSW, _lowcore, external_new_psw); - OFFSET(__LC_SVC_NEW_PSW, _lowcore, svc_new_psw); - OFFSET(__LC_PGM_NEW_PSW, _lowcore, program_new_psw); - OFFSET(__LC_MCK_NEW_PSW, _lowcore, mcck_new_psw); - OFFSET(__LC_IO_NEW_PSW, _lowcore, io_new_psw); + OFFSET(__LC_EXT_PARAMS, lowcore, ext_params); + OFFSET(__LC_EXT_CPU_ADDR, lowcore, ext_cpu_addr); + OFFSET(__LC_EXT_INT_CODE, lowcore, ext_int_code); + OFFSET(__LC_SVC_ILC, lowcore, svc_ilc); + OFFSET(__LC_SVC_INT_CODE, lowcore, svc_code); + OFFSET(__LC_PGM_ILC, lowcore, pgm_ilc); + OFFSET(__LC_PGM_INT_CODE, lowcore, pgm_code); + OFFSET(__LC_DATA_EXC_CODE, lowcore, data_exc_code); + OFFSET(__LC_MON_CLASS_NR, lowcore, mon_class_num); + OFFSET(__LC_PER_CODE, lowcore, per_code); + OFFSET(__LC_PER_ATMID, lowcore, per_atmid); + OFFSET(__LC_PER_ADDRESS, lowcore, per_address); + OFFSET(__LC_EXC_ACCESS_ID, lowcore, exc_access_id); + OFFSET(__LC_PER_ACCESS_ID, lowcore, per_access_id); + OFFSET(__LC_OP_ACCESS_ID, lowcore, op_access_id); + OFFSET(__LC_AR_MODE_ID, lowcore, ar_mode_id); + OFFSET(__LC_TRANS_EXC_CODE, lowcore, trans_exc_code); + OFFSET(__LC_MON_CODE, lowcore, monitor_code); + OFFSET(__LC_SUBCHANNEL_ID, lowcore, subchannel_id); + OFFSET(__LC_SUBCHANNEL_NR, lowcore, subchannel_nr); + OFFSET(__LC_IO_INT_PARM, lowcore, io_int_parm); + OFFSET(__LC_IO_INT_WORD, lowcore, io_int_word); + OFFSET(__LC_STFL_FAC_LIST, lowcore, stfl_fac_list); + OFFSET(__LC_STFLE_FAC_LIST, lowcore, stfle_fac_list); + OFFSET(__LC_MCCK_CODE, lowcore, mcck_interruption_code); + OFFSET(__LC_MCCK_FAIL_STOR_ADDR, lowcore, failing_storage_address); + OFFSET(__LC_LAST_BREAK, lowcore, breaking_event_addr); + OFFSET(__LC_RST_OLD_PSW, lowcore, restart_old_psw); + OFFSET(__LC_EXT_OLD_PSW, lowcore, external_old_psw); + OFFSET(__LC_SVC_OLD_PSW, lowcore, svc_old_psw); + OFFSET(__LC_PGM_OLD_PSW, lowcore, program_old_psw); + OFFSET(__LC_MCK_OLD_PSW, lowcore, mcck_old_psw); + OFFSET(__LC_IO_OLD_PSW, lowcore, io_old_psw); + OFFSET(__LC_RST_NEW_PSW, lowcore, restart_psw); + OFFSET(__LC_EXT_NEW_PSW, lowcore, external_new_psw); + OFFSET(__LC_SVC_NEW_PSW, lowcore, svc_new_psw); + OFFSET(__LC_PGM_NEW_PSW, lowcore, program_new_psw); + OFFSET(__LC_MCK_NEW_PSW, lowcore, mcck_new_psw); + OFFSET(__LC_IO_NEW_PSW, lowcore, io_new_psw); /* software defined lowcore locations 0x200 - 0xdff*/ - OFFSET(__LC_SAVE_AREA_SYNC, _lowcore, save_area_sync); - OFFSET(__LC_SAVE_AREA_ASYNC, _lowcore, save_area_async); - OFFSET(__LC_SAVE_AREA_RESTART, _lowcore, save_area_restart); - OFFSET(__LC_CPU_FLAGS, _lowcore, cpu_flags); - OFFSET(__LC_RETURN_PSW, _lowcore, return_psw); - OFFSET(__LC_RETURN_MCCK_PSW, _lowcore, return_mcck_psw); - OFFSET(__LC_SYNC_ENTER_TIMER, _lowcore, sync_enter_timer); - OFFSET(__LC_ASYNC_ENTER_TIMER, _lowcore, async_enter_timer); - OFFSET(__LC_MCCK_ENTER_TIMER, _lowcore, mcck_enter_timer); - OFFSET(__LC_EXIT_TIMER, _lowcore, exit_timer); - OFFSET(__LC_USER_TIMER, _lowcore, user_timer); - OFFSET(__LC_SYSTEM_TIMER, _lowcore, system_timer); - OFFSET(__LC_STEAL_TIMER, _lowcore, steal_timer); - OFFSET(__LC_LAST_UPDATE_TIMER, _lowcore, last_update_timer); - OFFSET(__LC_LAST_UPDATE_CLOCK, _lowcore, last_update_clock); - OFFSET(__LC_INT_CLOCK, _lowcore, int_clock); - OFFSET(__LC_MCCK_CLOCK, _lowcore, mcck_clock); - OFFSET(__LC_CURRENT, _lowcore, current_task); - OFFSET(__LC_THREAD_INFO, _lowcore, thread_info); - OFFSET(__LC_KERNEL_STACK, _lowcore, kernel_stack); - OFFSET(__LC_ASYNC_STACK, _lowcore, async_stack); - OFFSET(__LC_PANIC_STACK, _lowcore, panic_stack); - OFFSET(__LC_RESTART_STACK, _lowcore, restart_stack); - OFFSET(__LC_RESTART_FN, _lowcore, restart_fn); - OFFSET(__LC_RESTART_DATA, _lowcore, restart_data); - OFFSET(__LC_RESTART_SOURCE, _lowcore, restart_source); - OFFSET(__LC_USER_ASCE, _lowcore, user_asce); - OFFSET(__LC_LPP, _lowcore, lpp); - OFFSET(__LC_CURRENT_PID, _lowcore, current_pid); - OFFSET(__LC_PERCPU_OFFSET, _lowcore, percpu_offset); - OFFSET(__LC_VDSO_PER_CPU, _lowcore, vdso_per_cpu_data); - OFFSET(__LC_MACHINE_FLAGS, _lowcore, machine_flags); - OFFSET(__LC_GMAP, _lowcore, gmap); - OFFSET(__LC_PASTE, _lowcore, paste); + OFFSET(__LC_SAVE_AREA_SYNC, lowcore, save_area_sync); + OFFSET(__LC_SAVE_AREA_ASYNC, lowcore, save_area_async); + OFFSET(__LC_SAVE_AREA_RESTART, lowcore, save_area_restart); + OFFSET(__LC_CPU_FLAGS, lowcore, cpu_flags); + OFFSET(__LC_RETURN_PSW, lowcore, return_psw); + OFFSET(__LC_RETURN_MCCK_PSW, lowcore, return_mcck_psw); + OFFSET(__LC_SYNC_ENTER_TIMER, lowcore, sync_enter_timer); + OFFSET(__LC_ASYNC_ENTER_TIMER, lowcore, async_enter_timer); + OFFSET(__LC_MCCK_ENTER_TIMER, lowcore, mcck_enter_timer); + OFFSET(__LC_EXIT_TIMER, lowcore, exit_timer); + OFFSET(__LC_USER_TIMER, lowcore, user_timer); + OFFSET(__LC_SYSTEM_TIMER, lowcore, system_timer); + OFFSET(__LC_STEAL_TIMER, lowcore, steal_timer); + OFFSET(__LC_LAST_UPDATE_TIMER, lowcore, last_update_timer); + OFFSET(__LC_LAST_UPDATE_CLOCK, lowcore, last_update_clock); + OFFSET(__LC_INT_CLOCK, lowcore, int_clock); + OFFSET(__LC_MCCK_CLOCK, lowcore, mcck_clock); + OFFSET(__LC_CURRENT, lowcore, current_task); + OFFSET(__LC_THREAD_INFO, lowcore, thread_info); + OFFSET(__LC_KERNEL_STACK, lowcore, kernel_stack); + OFFSET(__LC_ASYNC_STACK, lowcore, async_stack); + OFFSET(__LC_PANIC_STACK, lowcore, panic_stack); + OFFSET(__LC_RESTART_STACK, lowcore, restart_stack); + OFFSET(__LC_RESTART_FN, lowcore, restart_fn); + OFFSET(__LC_RESTART_DATA, lowcore, restart_data); + OFFSET(__LC_RESTART_SOURCE, lowcore, restart_source); + OFFSET(__LC_USER_ASCE, lowcore, user_asce); + OFFSET(__LC_LPP, lowcore, lpp); + OFFSET(__LC_CURRENT_PID, lowcore, current_pid); + OFFSET(__LC_PERCPU_OFFSET, lowcore, percpu_offset); + OFFSET(__LC_VDSO_PER_CPU, lowcore, vdso_per_cpu_data); + OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags); + OFFSET(__LC_GMAP, lowcore, gmap); + OFFSET(__LC_PASTE, lowcore, paste); /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */ - OFFSET(__LC_DUMP_REIPL, _lowcore, ipib); + OFFSET(__LC_DUMP_REIPL, lowcore, ipib); /* hardware defined lowcore locations 0x1000 - 0x18ff */ - OFFSET(__LC_VX_SAVE_AREA_ADDR, _lowcore, vector_save_area_addr); - OFFSET(__LC_EXT_PARAMS2, _lowcore, ext_params2); - OFFSET(__LC_FPREGS_SAVE_AREA, _lowcore, floating_pt_save_area); - OFFSET(__LC_GPREGS_SAVE_AREA, _lowcore, gpregs_save_area); - OFFSET(__LC_PSW_SAVE_AREA, _lowcore, psw_save_area); - OFFSET(__LC_PREFIX_SAVE_AREA, _lowcore, prefixreg_save_area); - OFFSET(__LC_FP_CREG_SAVE_AREA, _lowcore, fpt_creg_save_area); - OFFSET(__LC_TOD_PROGREG_SAVE_AREA, _lowcore, tod_progreg_save_area); - OFFSET(__LC_CPU_TIMER_SAVE_AREA, _lowcore, cpu_timer_save_area); - OFFSET(__LC_CLOCK_COMP_SAVE_AREA, _lowcore, clock_comp_save_area); - OFFSET(__LC_AREGS_SAVE_AREA, _lowcore, access_regs_save_area); - OFFSET(__LC_CREGS_SAVE_AREA, _lowcore, cregs_save_area); - OFFSET(__LC_PGM_TDB, _lowcore, pgm_tdb); + OFFSET(__LC_VX_SAVE_AREA_ADDR, lowcore, vector_save_area_addr); + OFFSET(__LC_EXT_PARAMS2, lowcore, ext_params2); + OFFSET(__LC_FPREGS_SAVE_AREA, lowcore, floating_pt_save_area); + OFFSET(__LC_GPREGS_SAVE_AREA, lowcore, gpregs_save_area); + OFFSET(__LC_PSW_SAVE_AREA, lowcore, psw_save_area); + OFFSET(__LC_PREFIX_SAVE_AREA, lowcore, prefixreg_save_area); + OFFSET(__LC_FP_CREG_SAVE_AREA, lowcore, fpt_creg_save_area); + OFFSET(__LC_TOD_PROGREG_SAVE_AREA, lowcore, tod_progreg_save_area); + OFFSET(__LC_CPU_TIMER_SAVE_AREA, lowcore, cpu_timer_save_area); + OFFSET(__LC_CLOCK_COMP_SAVE_AREA, lowcore, clock_comp_save_area); + OFFSET(__LC_AREGS_SAVE_AREA, lowcore, access_regs_save_area); + OFFSET(__LC_CREGS_SAVE_AREA, lowcore, cregs_save_area); + OFFSET(__LC_PGM_TDB, lowcore, pgm_tdb); BLANK(); /* gmap/sie offsets */ OFFSET(__GMAP_ASCE, gmap, asce); diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 823ed6ab53c8..a92b39fd0e63 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -83,9 +83,9 @@ struct save_area * __init save_area_boot_cpu(void) */ void __init save_area_add_regs(struct save_area *sa, void *regs) { - struct _lowcore *lc; + struct lowcore *lc; - lc = (struct _lowcore *)(regs - __LC_FPREGS_SAVE_AREA); + lc = (struct lowcore *)(regs - __LC_FPREGS_SAVE_AREA); memcpy(&sa->psw, &lc->psw_save_area, sizeof(sa->psw)); memcpy(&sa->ctrs, &lc->cregs_save_area, sizeof(sa->ctrs)); memcpy(&sa->gprs, &lc->gpregs_save_area, sizeof(sa->gprs)); diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 26d58cf72573..0a5a6b661b93 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -2041,9 +2041,9 @@ static void do_reset_calls(void) void s390_reset_system(void) { - struct _lowcore *lc; + struct lowcore *lc; - lc = (struct _lowcore *)(unsigned long) store_prefix(); + lc = (struct lowcore *)(unsigned long) store_prefix(); /* Stack for interrupt/machine check handler */ lc->panic_stack = S390_lowcore.panic_stack; diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 22756bb0819e..ea2454d5dcba 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -97,7 +97,7 @@ unsigned long MODULES_VADDR; unsigned long MODULES_END; /* An array with a pointer to the lowcore of every CPU. */ -struct _lowcore *lowcore_ptr[NR_CPUS]; +struct lowcore *lowcore_ptr[NR_CPUS]; EXPORT_SYMBOL(lowcore_ptr); /* @@ -291,12 +291,12 @@ void *restart_stack __attribute__((__section__(".data"))); static void __init setup_lowcore(void) { - struct _lowcore *lc; + struct lowcore *lc; /* * Setup lowcore for boot cpu */ - BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096); + BUILD_BUG_ON(sizeof(struct lowcore) != LC_PAGES * 4096); lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0); lc->restart_psw.mask = PSW_KERNEL_BITS; lc->restart_psw.addr = diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 654c36ec0c60..a13468b9a913 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -64,7 +64,7 @@ enum { static DEFINE_PER_CPU(struct cpu *, cpu_device); struct pcpu { - struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ + struct lowcore *lowcore; /* lowcore page(s) for the cpu */ unsigned long ec_mask; /* bit mask for ec_xxx functions */ unsigned long ec_clk; /* sigp timestamp for ec_xxx */ signed char state; /* physical cpu state */ @@ -185,10 +185,10 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) { unsigned long async_stack, panic_stack; - struct _lowcore *lc; + struct lowcore *lc; if (pcpu != &pcpu_devices[0]) { - pcpu->lowcore = (struct _lowcore *) + pcpu->lowcore = (struct lowcore *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); panic_stack = __get_free_page(GFP_KERNEL); @@ -240,7 +240,7 @@ static void pcpu_free_lowcore(struct pcpu *pcpu) static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu) { - struct _lowcore *lc = pcpu->lowcore; + struct lowcore *lc = pcpu->lowcore; if (MACHINE_HAS_TLB_LC) cpumask_set_cpu(cpu, &init_mm.context.cpu_attach_mask); @@ -260,7 +260,7 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu) static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk) { - struct _lowcore *lc = pcpu->lowcore; + struct lowcore *lc = pcpu->lowcore; struct thread_info *ti = task_thread_info(tsk); lc->kernel_stack = (unsigned long) task_stack_page(tsk) @@ -276,7 +276,7 @@ static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk) static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data) { - struct _lowcore *lc = pcpu->lowcore; + struct lowcore *lc = pcpu->lowcore; lc->restart_stack = lc->kernel_stack; lc->restart_fn = (unsigned long) func; @@ -291,7 +291,7 @@ static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data) static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *), void *data, unsigned long stack) { - struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices]; + struct lowcore *lc = lowcore_ptr[pcpu - pcpu_devices]; unsigned long source_cpu = stap(); __load_psw_mask(PSW_KERNEL_BITS); @@ -923,7 +923,7 @@ void __init smp_prepare_boot_cpu(void) pcpu->state = CPU_STATE_CONFIGURED; pcpu->address = stap(); - pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix(); + pcpu->lowcore = (struct lowcore *)(unsigned long) store_prefix(); S390_lowcore.percpu_offset = __per_cpu_offset[0]; smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); set_cpu_present(0, true); diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 59eddb0e1a3e..4f07eaced960 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -90,7 +90,7 @@ static void vdso_init_data(struct vdso_data *vd) */ #define SEGMENT_ORDER 2 -int vdso_alloc_per_cpu(struct _lowcore *lowcore) +int vdso_alloc_per_cpu(struct lowcore *lowcore) { unsigned long segment_table, page_table, page_frame; u32 *psal, *aste; @@ -138,7 +138,7 @@ out: return -ENOMEM; } -void vdso_free_per_cpu(struct _lowcore *lowcore) +void vdso_free_per_cpu(struct lowcore *lowcore) { unsigned long segment_table, page_table, page_frame; u32 *psal, *aste; @@ -163,7 +163,7 @@ static void vdso_init_cr5(void) if (!vdso_enabled) return; - cr5 = offsetof(struct _lowcore, paste); + cr5 = offsetof(struct lowcore, paste); __ctl_load(cr5, 5, 5); } diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 6a75352f453c..cbad2e6d7dd7 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -399,9 +399,9 @@ static int __must_check __deliver_restart(struct kvm_vcpu *vcpu) trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0); rc = write_guest_lc(vcpu, - offsetof(struct _lowcore, restart_old_psw), + offsetof(struct lowcore, restart_old_psw), &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); - rc |= read_guest_lc(vcpu, offsetof(struct _lowcore, restart_psw), + rc |= read_guest_lc(vcpu, offsetof(struct lowcore, restart_psw), &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); clear_bit(IRQ_PEND_RESTART, &li->pending_irqs); return rc ? -EFAULT : 0; diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index d76b51cb4b62..ed74e86d9b9e 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -355,7 +355,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu) * into a u32 memory representation. They will remain bits 0-31. */ fac = *vcpu->kvm->arch.model.fac->list >> 32; - rc = write_guest_lc(vcpu, offsetof(struct _lowcore, stfl_fac_list), + rc = write_guest_lc(vcpu, offsetof(struct lowcore, stfl_fac_list), &fac, sizeof(fac)); if (rc) return rc; diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index 8a993a53fcd6..fec59c067d0d 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -163,11 +163,11 @@ static int is_swapped(unsigned long addr) unsigned long lc; int cpu; - if (addr < sizeof(struct _lowcore)) + if (addr < sizeof(struct lowcore)) return 1; for_each_online_cpu(cpu) { lc = (unsigned long) lowcore_ptr[cpu]; - if (addr > lc + sizeof(struct _lowcore) - 1 || addr < lc) + if (addr > lc + sizeof(struct lowcore) - 1 || addr < lc) continue; return 1; } -- cgit v1.2.3-59-g8ed1b From 0dab3e0e59ac3692e2f95cb37ba17d5dfb3d1e5f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 5 Jan 2016 18:17:53 +0200 Subject: s390: drop smp_mb in vdso_init The initial s390 vdso code is heavily influenced by the powerpc version which does have a smp_wmb in vdso_init right before the vdso_ready=1 assignment. s390 has no need for that. Signed-off-by: Michael S. Tsirkin Message-Id: <1452010645-25380-1-git-send-email-mst@redhat.com> Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/vdso.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 4f07eaced960..604f4a68b524 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -299,8 +299,6 @@ static int __init vdso_init(void) get_page(virt_to_page(vdso_data)); - smp_mb(); - return 0; } early_initcall(vdso_init); -- cgit v1.2.3-59-g8ed1b From 249c543b97e1409b13fb9539b2f880e58ddd87cf Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 5 Jan 2016 13:29:38 +0100 Subject: s390/vdso: optimize getcpu system call Add the CPU number to the per-cpu vdso data page and add the __kernel_getcpu function to the vdso object to retrieve the CPU number in user space. Suggested-by: Heiko Carstens Reviewed-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/vdso.h | 2 ++ arch/s390/kernel/asm-offsets.c | 2 ++ arch/s390/kernel/vdso.c | 9 +++++++- arch/s390/kernel/vdso32/Makefile | 2 +- arch/s390/kernel/vdso32/getcpu.S | 43 ++++++++++++++++++++++++++++++++++++ arch/s390/kernel/vdso32/vdso32.lds.S | 1 + arch/s390/kernel/vdso64/Makefile | 2 +- arch/s390/kernel/vdso64/getcpu.S | 42 +++++++++++++++++++++++++++++++++++ arch/s390/kernel/vdso64/vdso64.lds.S | 1 + 9 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 arch/s390/kernel/vdso32/getcpu.S create mode 100644 arch/s390/kernel/vdso64/getcpu.S diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h index f9b02d300d60..d0a2dbf2433d 100644 --- a/arch/s390/include/asm/vdso.h +++ b/arch/s390/include/asm/vdso.h @@ -38,6 +38,8 @@ struct vdso_data { struct vdso_per_cpu_data { __u64 ectg_timer_base; __u64 ectg_user_time; + __u32 cpu_nr; + __u32 node_id; }; extern struct vdso_data *vdso_data; diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index d5916ef9c619..53bbc9e8b281 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -80,6 +80,8 @@ int main(void) OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift); OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base); OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time); + OFFSET(__VDSO_CPU_NR, vdso_per_cpu_data, cpu_nr); + OFFSET(__VDSO_NODE_ID, vdso_per_cpu_data, node_id); BLANK(); /* constants used by the vdso */ DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME); diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 604f4a68b524..94495cac8be3 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -80,7 +80,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data; /* * Setup vdso data page. */ -static void vdso_init_data(struct vdso_data *vd) +static void __init vdso_init_data(struct vdso_data *vd) { vd->ectg_available = test_facility(31); } @@ -93,6 +93,7 @@ static void vdso_init_data(struct vdso_data *vd) int vdso_alloc_per_cpu(struct lowcore *lowcore) { unsigned long segment_table, page_table, page_frame; + struct vdso_per_cpu_data *vd; u32 *psal, *aste; int i; @@ -107,6 +108,12 @@ int vdso_alloc_per_cpu(struct lowcore *lowcore) if (!segment_table || !page_table || !page_frame) goto out; + /* Initialize per-cpu vdso data page */ + vd = (struct vdso_per_cpu_data *) page_frame; + vd->cpu_nr = lowcore->cpu_nr; + vd->node_id = cpu_to_node(vd->cpu_nr); + + /* Set up access register mode page table */ clear_table((unsigned long *) segment_table, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE << SEGMENT_ORDER); clear_table((unsigned long *) page_table, _PAGE_INVALID, diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile index ee8a18e50a25..f9c459586649 100644 --- a/arch/s390/kernel/vdso32/Makefile +++ b/arch/s390/kernel/vdso32/Makefile @@ -1,6 +1,6 @@ # List of files in the vdso, has to be asm only for now -obj-vdso32 = gettimeofday.o clock_getres.o clock_gettime.o note.o +obj-vdso32 = gettimeofday.o clock_getres.o clock_gettime.o note.o getcpu.o # Build rules diff --git a/arch/s390/kernel/vdso32/getcpu.S b/arch/s390/kernel/vdso32/getcpu.S new file mode 100644 index 000000000000..c1ed0b72030f --- /dev/null +++ b/arch/s390/kernel/vdso32/getcpu.S @@ -0,0 +1,43 @@ +/* + * Userland implementation of getcpu() for 32 bits processes in a + * s390 kernel for use in the vDSO + * + * Copyright IBM Corp. 2016 + * Author(s): Martin Schwidefsky + */ +#include +#include + + .text + .align 4 + .globl __kernel_getcpu + .type __kernel_getcpu,@function +__kernel_getcpu: + .cfi_startproc + ear %r1,%a4 + lhi %r4,1 + sll %r4,24 + sar %a4,%r4 + la %r4,0 + epsw %r0,0 + sacf 512 + l %r5,__VDSO_CPU_NR(%r4) + l %r4,__VDSO_NODE_ID(%r4) + tml %r0,0x4000 + jo 1f + tml %r0,0x8000 + jno 0f + sacf 256 + j 1f +0: sacf 0 +1: sar %a4,%r1 + ltr %r2,%r2 + jz 2f + st %r5,0(%r2) +2: ltr %r3,%r3 + jz 3f + st %r4,0(%r3) +3: lhi %r2,0 + br %r14 + .cfi_endproc + .size __kernel_getcpu,.-__kernel_getcpu diff --git a/arch/s390/kernel/vdso32/vdso32.lds.S b/arch/s390/kernel/vdso32/vdso32.lds.S index a8c379fa1247..8f048c2d6d13 100644 --- a/arch/s390/kernel/vdso32/vdso32.lds.S +++ b/arch/s390/kernel/vdso32/vdso32.lds.S @@ -132,6 +132,7 @@ VERSION __kernel_gettimeofday; __kernel_clock_gettime; __kernel_clock_getres; + __kernel_getcpu; local: *; }; diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile index c4b03f9ed228..058659c1b8cf 100644 --- a/arch/s390/kernel/vdso64/Makefile +++ b/arch/s390/kernel/vdso64/Makefile @@ -1,6 +1,6 @@ # List of files in the vdso, has to be asm only for now -obj-vdso64 = gettimeofday.o clock_getres.o clock_gettime.o note.o +obj-vdso64 = gettimeofday.o clock_getres.o clock_gettime.o note.o getcpu.o # Build rules diff --git a/arch/s390/kernel/vdso64/getcpu.S b/arch/s390/kernel/vdso64/getcpu.S new file mode 100644 index 000000000000..4cbe98291931 --- /dev/null +++ b/arch/s390/kernel/vdso64/getcpu.S @@ -0,0 +1,42 @@ +/* + * Userland implementation of getcpu() for 64 bits processes in a + * s390 kernel for use in the vDSO + * + * Copyright IBM Corp. 2016 + * Author(s): Martin Schwidefsky + */ +#include +#include + + .text + .align 4 + .globl __kernel_getcpu + .type __kernel_getcpu,@function +__kernel_getcpu: + .cfi_startproc + ear %r1,%a4 + llilh %r4,0x0100 + sar %a4,%r4 + la %r4,0 + epsw %r0,0 + sacf 512 + l %r5,__VDSO_CPU_NR(%r4) + l %r4,__VDSO_NODE_ID(%r4) + tml %r0,0x4000 + jo 1f + tml %r0,0x8000 + jno 0f + sacf 256 + j 1f +0: sacf 0 +1: sar %a4,%r1 + ltgr %r2,%r2 + jz 2f + st %r5,0(%r2) +2: ltgr %r3,%r3 + jz 3f + st %r4,0(%r3) +3: lghi %r2,0 + br %r14 + .cfi_endproc + .size __kernel_getcpu,.-__kernel_getcpu diff --git a/arch/s390/kernel/vdso64/vdso64.lds.S b/arch/s390/kernel/vdso64/vdso64.lds.S index 9f5979d102a9..f35455d497fe 100644 --- a/arch/s390/kernel/vdso64/vdso64.lds.S +++ b/arch/s390/kernel/vdso64/vdso64.lds.S @@ -132,6 +132,7 @@ VERSION __kernel_gettimeofday; __kernel_clock_gettime; __kernel_clock_getres; + __kernel_getcpu; local: *; }; -- cgit v1.2.3-59-g8ed1b From cb14def6a9cae973ba6f702443c8fc589998279c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 2 Jul 2015 17:30:31 +0200 Subject: s390/configs: update default configurations Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/configs/default_defconfig | 27 ++++++++++++--------------- arch/s390/configs/gcov_defconfig | 24 ++++++++++-------------- arch/s390/configs/performance_defconfig | 24 ++++++++++-------------- arch/s390/configs/zfcpdump_defconfig | 10 ++-------- arch/s390/defconfig | 30 +++++++++++++++++++++++++++--- 5 files changed, 61 insertions(+), 54 deletions(-) diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig index ed7da281df66..0ac42cc4f880 100644 --- a/arch/s390/configs/default_defconfig +++ b/arch/s390/configs/default_defconfig @@ -10,28 +10,35 @@ CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_RCU_FAST_NO_HZ=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_NUMA_BALANCING=y CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_KMEM=y +CONFIG_CGROUP_HUGETLB=y CONFIG_CGROUP_PERF=y CONFIG_CFS_BANDWIDTH=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_CGROUP=y CONFIG_NAMESPACES=y +CONFIG_USER_NS=y CONFIG_SCHED_AUTOGROUP=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y CONFIG_BPF_SYSCALL=y +CONFIG_USERFAULTFD=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_OPROFILE=m CONFIG_KPROBES=y CONFIG_JUMP_LABEL=y +CONFIG_STATIC_KEYS_SELFTEST=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y @@ -64,7 +71,6 @@ CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_S390=y CONFIG_CHSC_SCH=y CONFIG_CRASH_DUMP=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m CONFIG_HIBERNATION=y CONFIG_NET=y @@ -106,7 +112,6 @@ CONFIG_TCP_CONG_LP=m CONFIG_TCP_CONG_VENO=m CONFIG_TCP_CONG_YEAH=m CONFIG_TCP_CONG_ILLINOIS=m -CONFIG_IPV6=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m @@ -457,19 +462,9 @@ CONFIG_INFINIBAND=m CONFIG_INFINIBAND_USER_ACCESS=m CONFIG_MLX4_INFINIBAND=m CONFIG_VIRTIO_BALLOON=m -# CONFIG_IOMMU_SUPPORT is not set -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y -CONFIG_JBD_DEBUG=y CONFIG_JBD2_DEBUG=y CONFIG_JFS_FS=m CONFIG_JFS_POSIX_ACL=y @@ -490,7 +485,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V1=m CONFIG_QFMT_V2=m CONFIG_AUTOFS4_FS=m -CONFIG_FUSE_FS=m +CONFIG_FUSE_FS=y CONFIG_CUSE=m CONFIG_FSCACHE=m CONFIG_CACHEFILES=m @@ -542,10 +537,11 @@ CONFIG_DLM=m CONFIG_PRINTK_TIME=y CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_INFO=y -# CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=1024 CONFIG_READABLE_ASM=y CONFIG_UNUSED_SYMBOLS=y +CONFIG_HEADERS_CHECK=y +CONFIG_DEBUG_SECTION_MISMATCH=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_PAGEALLOC=y CONFIG_DEBUG_OBJECTS=y @@ -588,6 +584,7 @@ CONFIG_FAILSLAB=y CONFIG_FAIL_PAGE_ALLOC=y CONFIG_FAIL_MAKE_REQUEST=y CONFIG_FAIL_IO_TIMEOUT=y +CONFIG_FAIL_FUTEX=y CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_LATENCYTOP=y diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig index 9858b14cde1e..a31dcd56f7c0 100644 --- a/arch/s390/configs/gcov_defconfig +++ b/arch/s390/configs/gcov_defconfig @@ -10,21 +10,27 @@ CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_RCU_FAST_NO_HZ=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_NUMA_BALANCING=y CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_KMEM=y +CONFIG_CGROUP_HUGETLB=y CONFIG_CGROUP_PERF=y CONFIG_BLK_CGROUP=y CONFIG_NAMESPACES=y +CONFIG_USER_NS=y CONFIG_SCHED_AUTOGROUP=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y CONFIG_BPF_SYSCALL=y +CONFIG_USERFAULTFD=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_OPROFILE=m @@ -61,7 +67,6 @@ CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_S390=y CONFIG_CHSC_SCH=y CONFIG_CRASH_DUMP=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m CONFIG_HIBERNATION=y CONFIG_NET=y @@ -103,7 +108,6 @@ CONFIG_TCP_CONG_LP=m CONFIG_TCP_CONG_VENO=m CONFIG_TCP_CONG_YEAH=m CONFIG_TCP_CONG_ILLINOIS=m -CONFIG_IPV6=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m @@ -453,19 +457,9 @@ CONFIG_INFINIBAND=m CONFIG_INFINIBAND_USER_ACCESS=m CONFIG_MLX4_INFINIBAND=m CONFIG_VIRTIO_BALLOON=m -# CONFIG_IOMMU_SUPPORT is not set -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y -CONFIG_JBD_DEBUG=y CONFIG_JBD2_DEBUG=y CONFIG_JFS_FS=m CONFIG_JFS_POSIX_ACL=y @@ -485,7 +479,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V1=m CONFIG_QFMT_V2=m CONFIG_AUTOFS4_FS=m -CONFIG_FUSE_FS=m +CONFIG_FUSE_FS=y CONFIG_CUSE=m CONFIG_FSCACHE=m CONFIG_CACHEFILES=m @@ -550,6 +544,7 @@ CONFIG_NOTIFIER_ERROR_INJECTION=m CONFIG_CPU_NOTIFIER_ERROR_INJECT=m CONFIG_PM_NOTIFIER_ERROR_INJECT=m CONFIG_LATENCYTOP=y +CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y CONFIG_BLK_DEV_IO_TRACE=y # CONFIG_KPROBE_EVENT is not set CONFIG_LKDTM=m @@ -557,6 +552,7 @@ CONFIG_RBTREE_TEST=m CONFIG_INTERVAL_TREE_TEST=m CONFIG_PERCPU_TEST=m CONFIG_ATOMIC64_SELFTEST=y +CONFIG_TEST_BPF=m # CONFIG_STRICT_DEVMEM is not set CONFIG_S390_PTDUMP=y CONFIG_ENCRYPTED_KEYS=m diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig index 7f14f80717d4..7b73bf353345 100644 --- a/arch/s390/configs/performance_defconfig +++ b/arch/s390/configs/performance_defconfig @@ -10,22 +10,28 @@ CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_RCU_FAST_NO_HZ=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_NUMA_BALANCING=y # CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_KMEM=y +CONFIG_CGROUP_HUGETLB=y CONFIG_CGROUP_PERF=y CONFIG_BLK_CGROUP=y CONFIG_NAMESPACES=y +CONFIG_USER_NS=y CONFIG_SCHED_AUTOGROUP=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y CONFIG_BPF_SYSCALL=y +CONFIG_USERFAULTFD=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_OPROFILE=m @@ -61,7 +67,6 @@ CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_S390=y CONFIG_CHSC_SCH=y CONFIG_CRASH_DUMP=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=m CONFIG_HIBERNATION=y CONFIG_NET=y @@ -103,7 +108,6 @@ CONFIG_TCP_CONG_LP=m CONFIG_TCP_CONG_VENO=m CONFIG_TCP_CONG_YEAH=m CONFIG_TCP_CONG_ILLINOIS=m -CONFIG_IPV6=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m @@ -453,19 +457,9 @@ CONFIG_INFINIBAND=m CONFIG_INFINIBAND_USER_ACCESS=m CONFIG_MLX4_INFINIBAND=m CONFIG_VIRTIO_BALLOON=m -# CONFIG_IOMMU_SUPPORT is not set -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y -CONFIG_JBD_DEBUG=y CONFIG_JBD2_DEBUG=y CONFIG_JFS_FS=m CONFIG_JFS_POSIX_ACL=y @@ -485,7 +479,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V1=m CONFIG_QFMT_V2=m CONFIG_AUTOFS4_FS=m -CONFIG_FUSE_FS=m +CONFIG_FUSE_FS=y CONFIG_CUSE=m CONFIG_FSCACHE=m CONFIG_CACHEFILES=m @@ -546,6 +540,7 @@ CONFIG_TIMER_STATS=y CONFIG_RCU_TORTURE_TEST=m CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_LATENCYTOP=y +CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y CONFIG_SCHED_TRACER=y CONFIG_FTRACE_SYSCALLS=y CONFIG_STACK_TRACER=y @@ -554,6 +549,7 @@ CONFIG_UPROBE_EVENT=y CONFIG_LKDTM=m CONFIG_PERCPU_TEST=m CONFIG_ATOMIC64_SELFTEST=y +CONFIG_TEST_BPF=m # CONFIG_STRICT_DEVMEM is not set CONFIG_S390_PTDUMP=y CONFIG_ENCRYPTED_KEYS=m diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig index 92805d604173..1719843a55a2 100644 --- a/arch/s390/configs/zfcpdump_defconfig +++ b/arch/s390/configs/zfcpdump_defconfig @@ -23,8 +23,6 @@ CONFIG_CRASH_DUMP=y # CONFIG_SECCOMP is not set CONFIG_NET=y # CONFIG_IUCV is not set -CONFIG_ATM=y -CONFIG_ATM_LANE=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y # CONFIG_FIRMWARE_IN_KERNEL is not set @@ -54,14 +52,10 @@ CONFIG_RAW_DRIVER=y # CONFIG_S390_VMUR is not set # CONFIG_HID is not set # CONFIG_IOMMU_SUPPORT is not set -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y +# CONFIG_DNOTIFY is not set # CONFIG_INOTIFY_USER is not set CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set CONFIG_PRINTK_TIME=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_FS=y diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 9256b48e7e43..e24f2af4c73b 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -11,22 +11,31 @@ CONFIG_TASK_IO_ACCOUNTING=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_KMEM=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CGROUP_PERF=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_CGROUP=y CONFIG_NAMESPACES=y +CONFIG_USER_NS=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y CONFIG_BPF_SYSCALL=y +CONFIG_USERFAULTFD=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_OPROFILE=y CONFIG_KPROBES=y CONFIG_JUMP_LABEL=y +CONFIG_STATIC_KEYS_SELFTEST=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y @@ -37,6 +46,7 @@ CONFIG_DEFAULT_DEADLINE=y CONFIG_LIVEPATCH=y CONFIG_MARCH_Z196=y CONFIG_NR_CPUS=256 +CONFIG_NUMA=y CONFIG_HZ_100=y CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTREMOVE=y @@ -52,7 +62,6 @@ CONFIG_NET_KEY=y CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_INET_LRO is not set -CONFIG_IPV6=y CONFIG_L2TP=m CONFIG_L2TP_DEBUGFS=m CONFIG_VLAN_8021Q=y @@ -89,10 +98,26 @@ CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y CONFIG_SCSI_FC_ATTRS=y CONFIG_ZFCP=y CONFIG_SCSI_VIRTIO=y +CONFIG_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_MULTIPATH=m +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=m +CONFIG_DM_SWITCH=m CONFIG_NETDEVICES=y CONFIG_BONDING=m CONFIG_DUMMY=m @@ -137,7 +162,6 @@ CONFIG_DEBUG_PI_LIST=y CONFIG_DEBUG_SG=y CONFIG_DEBUG_NOTIFIERS=y CONFIG_RCU_CPU_STALL_TIMEOUT=60 -# CONFIG_RCU_CPU_STALL_INFO is not set CONFIG_RCU_TRACE=y CONFIG_LATENCYTOP=y CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y -- cgit v1.2.3-59-g8ed1b From bcb7825a77f41c7dd91da6f7ac10b928156a322e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 1 Jan 2016 13:39:22 +0100 Subject: s390: fix normalization bug in exception table sorting The normalization pass in the sorting routine of the relative exception table serves two purposes: - it ensures that the address fields of the exception table entries are fully ordered, so that no ambiguities arise between entries with identical instruction offsets (i.e., when two instructions that are exactly 8 bytes apart each have an exception table entry associated with them) - it ensures that the offsets of both the instruction and the fixup fields of each entry are relative to their final location after sorting. Commit eb608fb366de ("s390/exceptions: switch to relative exception table entries") ported the relative exception table format from x86, but modified the sorting routine to only normalize the instruction offset field and not the fixup offset field. The result is that the fixup offset of each entry will be relative to the original location of the entry before sorting, likely leading to crashes when those entries are dereferenced. Fixes: eb608fb366de ("s390/exceptions: switch to relative exception table entries") Signed-off-by: Ard Biesheuvel Cc: Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/extable.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c index 4d1ee88864e8..18c8b819b0aa 100644 --- a/arch/s390/mm/extable.c +++ b/arch/s390/mm/extable.c @@ -52,12 +52,16 @@ void sort_extable(struct exception_table_entry *start, int i; /* Normalize entries to being relative to the start of the section */ - for (p = start, i = 0; p < finish; p++, i += 8) + for (p = start, i = 0; p < finish; p++, i += 8) { p->insn += i; + p->fixup += i + 4; + } sort(start, finish - start, sizeof(*start), cmp_ex, NULL); /* Denormalize all entries */ - for (p = start, i = 0; p < finish; p++, i += 8) + for (p = start, i = 0; p < finish; p++, i += 8) { p->insn -= i; + p->fixup -= i + 4; + } } #ifdef CONFIG_MODULES -- cgit v1.2.3-59-g8ed1b From c2ab7282f0fcd11eea4d0ba45d1c65d89428c314 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 7 Jan 2016 13:37:22 +0100 Subject: s390/sclp: fix possible control register corruption sclp_sync_wait() disables all external interrupt classes except for the service signal subclass. The static mask used for that however is wrong. It clears a couple of bits which shouldn't be cleared and on the other hand potentially does not clear bits which should be cleared. Fix this by using the same generic mask like we do it in our delay implementation. Signed-off-by: Heiko Carstens Reviewed-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index f58bf4c6c3ee..272898225dbb 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -579,9 +579,8 @@ sclp_sync_wait(void) old_tick = local_tick_disable(); trace_hardirqs_on(); __ctl_store(cr0, 0, 0); - cr0_sync = cr0; - cr0_sync &= 0xffff00a0; - cr0_sync |= 0x00000200; + cr0_sync = cr0 & ~CR0_IRQ_SUBCLASS_MASK; + cr0_sync |= 1UL << (63 - 54); __ctl_load(cr0_sync, 0, 0); __arch_local_irq_stosm(0x01); /* Loop until driver state indicates finished request */ -- cgit v1.2.3-59-g8ed1b