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>
This commit is contained in:
parent
d9f12e48d0
commit
bd37b36832
|
@ -280,14 +280,23 @@ void parse_boot_command_line(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_ipl_block_dump(void)
|
||||||
|
{
|
||||||
|
if (ipl_block.pb0_hdr.pbt == IPL_PBT_FCP &&
|
||||||
|
ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP)
|
||||||
|
return true;
|
||||||
|
if (ipl_block.pb0_hdr.pbt == IPL_PBT_NVME &&
|
||||||
|
ipl_block.nvme.opt == IPL_PB0_NVME_OPT_DUMP)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void setup_memory_end(void)
|
void setup_memory_end(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_CRASH_DUMP
|
#ifdef CONFIG_CRASH_DUMP
|
||||||
if (OLDMEM_BASE) {
|
if (OLDMEM_BASE) {
|
||||||
kaslr_enabled = 0;
|
kaslr_enabled = 0;
|
||||||
} else if (ipl_block_valid &&
|
} else if (ipl_block_valid && is_ipl_block_dump()) {
|
||||||
ipl_block.pb0_hdr.pbt == IPL_PBT_FCP &&
|
|
||||||
ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP) {
|
|
||||||
kaslr_enabled = 0;
|
kaslr_enabled = 0;
|
||||||
if (!sclp_early_get_hsa_size(&memory_end) && memory_end)
|
if (!sclp_early_get_hsa_size(&memory_end) && memory_end)
|
||||||
memory_end_set = 1;
|
memory_end_set = 1;
|
||||||
|
|
|
@ -95,6 +95,12 @@ extern struct ipl_info ipl_info;
|
||||||
extern void setup_ipl(void);
|
extern void setup_ipl(void);
|
||||||
extern void set_os_info_reipl_block(void);
|
extern void set_os_info_reipl_block(void);
|
||||||
|
|
||||||
|
static inline bool is_ipl_type_dump(void)
|
||||||
|
{
|
||||||
|
return (ipl_info.type == IPL_TYPE_FCP_DUMP) ||
|
||||||
|
(ipl_info.type == IPL_TYPE_NVME_DUMP);
|
||||||
|
}
|
||||||
|
|
||||||
struct ipl_report {
|
struct ipl_report {
|
||||||
struct ipl_parameter_block *ipib;
|
struct ipl_parameter_block *ipib;
|
||||||
struct list_head components;
|
struct list_head components;
|
||||||
|
|
|
@ -141,7 +141,7 @@ int copy_oldmem_kernel(void *dst, void *src, size_t count)
|
||||||
while (count) {
|
while (count) {
|
||||||
from = __pa(src);
|
from = __pa(src);
|
||||||
if (!OLDMEM_BASE && from < sclp.hsa_size) {
|
if (!OLDMEM_BASE && from < sclp.hsa_size) {
|
||||||
/* Copy from zfcpdump HSA area */
|
/* Copy from zfcp/nvme dump HSA area */
|
||||||
len = min(count, sclp.hsa_size - from);
|
len = min(count, sclp.hsa_size - from);
|
||||||
rc = memcpy_hsa_kernel(dst, from, len);
|
rc = memcpy_hsa_kernel(dst, from, len);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -184,7 +184,7 @@ static int copy_oldmem_user(void __user *dst, void *src, size_t count)
|
||||||
while (count) {
|
while (count) {
|
||||||
from = __pa(src);
|
from = __pa(src);
|
||||||
if (!OLDMEM_BASE && from < sclp.hsa_size) {
|
if (!OLDMEM_BASE && from < sclp.hsa_size) {
|
||||||
/* Copy from zfcpdump HSA area */
|
/* Copy from zfcp/nvme dump HSA area */
|
||||||
len = min(count, sclp.hsa_size - from);
|
len = min(count, sclp.hsa_size - from);
|
||||||
rc = memcpy_hsa_user(dst, from, len);
|
rc = memcpy_hsa_user(dst, from, len);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -258,7 +258,7 @@ static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remap "oldmem" for zfcpdump
|
* Remap "oldmem" for zfcp/nvme dump
|
||||||
*
|
*
|
||||||
* We only map available memory above HSA size. Memory below HSA size
|
* We only map available memory above HSA size. Memory below HSA size
|
||||||
* is read on demand using the copy_oldmem_page() function.
|
* is read on demand using the copy_oldmem_page() function.
|
||||||
|
@ -283,7 +283,7 @@ static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remap "oldmem" for kdump or zfcpdump
|
* Remap "oldmem" for kdump or zfcp/nvme dump
|
||||||
*/
|
*/
|
||||||
int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
|
int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
|
||||||
unsigned long pfn, unsigned long size, pgprot_t prot)
|
unsigned long pfn, unsigned long size, pgprot_t prot)
|
||||||
|
@ -632,11 +632,11 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
|
||||||
u32 alloc_size;
|
u32 alloc_size;
|
||||||
u64 hdr_off;
|
u64 hdr_off;
|
||||||
|
|
||||||
/* If we are not in kdump or zfcpdump mode return */
|
/* If we are not in kdump or zfcp/nvme dump mode return */
|
||||||
if (!OLDMEM_BASE && ipl_info.type != IPL_TYPE_FCP_DUMP)
|
if (!OLDMEM_BASE && !is_ipl_type_dump())
|
||||||
return 0;
|
return 0;
|
||||||
/* If we cannot get HSA size for zfcpdump return error */
|
/* If we cannot get HSA size for zfcp/nvme dump return error */
|
||||||
if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp.hsa_size)
|
if (is_ipl_type_dump() && !sclp.hsa_size)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* For kdump, exclude previous crashkernel memory */
|
/* For kdump, exclude previous crashkernel memory */
|
||||||
|
|
|
@ -251,7 +251,7 @@ static void __init conmode_default(void)
|
||||||
#ifdef CONFIG_CRASH_DUMP
|
#ifdef CONFIG_CRASH_DUMP
|
||||||
static void __init setup_zfcpdump(void)
|
static void __init setup_zfcpdump(void)
|
||||||
{
|
{
|
||||||
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
|
if (!is_ipl_type_dump())
|
||||||
return;
|
return;
|
||||||
if (OLDMEM_BASE)
|
if (OLDMEM_BASE)
|
||||||
return;
|
return;
|
||||||
|
@ -1175,7 +1175,7 @@ void __init setup_arch(char **cmdline_p)
|
||||||
if (IS_ENABLED(CONFIG_EXPOLINE))
|
if (IS_ENABLED(CONFIG_EXPOLINE))
|
||||||
nospec_init_branches();
|
nospec_init_branches();
|
||||||
|
|
||||||
/* Setup zfcpdump support */
|
/* Setup zfcp/nvme dump support */
|
||||||
setup_zfcpdump();
|
setup_zfcpdump();
|
||||||
|
|
||||||
/* Add system specific data to the random pool */
|
/* Add system specific data to the random pool */
|
||||||
|
|
|
@ -606,14 +606,14 @@ int smp_store_status(int cpu)
|
||||||
/*
|
/*
|
||||||
* Collect CPU state of the previous, crashed system.
|
* Collect CPU state of the previous, crashed system.
|
||||||
* There are four cases:
|
* There are four cases:
|
||||||
* 1) standard zfcp dump
|
* 1) standard zfcp/nvme dump
|
||||||
* condition: OLDMEM_BASE == NULL && ipl_info.type == IPL_TYPE_FCP_DUMP
|
* condition: OLDMEM_BASE == NULL && is_ipl_type_dump() == true
|
||||||
* The state for all CPUs except the boot CPU needs to be collected
|
* The state for all CPUs except the boot CPU needs to be collected
|
||||||
* with sigp stop-and-store-status. The boot CPU state is located in
|
* with sigp stop-and-store-status. The boot CPU state is located in
|
||||||
* the absolute lowcore of the memory stored in the HSA. The zcore code
|
* the absolute lowcore of the memory stored in the HSA. The zcore code
|
||||||
* will copy the boot CPU state from the HSA.
|
* will copy the boot CPU state from the HSA.
|
||||||
* 2) stand-alone kdump for SCSI (zfcp dump with swapped memory)
|
* 2) stand-alone kdump for SCSI/NVMe (zfcp/nvme dump with swapped memory)
|
||||||
* condition: OLDMEM_BASE != NULL && ipl_info.type == IPL_TYPE_FCP_DUMP
|
* condition: OLDMEM_BASE != NULL && is_ipl_type_dump() == true
|
||||||
* The state for all CPUs except the boot CPU needs to be collected
|
* The state for all CPUs except the boot CPU needs to be collected
|
||||||
* with sigp stop-and-store-status. The firmware or the boot-loader
|
* with sigp stop-and-store-status. The firmware or the boot-loader
|
||||||
* stored the registers of the boot CPU in the absolute lowcore in the
|
* stored the registers of the boot CPU in the absolute lowcore in the
|
||||||
|
@ -660,7 +660,7 @@ void __init smp_save_dump_cpus(void)
|
||||||
unsigned long page;
|
unsigned long page;
|
||||||
bool is_boot_cpu;
|
bool is_boot_cpu;
|
||||||
|
|
||||||
if (!(OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP))
|
if (!(OLDMEM_BASE || is_ipl_type_dump()))
|
||||||
/* No previous system present, normal boot. */
|
/* No previous system present, normal boot. */
|
||||||
return;
|
return;
|
||||||
/* Allocate a page as dumping area for the store status sigps */
|
/* Allocate a page as dumping area for the store status sigps */
|
||||||
|
@ -686,7 +686,7 @@ void __init smp_save_dump_cpus(void)
|
||||||
/* Get the vector registers */
|
/* Get the vector registers */
|
||||||
smp_save_cpu_vxrs(sa, addr, is_boot_cpu, page);
|
smp_save_cpu_vxrs(sa, addr, is_boot_cpu, page);
|
||||||
/*
|
/*
|
||||||
* For a zfcp dump OLDMEM_BASE == NULL and the registers
|
* For a zfcp/nvme dump OLDMEM_BASE == NULL and the registers
|
||||||
* of the boot CPU are stored in the HSA. To retrieve
|
* of the boot CPU are stored in the HSA. To retrieve
|
||||||
* these registers an SCLP request is required which is
|
* these registers an SCLP request is required which is
|
||||||
* done by drivers/s390/char/zcore.c:init_cpu_info()
|
* done by drivers/s390/char/zcore.c:init_cpu_info()
|
||||||
|
|
|
@ -257,7 +257,7 @@ static int __init sclp_sdias_init_async(void)
|
||||||
|
|
||||||
int __init sclp_sdias_init(void)
|
int __init sclp_sdias_init(void)
|
||||||
{
|
{
|
||||||
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
|
if (!is_ipl_type_dump())
|
||||||
return 0;
|
return 0;
|
||||||
sclp_sdias_sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA);
|
sclp_sdias_sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA);
|
||||||
BUG_ON(!sclp_sdias_sccb);
|
BUG_ON(!sclp_sdias_sccb);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-1.0+
|
// SPDX-License-Identifier: GPL-1.0+
|
||||||
/*
|
/*
|
||||||
* zcore module to export memory content and register sets for creating system
|
* zcore module to export memory content and register sets for creating system
|
||||||
* dumps on SCSI disks (zfcpdump).
|
* dumps on SCSI/NVMe disks (zfcp/nvme dump).
|
||||||
*
|
*
|
||||||
* For more information please refer to Documentation/s390/zfcpdump.rst
|
* For more information please refer to Documentation/s390/zfcpdump.rst
|
||||||
*
|
*
|
||||||
|
@ -243,7 +243,7 @@ static int __init zcore_init(void)
|
||||||
unsigned char arch;
|
unsigned char arch;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
|
if (!is_ipl_type_dump())
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
if (OLDMEM_BASE)
|
if (OLDMEM_BASE)
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
|
@ -252,9 +252,16 @@ static int __init zcore_init(void)
|
||||||
debug_register_view(zcore_dbf, &debug_sprintf_view);
|
debug_register_view(zcore_dbf, &debug_sprintf_view);
|
||||||
debug_set_level(zcore_dbf, 6);
|
debug_set_level(zcore_dbf, 6);
|
||||||
|
|
||||||
|
if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
|
||||||
|
TRACE("type: fcp\n");
|
||||||
TRACE("devno: %x\n", ipl_info.data.fcp.dev_id.devno);
|
TRACE("devno: %x\n", ipl_info.data.fcp.dev_id.devno);
|
||||||
TRACE("wwpn: %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn);
|
TRACE("wwpn: %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn);
|
||||||
TRACE("lun: %llx\n", (unsigned long long) ipl_info.data.fcp.lun);
|
TRACE("lun: %llx\n", (unsigned long long) ipl_info.data.fcp.lun);
|
||||||
|
} else if (ipl_info.type == IPL_TYPE_NVME_DUMP) {
|
||||||
|
TRACE("type: nvme\n");
|
||||||
|
TRACE("fid: %x\n", ipl_info.data.nvme.fid);
|
||||||
|
TRACE("nsid: %x\n", ipl_info.data.nvme.nsid);
|
||||||
|
}
|
||||||
|
|
||||||
rc = sclp_sdias_init();
|
rc = sclp_sdias_init();
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|
Loading…
Reference in a new issue