Commit e657d8fe authored by Michael Holzheu's avatar Michael Holzheu Committed by Martin Schwidefsky

s390/sclp: Determine HSA size dynamically for zfcpdump

Currently we have hardcoded the HSA size to 32 MiB. With this patch the
HSA size is determined dynamically via SCLP in early.c.
Reviewed-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent f8049e3e
...@@ -57,5 +57,7 @@ bool sclp_has_vt220(void); ...@@ -57,5 +57,7 @@ bool sclp_has_vt220(void);
int sclp_pci_configure(u32 fid); int sclp_pci_configure(u32 fid);
int sclp_pci_deconfigure(u32 fid); int sclp_pci_deconfigure(u32 fid);
int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode);
void sclp_hsa_size_detect(void);
unsigned long sclp_get_hsa_size(void);
#endif /* _ASM_S390_SCLP_H */ #endif /* _ASM_S390_SCLP_H */
...@@ -107,9 +107,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr, ...@@ -107,9 +107,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
#define MACHINE_HAS_RRBM (S390_lowcore.machine_flags & MACHINE_FLAG_RRBM) #define MACHINE_HAS_RRBM (S390_lowcore.machine_flags & MACHINE_FLAG_RRBM)
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
#define ZFCPDUMP_HSA_SIZE (32UL<<20)
#define ZFCPDUMP_HSA_SIZE_MAX (64UL<<20)
/* /*
* Console mode. Override with conmode= * Console mode. Override with conmode=
*/ */
......
...@@ -95,7 +95,7 @@ static void *elfcorehdr_newmem; ...@@ -95,7 +95,7 @@ static void *elfcorehdr_newmem;
/* /*
* Copy one page from zfcpdump "oldmem" * Copy one page from zfcpdump "oldmem"
* *
* For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise * For pages below HSA size memory from the HSA is copied. Otherwise
* real memory copy is used. * real memory copy is used.
*/ */
static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize,
...@@ -103,7 +103,7 @@ static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, ...@@ -103,7 +103,7 @@ static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize,
{ {
int rc; int rc;
if (src < ZFCPDUMP_HSA_SIZE) { if (src < sclp_get_hsa_size()) {
rc = memcpy_hsa(buf, src, csize, userbuf); rc = memcpy_hsa(buf, src, csize, userbuf);
} else { } else {
if (userbuf) if (userbuf)
...@@ -188,18 +188,19 @@ static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma, ...@@ -188,18 +188,19 @@ static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,
/* /*
* Remap "oldmem" for zfcpdump * Remap "oldmem" for zfcpdump
* *
* We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below * We only map available memory above HSA size. Memory below HSA size
* ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function. * is read on demand using the copy_oldmem_page() function.
*/ */
static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma, static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,
unsigned long from, unsigned long from,
unsigned long pfn, unsigned long pfn,
unsigned long size, pgprot_t prot) unsigned long size, pgprot_t prot)
{ {
unsigned long hsa_end = sclp_get_hsa_size();
unsigned long size_hsa; unsigned long size_hsa;
if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) { if (pfn < hsa_end >> PAGE_SHIFT) {
size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT)); size_hsa = min(size, hsa_end - (pfn << PAGE_SHIFT));
if (size == size_hsa) if (size == size_hsa)
return 0; return 0;
size -= size_hsa; size -= size_hsa;
...@@ -238,9 +239,9 @@ int copy_from_oldmem(void *dest, void *src, size_t count) ...@@ -238,9 +239,9 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
return rc; return rc;
} }
} else { } else {
if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) { unsigned long hsa_end = sclp_get_hsa_size();
copied = min(count, if ((unsigned long) src < hsa_end) {
ZFCPDUMP_HSA_SIZE - (unsigned long) src); copied = min(count, hsa_end - (unsigned long) src);
rc = memcpy_hsa(dest, (unsigned long) src, copied, 0); rc = memcpy_hsa(dest, (unsigned long) src, copied, 0);
if (rc) if (rc)
return rc; return rc;
...@@ -580,6 +581,9 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) ...@@ -580,6 +581,9 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
/* If elfcorehdr= has been passed via cmdline, we use that one */ /* If elfcorehdr= has been passed via cmdline, we use that one */
if (elfcorehdr_addr != ELFCORE_ADDR_MAX) if (elfcorehdr_addr != ELFCORE_ADDR_MAX)
return 0; return 0;
/* If we cannot get HSA size for zfcpdump return error */
if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp_get_hsa_size())
return -ENODEV;
mem_chunk_cnt = get_mem_chunk_cnt(); mem_chunk_cnt = get_mem_chunk_cnt();
alloc_size = 0x1000 + get_cpu_cnt() * 0x300 + alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
......
...@@ -484,6 +484,7 @@ void __init startup_init(void) ...@@ -484,6 +484,7 @@ void __init startup_init(void)
detect_machine_facilities(); detect_machine_facilities();
setup_topology(); setup_topology();
sclp_facilities_detect(); sclp_facilities_detect();
sclp_hsa_size_detect();
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
S390_lowcore.ftrace_func = (unsigned long)ftrace_caller; S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
#endif #endif
......
...@@ -471,8 +471,9 @@ static void __init setup_memory_end(void) ...@@ -471,8 +471,9 @@ static void __init setup_memory_end(void)
#ifdef CONFIG_ZFCPDUMP #ifdef CONFIG_ZFCPDUMP
if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) { if (ipl_info.type == IPL_TYPE_FCP_DUMP &&
memory_end = ZFCPDUMP_HSA_SIZE; !OLDMEM_BASE && sclp_get_hsa_size()) {
memory_end = sclp_get_hsa_size();
memory_end_set = 1; memory_end_set = 1;
} }
#endif #endif
...@@ -586,7 +587,7 @@ static unsigned long __init find_crash_base(unsigned long crash_size, ...@@ -586,7 +587,7 @@ static unsigned long __init find_crash_base(unsigned long crash_size,
crash_base = (chunk->addr + chunk->size) - crash_size; crash_base = (chunk->addr + chunk->size) - crash_size;
if (crash_base < crash_size) if (crash_base < crash_size)
continue; continue;
if (crash_base < ZFCPDUMP_HSA_SIZE_MAX) if (crash_base < sclp_get_hsa_size())
continue; continue;
if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE) if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE)
continue; continue;
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
# #
obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o \
sclp_early.o
obj-$(CONFIG_TN3270) += raw3270.o obj-$(CONFIG_TN3270) += raw3270.o
obj-$(CONFIG_TN3270_CONSOLE) += con3270.o obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
......
...@@ -172,6 +172,7 @@ int sclp_deactivate(void); ...@@ -172,6 +172,7 @@ int sclp_deactivate(void);
int sclp_reactivate(void); int sclp_reactivate(void);
int sclp_service_call(sclp_cmdw_t command, void *sccb); int sclp_service_call(sclp_cmdw_t command, void *sccb);
int sclp_sync_request(sclp_cmdw_t command, void *sccb); int sclp_sync_request(sclp_cmdw_t command, void *sccb);
int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb);
int sclp_sdias_init(void); int sclp_sdias_init(void);
void sclp_sdias_exit(void); void sclp_sdias_exit(void);
......
...@@ -59,7 +59,7 @@ static u8 sclp_fac84; ...@@ -59,7 +59,7 @@ static u8 sclp_fac84;
static unsigned long long rzm; static unsigned long long rzm;
static unsigned long long rnmax; static unsigned long long rnmax;
static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
{ {
int rc; int rc;
......
/*
* SCLP early driver
*
* Copyright IBM Corp. 2013
*/
#define KMSG_COMPONENT "sclp_early"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <asm/sclp.h>
#include <asm/ipl.h>
#include "sclp_sdias.h"
#include "sclp.h"
static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE);
static unsigned long sclp_hsa_size;
static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb)
{
int rc;
do {
rc = sclp_cmd_sync_early(cmd, sccb);
} while (rc == -EBUSY);
if (rc)
return -EIO;
if (((struct sccb_header *) sccb)->response_code != 0x0020)
return -EIO;
return 0;
}
static void __init sccb_init_eq_size(struct sdias_sccb *sccb)
{
memset(sccb, 0, sizeof(*sccb));
sccb->hdr.length = sizeof(*sccb);
sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf);
sccb->evbuf.hdr.type = EVTYP_SDIAS;
sccb->evbuf.event_qual = SDIAS_EQ_SIZE;
sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP;
sccb->evbuf.event_id = 4712;
sccb->evbuf.dbs = 1;
}
static int __init sclp_set_event_mask(unsigned long receive_mask,
unsigned long send_mask)
{
struct init_sccb *sccb = (void *) &sccb_early;
memset(sccb, 0, sizeof(*sccb));
sccb->header.length = sizeof(*sccb);
sccb->mask_length = sizeof(sccb_mask_t);
sccb->receive_mask = receive_mask;
sccb->send_mask = send_mask;
return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb);
}
static long __init sclp_hsa_size_init(void)
{
struct sdias_sccb *sccb = (void *) &sccb_early;
sccb_init_eq_size(sccb);
if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb))
return -EIO;
if (sccb->evbuf.blk_cnt != 0)
return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE;
return 0;
}
static long __init sclp_hsa_copy_wait(void)
{
struct sccb_header *sccb = (void *) &sccb_early;
memset(sccb, 0, PAGE_SIZE);
sccb->length = PAGE_SIZE;
if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb))
return -EIO;
return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE;
}
unsigned long sclp_get_hsa_size(void)
{
return sclp_hsa_size;
}
void __init sclp_hsa_size_detect(void)
{
long size;
/* First try synchronous interface (LPAR) */
if (sclp_set_event_mask(0, 0x40000010))
return;
size = sclp_hsa_size_init();
if (size < 0)
return;
if (size != 0)
goto out;
/* Then try asynchronous interface (z/VM) */
if (sclp_set_event_mask(0x00000010, 0x40000010))
return;
size = sclp_hsa_size_init();
if (size < 0)
return;
size = sclp_hsa_copy_wait();
if (size < 0)
return;
out:
sclp_set_event_mask(0, 0);
sclp_hsa_size = size;
}
...@@ -328,9 +328,9 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count, ...@@ -328,9 +328,9 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,
mem_offs = 0; mem_offs = 0;
/* Copy from HSA data */ /* Copy from HSA data */
if (*ppos < (ZFCPDUMP_HSA_SIZE + HEADER_SIZE)) { if (*ppos < sclp_get_hsa_size() + HEADER_SIZE) {
size = min((count - hdr_count), (size_t) (ZFCPDUMP_HSA_SIZE size = min((count - hdr_count),
- mem_start)); (size_t) (sclp_get_hsa_size() - mem_start));
rc = memcpy_hsa_user(buf + hdr_count, mem_start, size); rc = memcpy_hsa_user(buf + hdr_count, mem_start, size);
if (rc) if (rc)
goto fail; goto fail;
...@@ -490,7 +490,7 @@ static ssize_t zcore_hsa_read(struct file *filp, char __user *buf, ...@@ -490,7 +490,7 @@ static ssize_t zcore_hsa_read(struct file *filp, char __user *buf,
static char str[18]; static char str[18];
if (hsa_available) if (hsa_available)
snprintf(str, sizeof(str), "%lx\n", ZFCPDUMP_HSA_SIZE); snprintf(str, sizeof(str), "%lx\n", sclp_get_hsa_size());
else else
snprintf(str, sizeof(str), "0\n"); snprintf(str, sizeof(str), "0\n");
return simple_read_from_buffer(buf, count, ppos, str, strlen(str)); return simple_read_from_buffer(buf, count, ppos, str, strlen(str));
...@@ -584,17 +584,9 @@ static int __init sys_info_init(enum arch_id arch, unsigned long mem_end) ...@@ -584,17 +584,9 @@ static int __init sys_info_init(enum arch_id arch, unsigned long mem_end)
static int __init check_sdias(void) static int __init check_sdias(void)
{ {
int rc, act_hsa_size; if (!sclp_get_hsa_size()) {
rc = sclp_sdias_blk_count();
if (rc < 0) {
TRACE("Could not determine HSA size\n"); TRACE("Could not determine HSA size\n");
return rc; return -ENODEV;
}
act_hsa_size = (rc - 1) * PAGE_SIZE;
if (act_hsa_size < ZFCPDUMP_HSA_SIZE) {
TRACE("HSA size too small: %i\n", act_hsa_size);
return -EINVAL;
} }
return 0; return 0;
} }
...@@ -662,7 +654,7 @@ static int __init zcore_reipl_init(void) ...@@ -662,7 +654,7 @@ static int __init zcore_reipl_init(void)
ipl_block = (void *) __get_free_page(GFP_KERNEL); ipl_block = (void *) __get_free_page(GFP_KERNEL);
if (!ipl_block) if (!ipl_block)
return -ENOMEM; return -ENOMEM;
if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE) if (ipib_info.ipib < sclp_get_hsa_size())
rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE);
else else
rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment