Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-1.0+
0002 /*
0003  * zcore module to export memory content and register sets for creating system
0004  * dumps on SCSI/NVMe disks (zfcp/nvme dump).
0005  *
0006  * For more information please refer to Documentation/s390/zfcpdump.rst
0007  *
0008  * Copyright IBM Corp. 2003, 2008
0009  * Author(s): Michael Holzheu
0010  */
0011 
0012 #define KMSG_COMPONENT "zdump"
0013 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0014 
0015 #include <linux/init.h>
0016 #include <linux/slab.h>
0017 #include <linux/debugfs.h>
0018 #include <linux/panic_notifier.h>
0019 #include <linux/reboot.h>
0020 #include <linux/uio.h>
0021 
0022 #include <asm/asm-offsets.h>
0023 #include <asm/ipl.h>
0024 #include <asm/sclp.h>
0025 #include <asm/setup.h>
0026 #include <linux/uaccess.h>
0027 #include <asm/debug.h>
0028 #include <asm/processor.h>
0029 #include <asm/irqflags.h>
0030 #include <asm/checksum.h>
0031 #include <asm/os_info.h>
0032 #include <asm/switch_to.h>
0033 #include "sclp.h"
0034 
0035 #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
0036 
0037 enum arch_id {
0038     ARCH_S390   = 0,
0039     ARCH_S390X  = 1,
0040 };
0041 
0042 struct ipib_info {
0043     unsigned long   ipib;
0044     u32     checksum;
0045 }  __attribute__((packed));
0046 
0047 static struct debug_info *zcore_dbf;
0048 static int hsa_available;
0049 static struct dentry *zcore_dir;
0050 static struct dentry *zcore_reipl_file;
0051 static struct dentry *zcore_hsa_file;
0052 static struct ipl_parameter_block *zcore_ipl_block;
0053 
0054 static DEFINE_MUTEX(hsa_buf_mutex);
0055 static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE);
0056 
0057 /*
0058  * Copy memory from HSA to iterator (not reentrant):
0059  *
0060  * @iter:  Iterator where memory should be copied to
0061  * @src:   Start address within HSA where data should be copied
0062  * @count: Size of buffer, which should be copied
0063  */
0064 size_t memcpy_hsa_iter(struct iov_iter *iter, unsigned long src, size_t count)
0065 {
0066     size_t bytes, copied, res = 0;
0067     unsigned long offset;
0068 
0069     if (!hsa_available)
0070         return 0;
0071 
0072     mutex_lock(&hsa_buf_mutex);
0073     while (count) {
0074         if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) {
0075             TRACE("sclp_sdias_copy() failed\n");
0076             break;
0077         }
0078         offset = src % PAGE_SIZE;
0079         bytes = min(PAGE_SIZE - offset, count);
0080         copied = copy_to_iter(hsa_buf + offset, bytes, iter);
0081         count -= copied;
0082         src += copied;
0083         res += copied;
0084         if (copied < bytes)
0085             break;
0086     }
0087     mutex_unlock(&hsa_buf_mutex);
0088     return res;
0089 }
0090 
0091 /*
0092  * Copy memory from HSA to kernel memory (not reentrant):
0093  *
0094  * @dest:  Kernel or user buffer where memory should be copied to
0095  * @src:   Start address within HSA where data should be copied
0096  * @count: Size of buffer, which should be copied
0097  */
0098 static inline int memcpy_hsa_kernel(void *dst, unsigned long src, size_t count)
0099 {
0100     struct iov_iter iter;
0101     struct kvec kvec;
0102 
0103     kvec.iov_base = dst;
0104     kvec.iov_len = count;
0105     iov_iter_kvec(&iter, WRITE, &kvec, 1, count);
0106     if (memcpy_hsa_iter(&iter, src, count) < count)
0107         return -EIO;
0108     return 0;
0109 }
0110 
0111 static int __init init_cpu_info(void)
0112 {
0113     struct save_area *sa;
0114 
0115     /* get info for boot cpu from lowcore, stored in the HSA */
0116     sa = save_area_boot_cpu();
0117     if (!sa)
0118         return -ENOMEM;
0119     if (memcpy_hsa_kernel(hsa_buf, __LC_FPREGS_SAVE_AREA, 512) < 0) {
0120         TRACE("could not copy from HSA\n");
0121         return -EIO;
0122     }
0123     save_area_add_regs(sa, hsa_buf); /* vx registers are saved in smp.c */
0124     return 0;
0125 }
0126 
0127 /*
0128  * Release the HSA
0129  */
0130 static void release_hsa(void)
0131 {
0132     diag308(DIAG308_REL_HSA, NULL);
0133     hsa_available = 0;
0134 }
0135 
0136 static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf,
0137                  size_t count, loff_t *ppos)
0138 {
0139     if (zcore_ipl_block) {
0140         diag308(DIAG308_SET, zcore_ipl_block);
0141         diag308(DIAG308_LOAD_CLEAR, NULL);
0142     }
0143     return count;
0144 }
0145 
0146 static int zcore_reipl_open(struct inode *inode, struct file *filp)
0147 {
0148     return stream_open(inode, filp);
0149 }
0150 
0151 static int zcore_reipl_release(struct inode *inode, struct file *filp)
0152 {
0153     return 0;
0154 }
0155 
0156 static const struct file_operations zcore_reipl_fops = {
0157     .owner      = THIS_MODULE,
0158     .write      = zcore_reipl_write,
0159     .open       = zcore_reipl_open,
0160     .release    = zcore_reipl_release,
0161     .llseek     = no_llseek,
0162 };
0163 
0164 static ssize_t zcore_hsa_read(struct file *filp, char __user *buf,
0165                   size_t count, loff_t *ppos)
0166 {
0167     static char str[18];
0168 
0169     if (hsa_available)
0170         snprintf(str, sizeof(str), "%lx\n", sclp.hsa_size);
0171     else
0172         snprintf(str, sizeof(str), "0\n");
0173     return simple_read_from_buffer(buf, count, ppos, str, strlen(str));
0174 }
0175 
0176 static ssize_t zcore_hsa_write(struct file *filp, const char __user *buf,
0177                    size_t count, loff_t *ppos)
0178 {
0179     char value;
0180 
0181     if (*ppos != 0)
0182         return -EPIPE;
0183     if (copy_from_user(&value, buf, 1))
0184         return -EFAULT;
0185     if (value != '0')
0186         return -EINVAL;
0187     release_hsa();
0188     return count;
0189 }
0190 
0191 static const struct file_operations zcore_hsa_fops = {
0192     .owner      = THIS_MODULE,
0193     .write      = zcore_hsa_write,
0194     .read       = zcore_hsa_read,
0195     .open       = nonseekable_open,
0196     .llseek     = no_llseek,
0197 };
0198 
0199 static int __init check_sdias(void)
0200 {
0201     if (!sclp.hsa_size) {
0202         TRACE("Could not determine HSA size\n");
0203         return -ENODEV;
0204     }
0205     return 0;
0206 }
0207 
0208 /*
0209  * Provide IPL parameter information block from either HSA or memory
0210  * for future reipl
0211  */
0212 static int __init zcore_reipl_init(void)
0213 {
0214     struct ipib_info ipib_info;
0215     int rc;
0216 
0217     rc = memcpy_hsa_kernel(&ipib_info, __LC_DUMP_REIPL, sizeof(ipib_info));
0218     if (rc)
0219         return rc;
0220     if (ipib_info.ipib == 0)
0221         return 0;
0222     zcore_ipl_block = (void *) __get_free_page(GFP_KERNEL);
0223     if (!zcore_ipl_block)
0224         return -ENOMEM;
0225     if (ipib_info.ipib < sclp.hsa_size)
0226         rc = memcpy_hsa_kernel(zcore_ipl_block, ipib_info.ipib,
0227                        PAGE_SIZE);
0228     else
0229         rc = memcpy_real(zcore_ipl_block, ipib_info.ipib, PAGE_SIZE);
0230     if (rc || (__force u32)csum_partial(zcore_ipl_block, zcore_ipl_block->hdr.len, 0) !=
0231         ipib_info.checksum) {
0232         TRACE("Checksum does not match\n");
0233         free_page((unsigned long) zcore_ipl_block);
0234         zcore_ipl_block = NULL;
0235     }
0236     return 0;
0237 }
0238 
0239 static int zcore_reboot_and_on_panic_handler(struct notifier_block *self,
0240                          unsigned long     event,
0241                          void          *data)
0242 {
0243     if (hsa_available)
0244         release_hsa();
0245 
0246     return NOTIFY_OK;
0247 }
0248 
0249 static struct notifier_block zcore_reboot_notifier = {
0250     .notifier_call  = zcore_reboot_and_on_panic_handler,
0251     /* we need to be notified before reipl and kdump */
0252     .priority   = INT_MAX,
0253 };
0254 
0255 static struct notifier_block zcore_on_panic_notifier = {
0256     .notifier_call  = zcore_reboot_and_on_panic_handler,
0257     /* we need to be notified before reipl and kdump */
0258     .priority   = INT_MAX,
0259 };
0260 
0261 static int __init zcore_init(void)
0262 {
0263     unsigned char arch;
0264     int rc;
0265 
0266     if (!is_ipl_type_dump())
0267         return -ENODATA;
0268     if (oldmem_data.start)
0269         return -ENODATA;
0270 
0271     zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long));
0272     debug_register_view(zcore_dbf, &debug_sprintf_view);
0273     debug_set_level(zcore_dbf, 6);
0274 
0275     if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
0276         TRACE("type:   fcp\n");
0277         TRACE("devno:  %x\n", ipl_info.data.fcp.dev_id.devno);
0278         TRACE("wwpn:   %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn);
0279         TRACE("lun:    %llx\n", (unsigned long long) ipl_info.data.fcp.lun);
0280     } else if (ipl_info.type == IPL_TYPE_NVME_DUMP) {
0281         TRACE("type:   nvme\n");
0282         TRACE("fid:    %x\n", ipl_info.data.nvme.fid);
0283         TRACE("nsid:   %x\n", ipl_info.data.nvme.nsid);
0284     }
0285 
0286     rc = sclp_sdias_init();
0287     if (rc)
0288         goto fail;
0289 
0290     rc = check_sdias();
0291     if (rc)
0292         goto fail;
0293     hsa_available = 1;
0294 
0295     rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1);
0296     if (rc)
0297         goto fail;
0298 
0299     if (arch == ARCH_S390) {
0300         pr_alert("The 64-bit dump tool cannot be used for a "
0301              "32-bit system\n");
0302         rc = -EINVAL;
0303         goto fail;
0304     }
0305 
0306     pr_alert("The dump process started for a 64-bit operating system\n");
0307     rc = init_cpu_info();
0308     if (rc)
0309         goto fail;
0310 
0311     rc = zcore_reipl_init();
0312     if (rc)
0313         goto fail;
0314 
0315     zcore_dir = debugfs_create_dir("zcore" , NULL);
0316     zcore_reipl_file = debugfs_create_file("reipl", S_IRUSR, zcore_dir,
0317                         NULL, &zcore_reipl_fops);
0318     zcore_hsa_file = debugfs_create_file("hsa", S_IRUSR|S_IWUSR, zcore_dir,
0319                          NULL, &zcore_hsa_fops);
0320 
0321     register_reboot_notifier(&zcore_reboot_notifier);
0322     atomic_notifier_chain_register(&panic_notifier_list, &zcore_on_panic_notifier);
0323 
0324     return 0;
0325 fail:
0326     diag308(DIAG308_REL_HSA, NULL);
0327     return rc;
0328 }
0329 subsys_initcall(zcore_init);