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

s390/nvme: support firmware-assisted dump to NVMe disks

From the kernel perspective NVMe dump works exactly like zFCP dump.
Therefore, adapt all places where code explicitly tests only for
IPL of type FCP DUMP. And also set the memory end correctly in this case.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Vasily Gorbik <gor@linux.ibm.com>
Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Alexander Egorenkov and committed by
Vasily Gorbik
bd37b368 d9f12e48

+47 -25
+12 -3
arch/s390/boot/ipl_parm.c
··· 280 280 } 281 281 } 282 282 283 + static inline bool is_ipl_block_dump(void) 284 + { 285 + if (ipl_block.pb0_hdr.pbt == IPL_PBT_FCP && 286 + ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP) 287 + return true; 288 + if (ipl_block.pb0_hdr.pbt == IPL_PBT_NVME && 289 + ipl_block.nvme.opt == IPL_PB0_NVME_OPT_DUMP) 290 + return true; 291 + return false; 292 + } 293 + 283 294 void setup_memory_end(void) 284 295 { 285 296 #ifdef CONFIG_CRASH_DUMP 286 297 if (OLDMEM_BASE) { 287 298 kaslr_enabled = 0; 288 - } else if (ipl_block_valid && 289 - ipl_block.pb0_hdr.pbt == IPL_PBT_FCP && 290 - ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP) { 299 + } else if (ipl_block_valid && is_ipl_block_dump()) { 291 300 kaslr_enabled = 0; 292 301 if (!sclp_early_get_hsa_size(&memory_end) && memory_end) 293 302 memory_end_set = 1;
+6
arch/s390/include/asm/ipl.h
··· 95 95 extern void setup_ipl(void); 96 96 extern void set_os_info_reipl_block(void); 97 97 98 + static inline bool is_ipl_type_dump(void) 99 + { 100 + return (ipl_info.type == IPL_TYPE_FCP_DUMP) || 101 + (ipl_info.type == IPL_TYPE_NVME_DUMP); 102 + } 103 + 98 104 struct ipl_report { 99 105 struct ipl_parameter_block *ipib; 100 106 struct list_head components;
+8 -8
arch/s390/kernel/crash_dump.c
··· 141 141 while (count) { 142 142 from = __pa(src); 143 143 if (!OLDMEM_BASE && from < sclp.hsa_size) { 144 - /* Copy from zfcpdump HSA area */ 144 + /* Copy from zfcp/nvme dump HSA area */ 145 145 len = min(count, sclp.hsa_size - from); 146 146 rc = memcpy_hsa_kernel(dst, from, len); 147 147 if (rc) ··· 184 184 while (count) { 185 185 from = __pa(src); 186 186 if (!OLDMEM_BASE && from < sclp.hsa_size) { 187 - /* Copy from zfcpdump HSA area */ 187 + /* Copy from zfcp/nvme dump HSA area */ 188 188 len = min(count, sclp.hsa_size - from); 189 189 rc = memcpy_hsa_user(dst, from, len); 190 190 if (rc) ··· 258 258 } 259 259 260 260 /* 261 - * Remap "oldmem" for zfcpdump 261 + * Remap "oldmem" for zfcp/nvme dump 262 262 * 263 263 * We only map available memory above HSA size. Memory below HSA size 264 264 * is read on demand using the copy_oldmem_page() function. ··· 283 283 } 284 284 285 285 /* 286 - * Remap "oldmem" for kdump or zfcpdump 286 + * Remap "oldmem" for kdump or zfcp/nvme dump 287 287 */ 288 288 int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from, 289 289 unsigned long pfn, unsigned long size, pgprot_t prot) ··· 632 632 u32 alloc_size; 633 633 u64 hdr_off; 634 634 635 - /* If we are not in kdump or zfcpdump mode return */ 636 - if (!OLDMEM_BASE && ipl_info.type != IPL_TYPE_FCP_DUMP) 635 + /* If we are not in kdump or zfcp/nvme dump mode return */ 636 + if (!OLDMEM_BASE && !is_ipl_type_dump()) 637 637 return 0; 638 - /* If we cannot get HSA size for zfcpdump return error */ 639 - if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp.hsa_size) 638 + /* If we cannot get HSA size for zfcp/nvme dump return error */ 639 + if (is_ipl_type_dump() && !sclp.hsa_size) 640 640 return -ENODEV; 641 641 642 642 /* For kdump, exclude previous crashkernel memory */
+2 -2
arch/s390/kernel/setup.c
··· 251 251 #ifdef CONFIG_CRASH_DUMP 252 252 static void __init setup_zfcpdump(void) 253 253 { 254 - if (ipl_info.type != IPL_TYPE_FCP_DUMP) 254 + if (!is_ipl_type_dump()) 255 255 return; 256 256 if (OLDMEM_BASE) 257 257 return; ··· 1175 1175 if (IS_ENABLED(CONFIG_EXPOLINE)) 1176 1176 nospec_init_branches(); 1177 1177 1178 - /* Setup zfcpdump support */ 1178 + /* Setup zfcp/nvme dump support */ 1179 1179 setup_zfcpdump(); 1180 1180 1181 1181 /* Add system specific data to the random pool */
+6 -6
arch/s390/kernel/smp.c
··· 606 606 /* 607 607 * Collect CPU state of the previous, crashed system. 608 608 * There are four cases: 609 - * 1) standard zfcp dump 610 - * condition: OLDMEM_BASE == NULL && ipl_info.type == IPL_TYPE_FCP_DUMP 609 + * 1) standard zfcp/nvme dump 610 + * condition: OLDMEM_BASE == NULL && is_ipl_type_dump() == true 611 611 * The state for all CPUs except the boot CPU needs to be collected 612 612 * with sigp stop-and-store-status. The boot CPU state is located in 613 613 * the absolute lowcore of the memory stored in the HSA. The zcore code 614 614 * will copy the boot CPU state from the HSA. 615 - * 2) stand-alone kdump for SCSI (zfcp dump with swapped memory) 616 - * condition: OLDMEM_BASE != NULL && ipl_info.type == IPL_TYPE_FCP_DUMP 615 + * 2) stand-alone kdump for SCSI/NVMe (zfcp/nvme dump with swapped memory) 616 + * condition: OLDMEM_BASE != NULL && is_ipl_type_dump() == true 617 617 * The state for all CPUs except the boot CPU needs to be collected 618 618 * with sigp stop-and-store-status. The firmware or the boot-loader 619 619 * stored the registers of the boot CPU in the absolute lowcore in the ··· 660 660 unsigned long page; 661 661 bool is_boot_cpu; 662 662 663 - if (!(OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP)) 663 + if (!(OLDMEM_BASE || is_ipl_type_dump())) 664 664 /* No previous system present, normal boot. */ 665 665 return; 666 666 /* Allocate a page as dumping area for the store status sigps */ ··· 686 686 /* Get the vector registers */ 687 687 smp_save_cpu_vxrs(sa, addr, is_boot_cpu, page); 688 688 /* 689 - * For a zfcp dump OLDMEM_BASE == NULL and the registers 689 + * For a zfcp/nvme dump OLDMEM_BASE == NULL and the registers 690 690 * of the boot CPU are stored in the HSA. To retrieve 691 691 * these registers an SCLP request is required which is 692 692 * done by drivers/s390/char/zcore.c:init_cpu_info()
+1 -1
drivers/s390/char/sclp_sdias.c
··· 257 257 258 258 int __init sclp_sdias_init(void) 259 259 { 260 - if (ipl_info.type != IPL_TYPE_FCP_DUMP) 260 + if (!is_ipl_type_dump()) 261 261 return 0; 262 262 sclp_sdias_sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA); 263 263 BUG_ON(!sclp_sdias_sccb);
+12 -5
drivers/s390/char/zcore.c
··· 1 1 // SPDX-License-Identifier: GPL-1.0+ 2 2 /* 3 3 * zcore module to export memory content and register sets for creating system 4 - * dumps on SCSI disks (zfcpdump). 4 + * dumps on SCSI/NVMe disks (zfcp/nvme dump). 5 5 * 6 6 * For more information please refer to Documentation/s390/zfcpdump.rst 7 7 * ··· 243 243 unsigned char arch; 244 244 int rc; 245 245 246 - if (ipl_info.type != IPL_TYPE_FCP_DUMP) 246 + if (!is_ipl_type_dump()) 247 247 return -ENODATA; 248 248 if (OLDMEM_BASE) 249 249 return -ENODATA; ··· 252 252 debug_register_view(zcore_dbf, &debug_sprintf_view); 253 253 debug_set_level(zcore_dbf, 6); 254 254 255 - TRACE("devno: %x\n", ipl_info.data.fcp.dev_id.devno); 256 - TRACE("wwpn: %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn); 257 - TRACE("lun: %llx\n", (unsigned long long) ipl_info.data.fcp.lun); 255 + if (ipl_info.type == IPL_TYPE_FCP_DUMP) { 256 + TRACE("type: fcp\n"); 257 + TRACE("devno: %x\n", ipl_info.data.fcp.dev_id.devno); 258 + TRACE("wwpn: %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn); 259 + TRACE("lun: %llx\n", (unsigned long long) ipl_info.data.fcp.lun); 260 + } else if (ipl_info.type == IPL_TYPE_NVME_DUMP) { 261 + TRACE("type: nvme\n"); 262 + TRACE("fid: %x\n", ipl_info.data.nvme.fid); 263 + TRACE("nsid: %x\n", ipl_info.data.nvme.nsid); 264 + } 258 265 259 266 rc = sclp_sdias_init(); 260 267 if (rc)