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