1 /* 2 * zcore module to export memory content and register sets for creating system 3 * dumps on SCSI disks (zfcpdump). The "zcore/mem" debugfs file shows the same 4 * dump format as s390 standalone dumps. 5 * 6 * For more information please refer to Documentation/s390/zfcpdump.txt 7 * 8 * Copyright IBM Corp. 2003, 2008 9 * Author(s): Michael Holzheu 10 * License: GPL 11 */ 12 13 #define KMSG_COMPONENT "zdump" 14 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 15 16 #include <linux/init.h> 17 #include <linux/slab.h> 18 #include <linux/miscdevice.h> 19 #include <linux/debugfs.h> 20 #include <linux/memblock.h> 21 22 #include <asm/asm-offsets.h> 23 #include <asm/ipl.h> 24 #include <asm/sclp.h> 25 #include <asm/setup.h> 26 #include <linux/uaccess.h> 27 #include <asm/debug.h> 28 #include <asm/processor.h> 29 #include <asm/irqflags.h> 30 #include <asm/checksum.h> 31 #include <asm/os_info.h> 32 #include <asm/switch_to.h> 33 #include "sclp.h" 34 35 #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) 36 37 #define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */ 38 39 enum arch_id { 40 ARCH_S390 = 0, 41 ARCH_S390X = 1, 42 }; 43 44 struct ipib_info { 45 unsigned long ipib; 46 u32 checksum; 47 } __attribute__((packed)); 48 49 static struct debug_info *zcore_dbf; 50 static int hsa_available; 51 static struct dentry *zcore_dir; 52 static struct dentry *zcore_memmap_file; 53 static struct dentry *zcore_reipl_file; 54 static struct dentry *zcore_hsa_file; 55 static struct ipl_parameter_block *ipl_block; 56 57 static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE); 58 59 /* 60 * Copy memory from HSA to user memory (not reentrant): 61 * 62 * @dest: User buffer where memory should be copied to 63 * @src: Start address within HSA where data should be copied 64 * @count: Size of buffer, which should be copied 65 */ 66 int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count) 67 { 68 unsigned long offset, bytes; 69 70 if (!hsa_available) 71 return -ENODATA; 72 73 while (count) { 74 if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) { 75 TRACE("sclp_sdias_copy() failed\n"); 76 return -EIO; 77 } 78 offset = src % PAGE_SIZE; 79 bytes = min(PAGE_SIZE - offset, count); 80 if (copy_to_user(dest, hsa_buf + offset, bytes)) 81 return -EFAULT; 82 src += bytes; 83 dest += bytes; 84 count -= bytes; 85 } 86 return 0; 87 } 88 89 /* 90 * Copy memory from HSA to kernel memory (not reentrant): 91 * 92 * @dest: Kernel or user buffer where memory should be copied to 93 * @src: Start address within HSA where data should be copied 94 * @count: Size of buffer, which should be copied 95 */ 96 int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count) 97 { 98 unsigned long offset, bytes; 99 100 if (!hsa_available) 101 return -ENODATA; 102 103 while (count) { 104 if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) { 105 TRACE("sclp_sdias_copy() failed\n"); 106 return -EIO; 107 } 108 offset = src % PAGE_SIZE; 109 bytes = min(PAGE_SIZE - offset, count); 110 memcpy(dest, hsa_buf + offset, bytes); 111 src += bytes; 112 dest += bytes; 113 count -= bytes; 114 } 115 return 0; 116 } 117 118 static int __init init_cpu_info(void) 119 { 120 struct save_area *sa; 121 122 /* get info for boot cpu from lowcore, stored in the HSA */ 123 sa = save_area_boot_cpu(); 124 if (!sa) 125 return -ENOMEM; 126 if (memcpy_hsa_kernel(hsa_buf, __LC_FPREGS_SAVE_AREA, 512) < 0) { 127 TRACE("could not copy from HSA\n"); 128 return -EIO; 129 } 130 save_area_add_regs(sa, hsa_buf); /* vx registers are saved in smp.c */ 131 return 0; 132 } 133 134 /* 135 * Release the HSA 136 */ 137 static void release_hsa(void) 138 { 139 diag308(DIAG308_REL_HSA, NULL); 140 hsa_available = 0; 141 } 142 143 static ssize_t zcore_memmap_read(struct file *filp, char __user *buf, 144 size_t count, loff_t *ppos) 145 { 146 return simple_read_from_buffer(buf, count, ppos, filp->private_data, 147 memblock.memory.cnt * CHUNK_INFO_SIZE); 148 } 149 150 static int zcore_memmap_open(struct inode *inode, struct file *filp) 151 { 152 struct memblock_region *reg; 153 char *buf; 154 int i = 0; 155 156 buf = kzalloc(memblock.memory.cnt * CHUNK_INFO_SIZE, GFP_KERNEL); 157 if (!buf) { 158 return -ENOMEM; 159 } 160 for_each_memblock(memory, reg) { 161 sprintf(buf + (i++ * CHUNK_INFO_SIZE), "%016llx %016llx ", 162 (unsigned long long) reg->base, 163 (unsigned long long) reg->size); 164 } 165 filp->private_data = buf; 166 return nonseekable_open(inode, filp); 167 } 168 169 static int zcore_memmap_release(struct inode *inode, struct file *filp) 170 { 171 kfree(filp->private_data); 172 return 0; 173 } 174 175 static const struct file_operations zcore_memmap_fops = { 176 .owner = THIS_MODULE, 177 .read = zcore_memmap_read, 178 .open = zcore_memmap_open, 179 .release = zcore_memmap_release, 180 .llseek = no_llseek, 181 }; 182 183 static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, 184 size_t count, loff_t *ppos) 185 { 186 if (ipl_block) { 187 diag308(DIAG308_SET, ipl_block); 188 diag308(DIAG308_LOAD_CLEAR, NULL); 189 } 190 return count; 191 } 192 193 static int zcore_reipl_open(struct inode *inode, struct file *filp) 194 { 195 return nonseekable_open(inode, filp); 196 } 197 198 static int zcore_reipl_release(struct inode *inode, struct file *filp) 199 { 200 return 0; 201 } 202 203 static const struct file_operations zcore_reipl_fops = { 204 .owner = THIS_MODULE, 205 .write = zcore_reipl_write, 206 .open = zcore_reipl_open, 207 .release = zcore_reipl_release, 208 .llseek = no_llseek, 209 }; 210 211 static ssize_t zcore_hsa_read(struct file *filp, char __user *buf, 212 size_t count, loff_t *ppos) 213 { 214 static char str[18]; 215 216 if (hsa_available) 217 snprintf(str, sizeof(str), "%lx\n", sclp.hsa_size); 218 else 219 snprintf(str, sizeof(str), "0\n"); 220 return simple_read_from_buffer(buf, count, ppos, str, strlen(str)); 221 } 222 223 static ssize_t zcore_hsa_write(struct file *filp, const char __user *buf, 224 size_t count, loff_t *ppos) 225 { 226 char value; 227 228 if (*ppos != 0) 229 return -EPIPE; 230 if (copy_from_user(&value, buf, 1)) 231 return -EFAULT; 232 if (value != '0') 233 return -EINVAL; 234 release_hsa(); 235 return count; 236 } 237 238 static const struct file_operations zcore_hsa_fops = { 239 .owner = THIS_MODULE, 240 .write = zcore_hsa_write, 241 .read = zcore_hsa_read, 242 .open = nonseekable_open, 243 .llseek = no_llseek, 244 }; 245 246 static int __init check_sdias(void) 247 { 248 if (!sclp.hsa_size) { 249 TRACE("Could not determine HSA size\n"); 250 return -ENODEV; 251 } 252 return 0; 253 } 254 255 /* 256 * Provide IPL parameter information block from either HSA or memory 257 * for future reipl 258 */ 259 static int __init zcore_reipl_init(void) 260 { 261 struct ipib_info ipib_info; 262 int rc; 263 264 rc = memcpy_hsa_kernel(&ipib_info, __LC_DUMP_REIPL, sizeof(ipib_info)); 265 if (rc) 266 return rc; 267 if (ipib_info.ipib == 0) 268 return 0; 269 ipl_block = (void *) __get_free_page(GFP_KERNEL); 270 if (!ipl_block) 271 return -ENOMEM; 272 if (ipib_info.ipib < sclp.hsa_size) 273 rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); 274 else 275 rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); 276 if (rc || csum_partial(ipl_block, ipl_block->hdr.len, 0) != 277 ipib_info.checksum) { 278 TRACE("Checksum does not match\n"); 279 free_page((unsigned long) ipl_block); 280 ipl_block = NULL; 281 } 282 return 0; 283 } 284 285 static int __init zcore_init(void) 286 { 287 unsigned char arch; 288 int rc; 289 290 if (ipl_info.type != IPL_TYPE_FCP_DUMP) 291 return -ENODATA; 292 if (OLDMEM_BASE) 293 return -ENODATA; 294 295 zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long)); 296 debug_register_view(zcore_dbf, &debug_sprintf_view); 297 debug_set_level(zcore_dbf, 6); 298 299 TRACE("devno: %x\n", ipl_info.data.fcp.dev_id.devno); 300 TRACE("wwpn: %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn); 301 TRACE("lun: %llx\n", (unsigned long long) ipl_info.data.fcp.lun); 302 303 rc = sclp_sdias_init(); 304 if (rc) 305 goto fail; 306 307 rc = check_sdias(); 308 if (rc) 309 goto fail; 310 hsa_available = 1; 311 312 rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1); 313 if (rc) 314 goto fail; 315 316 if (arch == ARCH_S390) { 317 pr_alert("The 64-bit dump tool cannot be used for a " 318 "32-bit system\n"); 319 rc = -EINVAL; 320 goto fail; 321 } 322 323 pr_alert("The dump process started for a 64-bit operating system\n"); 324 rc = init_cpu_info(); 325 if (rc) 326 goto fail; 327 328 rc = zcore_reipl_init(); 329 if (rc) 330 goto fail; 331 332 zcore_dir = debugfs_create_dir("zcore" , NULL); 333 if (!zcore_dir) { 334 rc = -ENOMEM; 335 goto fail; 336 } 337 zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir, 338 NULL, &zcore_memmap_fops); 339 if (!zcore_memmap_file) { 340 rc = -ENOMEM; 341 goto fail_dir; 342 } 343 zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir, 344 NULL, &zcore_reipl_fops); 345 if (!zcore_reipl_file) { 346 rc = -ENOMEM; 347 goto fail_memmap_file; 348 } 349 zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir, 350 NULL, &zcore_hsa_fops); 351 if (!zcore_hsa_file) { 352 rc = -ENOMEM; 353 goto fail_reipl_file; 354 } 355 return 0; 356 357 fail_reipl_file: 358 debugfs_remove(zcore_reipl_file); 359 fail_memmap_file: 360 debugfs_remove(zcore_memmap_file); 361 fail_dir: 362 debugfs_remove(zcore_dir); 363 fail: 364 diag308(DIAG308_REL_HSA, NULL); 365 return rc; 366 } 367 subsys_initcall(zcore_init); 368