Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

+17 -402
+8 -12
Documentation/s390/zfcpdump.txt
··· 15 15 system can then trigger a SCSI dump by booting the SCSI disk, where zfcpdump 16 16 resides on. 17 17 18 - The kernel part of zfcpdump is implemented as a debugfs file under "zcore/mem", 19 - which exports memory and registers of the crashed Linux in an s390 20 - standalone dump format. It can be used in the same way as e.g. /dev/mem. The 21 - dump format defines a 4K header followed by plain uncompressed memory. The 22 - register sets are stored in the prefix pages of the respective CPUs. To build a 23 - dump enabled kernel with the zcore driver, the kernel config option 24 - CONFIG_CRASH_DUMP has to be set. When reading from "zcore/mem", the part of 25 - memory, which has been saved by hardware is read by the driver via the SCLP 26 - hardware interface. The second part is just copied from the non overwritten real 27 - memory. 18 + The user space dump tool accesses the memory of the crashed system by means 19 + of the /proc/vmcore interface. This interface exports the crashed system's 20 + memory and registers in ELF core dump format. To access the memory which has 21 + been saved by the hardware SCLP requests will be created at the time the data 22 + is needed by /proc/vmcore. The tail part of the crashed systems memory which 23 + has not been stashed by hardware can just be copied from real memory. 28 24 29 - Since kernel version 3.12 also the /proc/vmcore file can also be used to access 30 - the dump. 25 + To build a dump enabled kernel the kernel config option CONFIG_CRASH_DUMP 26 + has to be set. 31 27 32 28 To get a valid zfcpdump kernel configuration use "make zfcpdump_defconfig". 33 29
-1
arch/s390/include/asm/lowcore.h
··· 35 35 struct save_area_ext { 36 36 struct save_area sa; 37 37 __vector128 vx_regs[32]; 38 - u64 vx_sa_addr; 39 38 }; 40 39 41 40 struct _lowcore {
+1 -3
drivers/s390/char/Makefile
··· 30 30 obj-$(CONFIG_MONREADER) += monreader.o 31 31 obj-$(CONFIG_MONWRITER) += monwriter.o 32 32 obj-$(CONFIG_S390_VMUR) += vmur.o 33 - 34 - zcore_mod-objs := sclp_sdias.o zcore.o 35 - obj-$(CONFIG_CRASH_DUMP) += zcore_mod.o 33 + obj-$(CONFIG_CRASH_DUMP) += sclp_sdias.o zcore.o 36 34 37 35 hmcdrv-objs := hmcdrv_mod.o hmcdrv_dev.o hmcdrv_ftp.o hmcdrv_cache.o diag_ftp.o sclp_ftp.o 38 36 obj-$(CONFIG_HMC_DRV) += hmcdrv.o
+8 -386
drivers/s390/char/zcore.c
··· 43 43 ARCH_S390X = 1, 44 44 }; 45 45 46 - /* dump system info */ 47 - 48 - struct sys_info { 49 - enum arch_id arch; 50 - unsigned long sa_base; 51 - u32 sa_size; 52 - int cpu_map[NR_CPUS]; 53 - unsigned long mem_size; 54 - struct save_area lc_mask; 55 - }; 56 - 57 46 struct ipib_info { 58 47 unsigned long ipib; 59 48 u32 checksum; 60 49 } __attribute__((packed)); 61 50 62 - static struct sys_info sys_info; 63 51 static struct debug_info *zcore_dbf; 64 52 static int hsa_available; 65 53 static struct dentry *zcore_dir; 66 - static struct dentry *zcore_file; 67 54 static struct dentry *zcore_memmap_file; 68 55 static struct dentry *zcore_reipl_file; 69 56 static struct dentry *zcore_hsa_file; ··· 136 149 return memcpy_hsa(dest, src, count, TO_KERNEL); 137 150 } 138 151 139 - static int __init init_cpu_info(enum arch_id arch) 152 + static int __init init_cpu_info(void) 140 153 { 141 154 struct save_area_ext *sa_ext; 142 - struct _lowcore *lc; 143 - void *ptr; 144 - int i; 145 155 146 156 /* get info for boot cpu from lowcore, stored in the HSA */ 147 157 148 158 sa_ext = dump_save_areas.areas[0]; 149 159 if (!sa_ext) 150 160 return -ENOMEM; 151 - if (memcpy_hsa_kernel(&sa_ext->sa, sys_info.sa_base, 152 - sys_info.sa_size) < 0) { 161 + if (memcpy_hsa_kernel(&sa_ext->sa, SAVE_AREA_BASE, 162 + sizeof(struct save_area)) < 0) { 153 163 TRACE("could not copy from HSA\n"); 154 164 return -EIO; 155 165 } 156 - if (!MACHINE_HAS_VX) 157 - return 0; 158 - 159 - save_vx_regs_safe(sa_ext->vx_regs); 160 - /* Get address of the vector register save area for each CPU */ 161 - for (i = 0; i < dump_save_areas.count; i++) { 162 - sa_ext = dump_save_areas.areas[i]; 163 - lc = (struct _lowcore *)(unsigned long) sa_ext->sa.pref_reg; 164 - ptr = &lc->vector_save_area_addr; 165 - copy_from_oldmem(&sa_ext->vx_sa_addr, ptr, 166 - sizeof(sa_ext->vx_sa_addr)); 167 - } 168 - return 0; 169 - } 170 - 171 - static DEFINE_MUTEX(zcore_mutex); 172 - 173 - #define DUMP_VERSION 0x5 174 - #define DUMP_MAGIC 0xa8190173618f23fdULL 175 - #define DUMP_ARCH_S390X 2 176 - #define DUMP_ARCH_S390 1 177 - #define HEADER_SIZE 4096 178 - 179 - /* dump header dumped according to s390 crash dump format */ 180 - 181 - struct zcore_header { 182 - u64 magic; 183 - u32 version; 184 - u32 header_size; 185 - u32 dump_level; 186 - u32 page_size; 187 - u64 mem_size; 188 - u64 mem_start; 189 - u64 mem_end; 190 - u32 num_pages; 191 - u32 pad1; 192 - u64 tod; 193 - struct cpuid cpu_id; 194 - u32 arch_id; 195 - u32 volnr; 196 - u32 build_arch; 197 - u64 rmem_size; 198 - u8 mvdump; 199 - u16 cpu_cnt; 200 - u16 real_cpu_cnt; 201 - u8 end_pad1[0x200-0x061]; 202 - u64 mvdump_sign; 203 - u64 mvdump_zipl_time; 204 - u8 end_pad2[0x800-0x210]; 205 - u32 lc_vec[512]; 206 - } __attribute__((packed,__aligned__(16))); 207 - 208 - static struct zcore_header zcore_header = { 209 - .magic = DUMP_MAGIC, 210 - .version = DUMP_VERSION, 211 - .header_size = 4096, 212 - .dump_level = 0, 213 - .page_size = PAGE_SIZE, 214 - .mem_start = 0, 215 - .build_arch = DUMP_ARCH_S390X, 216 - }; 217 - 218 - /* 219 - * Copy lowcore info to buffer. Use map in order to copy only register parts. 220 - * 221 - * @buf: User buffer 222 - * @sa: Pointer to save area 223 - * @sa_off: Offset in save area to copy 224 - * @len: Number of bytes to copy 225 - */ 226 - static int copy_lc(void __user *buf, void *sa, int sa_off, int len) 227 - { 228 - int i; 229 - char *lc_mask = (char*)&sys_info.lc_mask; 230 - 231 - for (i = 0; i < len; i++) { 232 - if (!lc_mask[i + sa_off]) 233 - continue; 234 - if (copy_to_user(buf + i, sa + sa_off + i, 1)) 235 - return -EFAULT; 236 - } 237 - return 0; 238 - } 239 - 240 - /* 241 - * Copy lowcores info to memory, if necessary 242 - * 243 - * @buf: User buffer 244 - * @addr: Start address of buffer in dump memory 245 - * @count: Size of buffer 246 - */ 247 - static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) 248 - { 249 - struct save_area_ext *sa_ext; 250 - struct save_area *sa; 251 - unsigned long end; 252 - int i; 253 - 254 - if (count == 0) 255 - return 0; 256 - 257 - end = start + count; 258 - for (i = 0; i < dump_save_areas.count; i++) { 259 - unsigned long cp_start, cp_end; /* copy range */ 260 - unsigned long sa_start, sa_end; /* save area range */ 261 - unsigned long sa_off, len, buf_off; 262 - 263 - sa_ext = dump_save_areas.areas[i]; 264 - sa = &sa_ext->sa; 265 - 266 - /* Copy the 512 bytes lowcore save area 0x1200 - 0x1400 */ 267 - sa_start = sa->pref_reg + sys_info.sa_base; 268 - sa_end = sa_start + sys_info.sa_size; 269 - 270 - if (end >= sa_start && start < sa_end) { 271 - cp_start = max(start, sa_start); 272 - cp_end = min(end, sa_end); 273 - buf_off = cp_start - start; 274 - sa_off = cp_start - sa_start; 275 - len = cp_end - cp_start; 276 - 277 - TRACE("copy_lc: %lx-%lx\n", cp_start, cp_end); 278 - if (copy_lc(buf + buf_off, sa, sa_off, len)) 279 - return -EFAULT; 280 - } 281 - 282 - if (!MACHINE_HAS_VX) 283 - continue; 284 - 285 - /* Copy the 512 bytes vector save area */ 286 - sa_start = sa_ext->vx_sa_addr & -1024UL; 287 - sa_end = sa_start + 512; 288 - 289 - if (end >= sa_start && start < sa_end) { 290 - cp_start = max(start, sa_start); 291 - cp_end = min(end, sa_end); 292 - 293 - buf_off = cp_start - start; 294 - sa_off = cp_start - sa_start; 295 - len = cp_end - cp_start; 296 - 297 - TRACE("copy vxrs: %lx-%lx\n", cp_start, cp_end); 298 - if (copy_to_user(buf + buf_off, 299 - (void *) &sa_ext->vx_regs + sa_off, 300 - len)) 301 - return -EFAULT; 302 - } 303 - } 166 + if (MACHINE_HAS_VX) 167 + save_vx_regs_safe(sa_ext->vx_regs); 304 168 return 0; 305 169 } 306 170 ··· 163 325 diag308(DIAG308_REL_HSA, NULL); 164 326 hsa_available = 0; 165 327 } 166 - 167 - /* 168 - * Read routine for zcore character device 169 - * First 4K are dump header 170 - * Next 32MB are HSA Memory 171 - * Rest is read from absolute Memory 172 - */ 173 - static ssize_t zcore_read(struct file *file, char __user *buf, size_t count, 174 - loff_t *ppos) 175 - { 176 - unsigned long mem_start; /* Start address in memory */ 177 - size_t mem_offs; /* Offset in dump memory */ 178 - size_t hdr_count; /* Size of header part of output buffer */ 179 - size_t size; 180 - int rc; 181 - 182 - mutex_lock(&zcore_mutex); 183 - 184 - if (*ppos > (sys_info.mem_size + HEADER_SIZE)) { 185 - rc = -EINVAL; 186 - goto fail; 187 - } 188 - 189 - count = min(count, (size_t) (sys_info.mem_size + HEADER_SIZE - *ppos)); 190 - 191 - /* Copy dump header */ 192 - if (*ppos < HEADER_SIZE) { 193 - size = min(count, (size_t) (HEADER_SIZE - *ppos)); 194 - if (copy_to_user(buf, &zcore_header + *ppos, size)) { 195 - rc = -EFAULT; 196 - goto fail; 197 - } 198 - hdr_count = size; 199 - mem_start = 0; 200 - } else { 201 - hdr_count = 0; 202 - mem_start = *ppos - HEADER_SIZE; 203 - } 204 - 205 - mem_offs = 0; 206 - 207 - /* Copy from HSA data */ 208 - if (*ppos < sclp.hsa_size + HEADER_SIZE) { 209 - size = min((count - hdr_count), 210 - (size_t) (sclp.hsa_size - mem_start)); 211 - rc = memcpy_hsa_user(buf + hdr_count, mem_start, size); 212 - if (rc) 213 - goto fail; 214 - 215 - mem_offs += size; 216 - } 217 - 218 - /* Copy from real mem */ 219 - size = count - mem_offs - hdr_count; 220 - rc = copy_to_user_real(buf + hdr_count + mem_offs, 221 - (void *) mem_start + mem_offs, size); 222 - if (rc) 223 - goto fail; 224 - 225 - /* 226 - * Since s390 dump analysis tools like lcrash or crash 227 - * expect register sets in the prefix pages of the cpus, 228 - * we copy them into the read buffer, if necessary. 229 - * buf + hdr_count: Start of memory part of output buffer 230 - * mem_start: Start memory address to copy from 231 - * count - hdr_count: Size of memory area to copy 232 - */ 233 - if (zcore_add_lc(buf + hdr_count, mem_start, count - hdr_count)) { 234 - rc = -EFAULT; 235 - goto fail; 236 - } 237 - *ppos += count; 238 - fail: 239 - mutex_unlock(&zcore_mutex); 240 - return (rc < 0) ? rc : count; 241 - } 242 - 243 - static int zcore_open(struct inode *inode, struct file *filp) 244 - { 245 - if (!hsa_available) 246 - return -ENODATA; 247 - else 248 - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; 249 - } 250 - 251 - static int zcore_release(struct inode *inode, struct file *filep) 252 - { 253 - if (hsa_available) 254 - release_hsa(); 255 - return 0; 256 - } 257 - 258 - static loff_t zcore_lseek(struct file *file, loff_t offset, int orig) 259 - { 260 - loff_t rc; 261 - 262 - mutex_lock(&zcore_mutex); 263 - switch (orig) { 264 - case 0: 265 - file->f_pos = offset; 266 - rc = file->f_pos; 267 - break; 268 - case 1: 269 - file->f_pos += offset; 270 - rc = file->f_pos; 271 - break; 272 - default: 273 - rc = -EINVAL; 274 - } 275 - mutex_unlock(&zcore_mutex); 276 - return rc; 277 - } 278 - 279 - static const struct file_operations zcore_fops = { 280 - .owner = THIS_MODULE, 281 - .llseek = zcore_lseek, 282 - .read = zcore_read, 283 - .open = zcore_open, 284 - .release = zcore_release, 285 - }; 286 328 287 329 static ssize_t zcore_memmap_read(struct file *filp, char __user *buf, 288 330 size_t count, loff_t *ppos) ··· 267 549 .llseek = no_llseek, 268 550 }; 269 551 270 - static void __init set_lc_mask(struct save_area *map) 271 - { 272 - memset(&map->fp_regs, 0xff, sizeof(map->fp_regs)); 273 - memset(&map->gp_regs, 0xff, sizeof(map->gp_regs)); 274 - memset(&map->psw, 0xff, sizeof(map->psw)); 275 - memset(&map->pref_reg, 0xff, sizeof(map->pref_reg)); 276 - memset(&map->fp_ctrl_reg, 0xff, sizeof(map->fp_ctrl_reg)); 277 - memset(&map->tod_reg, 0xff, sizeof(map->tod_reg)); 278 - memset(&map->timer, 0xff, sizeof(map->timer)); 279 - memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp)); 280 - memset(&map->acc_regs, 0xff, sizeof(map->acc_regs)); 281 - memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs)); 282 - } 283 - 284 - /* 285 - * Initialize dump globals for a given architecture 286 - */ 287 - static int __init sys_info_init(enum arch_id arch, unsigned long mem_end) 288 - { 289 - int rc; 290 - 291 - switch (arch) { 292 - case ARCH_S390X: 293 - pr_alert("DETECTED 'S390X (64 bit) OS'\n"); 294 - break; 295 - case ARCH_S390: 296 - pr_alert("DETECTED 'S390 (32 bit) OS'\n"); 297 - break; 298 - default: 299 - pr_alert("0x%x is an unknown architecture.\n",arch); 300 - return -EINVAL; 301 - } 302 - sys_info.sa_base = SAVE_AREA_BASE; 303 - sys_info.sa_size = sizeof(struct save_area); 304 - sys_info.arch = arch; 305 - set_lc_mask(&sys_info.lc_mask); 306 - rc = init_cpu_info(arch); 307 - if (rc) 308 - return rc; 309 - sys_info.mem_size = mem_end; 310 - 311 - return 0; 312 - } 313 - 314 552 static int __init check_sdias(void) 315 553 { 316 554 if (!sclp.hsa_size) { ··· 274 600 return -ENODEV; 275 601 } 276 602 return 0; 277 - } 278 - 279 - static int __init get_mem_info(unsigned long *mem, unsigned long *end) 280 - { 281 - struct memblock_region *reg; 282 - 283 - for_each_memblock(memory, reg) { 284 - *mem += reg->size; 285 - *end = max_t(unsigned long, *end, reg->base + reg->size); 286 - } 287 - return 0; 288 - } 289 - 290 - static void __init zcore_header_init(int arch, struct zcore_header *hdr, 291 - unsigned long mem_size) 292 - { 293 - u32 prefix; 294 - int i; 295 - 296 - if (arch == ARCH_S390X) 297 - hdr->arch_id = DUMP_ARCH_S390X; 298 - else 299 - hdr->arch_id = DUMP_ARCH_S390; 300 - hdr->mem_size = mem_size; 301 - hdr->rmem_size = mem_size; 302 - hdr->mem_end = sys_info.mem_size; 303 - hdr->num_pages = mem_size / PAGE_SIZE; 304 - hdr->tod = get_tod_clock(); 305 - get_cpu_id(&hdr->cpu_id); 306 - for (i = 0; i < dump_save_areas.count; i++) { 307 - prefix = dump_save_areas.areas[i]->sa.pref_reg; 308 - hdr->real_cpu_cnt++; 309 - if (!prefix) 310 - continue; 311 - hdr->lc_vec[hdr->cpu_cnt] = prefix; 312 - hdr->cpu_cnt++; 313 - } 314 603 } 315 604 316 605 /* ··· 308 671 309 672 static int __init zcore_init(void) 310 673 { 311 - unsigned long mem_size, mem_end; 312 674 unsigned char arch; 313 675 int rc; 314 676 315 - mem_size = mem_end = 0; 316 677 if (ipl_info.type != IPL_TYPE_FCP_DUMP) 317 678 return -ENODATA; 318 679 if (OLDMEM_BASE) ··· 344 709 goto fail; 345 710 } 346 711 347 - rc = get_mem_info(&mem_size, &mem_end); 712 + pr_alert("DETECTED 'S390X (64 bit) OS'\n"); 713 + rc = init_cpu_info(); 348 714 if (rc) 349 715 goto fail; 350 - 351 - rc = sys_info_init(arch, mem_end); 352 - if (rc) 353 - goto fail; 354 - zcore_header_init(arch, &zcore_header, mem_size); 355 716 356 717 rc = zcore_reipl_init(); 357 718 if (rc) ··· 358 727 rc = -ENOMEM; 359 728 goto fail; 360 729 } 361 - zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL, 362 - &zcore_fops); 363 - if (!zcore_file) { 364 - rc = -ENOMEM; 365 - goto fail_dir; 366 - } 367 730 zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir, 368 731 NULL, &zcore_memmap_fops); 369 732 if (!zcore_memmap_file) { 370 733 rc = -ENOMEM; 371 - goto fail_file; 734 + goto fail_dir; 372 735 } 373 736 zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, 374 737 NULL, &zcore_reipl_fops); ··· 382 757 debugfs_remove(zcore_reipl_file); 383 758 fail_memmap_file: 384 759 debugfs_remove(zcore_memmap_file); 385 - fail_file: 386 - debugfs_remove(zcore_file); 387 760 fail_dir: 388 761 debugfs_remove(zcore_dir); 389 762 fail: ··· 397 774 debugfs_remove(zcore_hsa_file); 398 775 debugfs_remove(zcore_reipl_file); 399 776 debugfs_remove(zcore_memmap_file); 400 - debugfs_remove(zcore_file); 401 777 debugfs_remove(zcore_dir); 402 778 diag308(DIAG308_REL_HSA, NULL); 403 779 }