--- zzzz-none-000/linux-3.10.107/drivers/s390/char/zcore.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/s390/char/zcore.c 2021-02-04 17:41:59.000000000 +0000 @@ -17,6 +17,8 @@ #include #include #include +#include + #include #include #include @@ -26,12 +28,13 @@ #include #include #include +#include #include "sclp.h" #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) -#define TO_USER 0 -#define TO_KERNEL 1 +#define TO_USER 1 +#define TO_KERNEL 0 #define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */ enum arch_id { @@ -73,7 +76,7 @@ * @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(void *dest, unsigned long src, size_t count, int mode) { int offs, blk_num; static char buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); @@ -147,19 +150,21 @@ static int __init init_cpu_info(enum arch_id arch) { - struct save_area *sa; + struct save_area_ext *sa_ext; /* get info for boot cpu from lowcore, stored in the HSA */ - sa = kmalloc(sizeof(*sa), GFP_KERNEL); - if (!sa) + sa_ext = dump_save_areas.areas[0]; + if (!sa_ext) return -ENOMEM; - if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) { + 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); + kfree(sa_ext); return -EIO; } - zfcpdump_save_areas[0] = sa; + if (MACHINE_HAS_VX) + save_vx_regs_safe(sa_ext->vx_regs); return 0; } @@ -207,11 +212,7 @@ .dump_level = 0, .page_size = PAGE_SIZE, .mem_start = 0, -#ifdef CONFIG_64BIT .build_arch = DUMP_ARCH_S390X, -#else - .build_arch = DUMP_ARCH_S390, -#endif }; /* @@ -246,24 +247,25 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) { unsigned long end; - int i = 0; + int i; if (count == 0) return 0; end = start + count; - while (zfcpdump_save_areas[i]) { + 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 = zfcpdump_save_areas[i]->pref_reg; + prefix = save_area->pref_reg; sa_start = prefix + sys_info.sa_base; sa_end = prefix + sys_info.sa_base + sys_info.sa_size; if ((end < sa_start) || (start > sa_end)) - goto next; + continue; cp_start = max(start, sa_start); cp_end = min(end, sa_end); @@ -272,10 +274,8 @@ len = cp_end - cp_start; TRACE("copy_lc for: %lx\n", start); - if (copy_lc(buf + buf_off, zfcpdump_save_areas[i], sa_off, len)) + if (copy_lc(buf + buf_off, save_area, sa_off, len)) return -EFAULT; -next: - i++; } return 0; } @@ -330,9 +330,9 @@ mem_offs = 0; /* Copy from HSA data */ - if (*ppos < (ZFCPDUMP_HSA_SIZE + HEADER_SIZE)) { - size = min((count - hdr_count), (size_t) (ZFCPDUMP_HSA_SIZE - - mem_start)); + 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; @@ -413,33 +413,24 @@ size_t count, loff_t *ppos) { return simple_read_from_buffer(buf, count, ppos, filp->private_data, - MEMORY_CHUNKS * CHUNK_INFO_SIZE); + memblock.memory.cnt * CHUNK_INFO_SIZE); } static int zcore_memmap_open(struct inode *inode, struct file *filp) { - int i; + struct memblock_region *reg; char *buf; - struct mem_chunk *chunk_array; + int i = 0; - chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk), - GFP_KERNEL); - if (!chunk_array) - return -ENOMEM; - detect_memory_layout(chunk_array, 0); - buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL); + buf = kzalloc(memblock.memory.cnt * CHUNK_INFO_SIZE, GFP_KERNEL); if (!buf) { - kfree(chunk_array); return -ENOMEM; } - for (i = 0; i < MEMORY_CHUNKS; i++) { - sprintf(buf + (i * CHUNK_INFO_SIZE), "%016llx %016llx ", - (unsigned long long) chunk_array[i].addr, - (unsigned long long) chunk_array[i].size); - if (chunk_array[i].size == 0) - break; + for_each_memblock(memory, reg) { + sprintf(buf + (i++ * CHUNK_INFO_SIZE), "%016llx %016llx ", + (unsigned long long) reg->base, + (unsigned long long) reg->size); } - kfree(chunk_array); filp->private_data = buf; return nonseekable_open(inode, filp); } @@ -492,7 +483,7 @@ static char str[18]; if (hsa_available) - snprintf(str, sizeof(str), "%lx\n", ZFCPDUMP_HSA_SIZE); + snprintf(str, sizeof(str), "%lx\n", sclp.hsa_size); else snprintf(str, sizeof(str), "0\n"); return simple_read_from_buffer(buf, count, ppos, str, strlen(str)); @@ -521,23 +512,6 @@ .llseek = no_llseek, }; -#ifdef CONFIG_32BIT - -static void __init set_lc_mask(struct save_area *map) -{ - memset(&map->ext_save, 0xff, sizeof(map->ext_save)); - memset(&map->timer, 0xff, sizeof(map->timer)); - memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp)); - memset(&map->psw, 0xff, sizeof(map->psw)); - memset(&map->pref_reg, 0xff, sizeof(map->pref_reg)); - memset(&map->acc_regs, 0xff, sizeof(map->acc_regs)); - memset(&map->fp_regs, 0xff, sizeof(map->fp_regs)); - memset(&map->gp_regs, 0xff, sizeof(map->gp_regs)); - memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs)); -} - -#else /* CONFIG_32BIT */ - static void __init set_lc_mask(struct save_area *map) { memset(&map->fp_regs, 0xff, sizeof(map->fp_regs)); @@ -552,8 +526,6 @@ memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs)); } -#endif /* CONFIG_32BIT */ - /* * Initialize dump globals for a given architecture */ @@ -586,38 +558,21 @@ static int __init check_sdias(void) { - int rc, act_hsa_size; - - rc = sclp_sdias_blk_count(); - if (rc < 0) { + if (!sclp.hsa_size) { TRACE("Could not determine HSA size\n"); - return rc; - } - act_hsa_size = (rc - 1) * PAGE_SIZE; - if (act_hsa_size < ZFCPDUMP_HSA_SIZE) { - TRACE("HSA size too small: %i\n", act_hsa_size); - return -EINVAL; + return -ENODEV; } return 0; } static int __init get_mem_info(unsigned long *mem, unsigned long *end) { - int i; - struct mem_chunk *chunk_array; + struct memblock_region *reg; - chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk), - GFP_KERNEL); - if (!chunk_array) - return -ENOMEM; - detect_memory_layout(chunk_array, 0); - for (i = 0; i < MEMORY_CHUNKS; i++) { - if (chunk_array[i].size == 0) - break; - *mem += chunk_array[i].size; - *end = max(*end, chunk_array[i].addr + chunk_array[i].size); + for_each_memblock(memory, reg) { + *mem += reg->size; + *end = max_t(unsigned long, *end, reg->base + reg->size); } - kfree(chunk_array); return 0; } @@ -637,8 +592,8 @@ hdr->num_pages = mem_size / PAGE_SIZE; hdr->tod = get_tod_clock(); get_cpu_id(&hdr->cpu_id); - for (i = 0; zfcpdump_save_areas[i]; i++) { - prefix = zfcpdump_save_areas[i]->pref_reg; + 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; @@ -664,7 +619,7 @@ ipl_block = (void *) __get_free_page(GFP_KERNEL); if (!ipl_block) return -ENOMEM; - if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE) + if (ipib_info.ipib < sclp.hsa_size) rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); else rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); @@ -710,21 +665,12 @@ if (rc) goto fail; -#ifdef CONFIG_64BIT if (arch == ARCH_S390) { pr_alert("The 64-bit dump tool cannot be used for a " "32-bit system\n"); rc = -EINVAL; goto fail; } -#else /* CONFIG_64BIT */ - if (arch == ARCH_S390X) { - pr_alert("The 32-bit dump tool cannot be used for a " - "64-bit system\n"); - rc = -EINVAL; - goto fail; - } -#endif /* CONFIG_64BIT */ rc = get_mem_info(&mem_size, &mem_end); if (rc)