Skip to content

Commit

Permalink
s390/sclp: Determine HSA size dynamically for zfcpdump
Browse files Browse the repository at this point in the history
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: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Michael Holzheu authored and Martin Schwidefsky committed Nov 15, 2013
1 parent f8049e3 commit e657d8f
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 32 deletions.
2 changes: 2 additions & 0 deletions arch/s390/include/asm/sclp.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,7 @@ bool sclp_has_vt220(void);
int sclp_pci_configure(u32 fid);
int sclp_pci_deconfigure(u32 fid);
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 */
3 changes: 0 additions & 3 deletions arch/s390/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
#endif /* CONFIG_64BIT */

#define ZFCPDUMP_HSA_SIZE (32UL<<20)
#define ZFCPDUMP_HSA_SIZE_MAX (64UL<<20)

/*
* Console mode. Override with conmode=
*/
Expand Down
22 changes: 13 additions & 9 deletions arch/s390/kernel/crash_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ static void *elfcorehdr_newmem;
/*
* 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.
*/
static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize,
unsigned long src, int userbuf)
{
int rc;

if (src < ZFCPDUMP_HSA_SIZE) {
if (src < sclp_get_hsa_size()) {
rc = memcpy_hsa(buf, src, csize, userbuf);
} else {
if (userbuf)
Expand Down Expand Up @@ -188,18 +188,19 @@ static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma,
/*
* Remap "oldmem" for zfcpdump
*
* We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below
* ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function.
* We only map available memory above HSA size. Memory below HSA size
* is read on demand using the copy_oldmem_page() function.
*/
static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma,
unsigned long from,
unsigned long pfn,
unsigned long size, pgprot_t prot)
{
unsigned long hsa_end = sclp_get_hsa_size();
unsigned long size_hsa;

if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) {
size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT));
if (pfn < hsa_end >> PAGE_SHIFT) {
size_hsa = min(size, hsa_end - (pfn << PAGE_SHIFT));
if (size == size_hsa)
return 0;
size -= size_hsa;
Expand Down Expand Up @@ -238,9 +239,9 @@ int copy_from_oldmem(void *dest, void *src, size_t count)
return rc;
}
} else {
if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) {
copied = min(count,
ZFCPDUMP_HSA_SIZE - (unsigned long) src);
unsigned long hsa_end = sclp_get_hsa_size();
if ((unsigned long) src < hsa_end) {
copied = min(count, hsa_end - (unsigned long) src);
rc = memcpy_hsa(dest, (unsigned long) src, copied, 0);
if (rc)
return rc;
Expand Down Expand Up @@ -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_addr != ELFCORE_ADDR_MAX)
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();

alloc_size = 0x1000 + get_cpu_cnt() * 0x300 +
Expand Down
1 change: 1 addition & 0 deletions arch/s390/kernel/early.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ void __init startup_init(void)
detect_machine_facilities();
setup_topology();
sclp_facilities_detect();
sclp_hsa_size_detect();
#ifdef CONFIG_DYNAMIC_FTRACE
S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
#endif
Expand Down
7 changes: 4 additions & 3 deletions arch/s390/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,9 @@ static void __init setup_memory_end(void)


#ifdef CONFIG_ZFCPDUMP
if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) {
memory_end = ZFCPDUMP_HSA_SIZE;
if (ipl_info.type == IPL_TYPE_FCP_DUMP &&
!OLDMEM_BASE && sclp_get_hsa_size()) {
memory_end = sclp_get_hsa_size();
memory_end_set = 1;
}
#endif
Expand Down Expand Up @@ -586,7 +587,7 @@ static unsigned long __init find_crash_base(unsigned long crash_size,
crash_base = (chunk->addr + chunk->size) - crash_size;
if (crash_base < crash_size)
continue;
if (crash_base < ZFCPDUMP_HSA_SIZE_MAX)
if (crash_base < sclp_get_hsa_size())
continue;
if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE)
continue;
Expand Down
3 changes: 2 additions & 1 deletion drivers/s390/char/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#

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_CONSOLE) += con3270.o
Expand Down
1 change: 1 addition & 0 deletions drivers/s390/char/sclp.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ int sclp_deactivate(void);
int sclp_reactivate(void);
int sclp_service_call(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);
void sclp_sdias_exit(void);
Expand Down
2 changes: 1 addition & 1 deletion drivers/s390/char/sclp_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static u8 sclp_fac84;
static unsigned long long rzm;
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;

Expand Down
111 changes: 111 additions & 0 deletions drivers/s390/char/sclp_early.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* 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;
}
22 changes: 7 additions & 15 deletions drivers/s390/char/zcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,9 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count,
mem_offs = 0;

/* Copy from HSA data */
if (*ppos < (ZFCPDUMP_HSA_SIZE + HEADER_SIZE)) {
size = min((count - hdr_count), (size_t) (ZFCPDUMP_HSA_SIZE
- mem_start));
if (*ppos < sclp_get_hsa_size() + HEADER_SIZE) {
size = min((count - hdr_count),
(size_t) (sclp_get_hsa_size() - mem_start));
rc = memcpy_hsa_user(buf + hdr_count, mem_start, size);
if (rc)
goto fail;
Expand Down Expand Up @@ -490,7 +490,7 @@ static ssize_t zcore_hsa_read(struct file *filp, char __user *buf,
static char str[18];

if (hsa_available)
snprintf(str, sizeof(str), "%lx\n", ZFCPDUMP_HSA_SIZE);
snprintf(str, sizeof(str), "%lx\n", sclp_get_hsa_size());
else
snprintf(str, sizeof(str), "0\n");
return simple_read_from_buffer(buf, count, ppos, str, strlen(str));
Expand Down Expand Up @@ -584,17 +584,9 @@ static int __init sys_info_init(enum arch_id arch, unsigned long mem_end)

static int __init check_sdias(void)
{
int rc, act_hsa_size;

rc = sclp_sdias_blk_count();
if (rc < 0) {
if (!sclp_get_hsa_size()) {
TRACE("Could not determine HSA size\n");
return rc;
}
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 -ENODEV;
}
return 0;
}
Expand Down Expand Up @@ -662,7 +654,7 @@ static int __init zcore_reipl_init(void)
ipl_block = (void *) __get_free_page(GFP_KERNEL);
if (!ipl_block)
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);
else
rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE);
Expand Down

0 comments on commit e657d8f

Please sign in to comment.