Skip to content

Commit

Permalink
[S390] kernel: Add OS info memory interface
Browse files Browse the repository at this point in the history
In order to allow kdump based stand-alone dump, some information
has to be passed from the old kernel to the new dump kernel. This
is done via a the struct "os_info" that contains the following fields:
 * crashkernel base and size
 * reipl block
 * vmcoreinfo
 * init function
A pointer to os_info is stored at a well known storage location
and the whole structure as well as all fields are secured with
checksums.

Signed-off-by: Michael Holzheu <[email protected]>
Signed-off-by: Martin Schwidefsky <[email protected]>
  • Loading branch information
Michael Holzheu authored and Martin Schwidefsky committed Mar 11, 2012
1 parent ad252ff commit 4857d4b
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 20 deletions.
8 changes: 6 additions & 2 deletions arch/s390/include/asm/lowcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ struct _lowcore {
__u32 ipib; /* 0x0e00 */
__u32 ipib_checksum; /* 0x0e04 */
__u32 vmcore_info; /* 0x0e08 */
__u8 pad_0x0e0c[0x0f00-0x0e0c]; /* 0x0e0c */
__u8 pad_0x0e0c[0x0e18-0x0e0c]; /* 0x0e0c */
__u32 os_info; /* 0x0e18 */
__u8 pad_0x0e1c[0x0f00-0x0e1c]; /* 0x0e1c */

/* Extended facility list */
__u64 stfle_fac_list[32]; /* 0x0f00 */
Expand Down Expand Up @@ -301,7 +303,9 @@ struct _lowcore {
__u64 ipib; /* 0x0e00 */
__u32 ipib_checksum; /* 0x0e08 */
__u64 vmcore_info; /* 0x0e0c */
__u8 pad_0x0e14[0x0f00-0x0e14]; /* 0x0e14 */
__u8 pad_0x0e14[0x0e18-0x0e14]; /* 0x0e14 */
__u64 os_info; /* 0x0e18 */
__u8 pad_0x0e20[0x0f00-0x0e20]; /* 0x0e20 */

/* Extended facility list */
__u64 stfle_fac_list[32]; /* 0x0f00 */
Expand Down
50 changes: 50 additions & 0 deletions arch/s390/include/asm/os_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* OS info memory interface
*
* Copyright IBM Corp. 2012
* Author(s): Michael Holzheu <[email protected]>
*/
#ifndef _ASM_S390_OS_INFO_H
#define _ASM_S390_OS_INFO_H

#define OS_INFO_VERSION_MAJOR 1
#define OS_INFO_VERSION_MINOR 1
#define OS_INFO_MAGIC 0x4f53494e464f535aULL /* OSINFOSZ */

#define OS_INFO_VMCOREINFO 0
#define OS_INFO_REIPL_BLOCK 1
#define OS_INFO_INIT_FN 2

struct os_info_entry {
u64 addr;
u64 size;
u32 csum;
} __packed;

struct os_info {
u64 magic;
u32 csum;
u16 version_major;
u16 version_minor;
u64 crashkernel_addr;
u64 crashkernel_size;
struct os_info_entry entry[3];
u8 reserved[4004];
} __packed;

void os_info_init(void);
void os_info_entry_add(int nr, void *ptr, u64 len);
void os_info_crashkernel_add(unsigned long base, unsigned long size);
u32 os_info_csum(struct os_info *os_info);

#ifdef CONFIG_CRASH_DUMP
void *os_info_old_entry(int nr, unsigned long *size);
int copy_from_oldmem(void *dest, void *src, size_t count);
#else
static inline void *os_info_old_entry(int nr, unsigned long *size)
{
return NULL;
}
#endif

#endif /* _ASM_S390_OS_INFO_H */
2 changes: 1 addition & 1 deletion arch/s390/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
sysinfo.o jump_label.o lgr.o
sysinfo.o jump_label.o lgr.o os_info.o

obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
Expand Down
37 changes: 27 additions & 10 deletions arch/s390/kernel/crash_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/bootmem.h>
#include <linux/elf.h>
#include <asm/ipl.h>
#include <asm/os_info.h>

#define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
Expand Down Expand Up @@ -51,7 +52,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
/*
* Copy memory from old kernel
*/
static int copy_from_oldmem(void *dest, void *src, size_t count)
int copy_from_oldmem(void *dest, void *src, size_t count)
{
unsigned long copied = 0;
int rc;
Expand Down Expand Up @@ -224,28 +225,44 @@ static void *nt_prpsinfo(void *ptr)
}

/*
* Initialize vmcoreinfo note (new kernel)
* Get vmcoreinfo using lowcore->vmcore_info (new kernel)
*/
static void *nt_vmcoreinfo(void *ptr)
static void *get_vmcoreinfo_old(unsigned long *size)
{
char nt_name[11], *vmcoreinfo;
Elf64_Nhdr note;
void *addr;

if (copy_from_oldmem(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
return ptr;
return NULL;
memset(nt_name, 0, sizeof(nt_name));
if (copy_from_oldmem(&note, addr, sizeof(note)))
return ptr;
return NULL;
if (copy_from_oldmem(nt_name, addr + sizeof(note), sizeof(nt_name) - 1))
return ptr;
return NULL;
if (strcmp(nt_name, "VMCOREINFO") != 0)
return ptr;
vmcoreinfo = kzalloc_panic(note.n_descsz + 1);
return NULL;
vmcoreinfo = kzalloc_panic(note.n_descsz);
if (copy_from_oldmem(vmcoreinfo, addr + 24, note.n_descsz))
return NULL;
*size = note.n_descsz;
return vmcoreinfo;
}

/*
* Initialize vmcoreinfo note (new kernel)
*/
static void *nt_vmcoreinfo(void *ptr)
{
unsigned long size;
void *vmcoreinfo;

vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size);
if (!vmcoreinfo)
vmcoreinfo = get_vmcoreinfo_old(&size);
if (!vmcoreinfo)
return ptr;
vmcoreinfo[note.n_descsz + 1] = 0;
return nt_init(ptr, 0, vmcoreinfo, note.n_descsz, "VMCOREINFO");
return nt_init(ptr, 0, vmcoreinfo, size, "VMCOREINFO");
}

/*
Expand Down
42 changes: 35 additions & 7 deletions arch/s390/kernel/ipl.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <asm/sclp.h>
#include <asm/checksum.h>
#include <asm/debug.h>
#include <asm/os_info.h>
#include "entry.h"

#define IPL_PARM_BLOCK_VERSION 0
Expand Down Expand Up @@ -951,6 +952,13 @@ static struct attribute_group reipl_nss_attr_group = {
.attrs = reipl_nss_attrs,
};

static void set_reipl_block_actual(struct ipl_parameter_block *reipl_block)
{
reipl_block_actual = reipl_block;
os_info_entry_add(OS_INFO_REIPL_BLOCK, reipl_block_actual,
reipl_block->hdr.len);
}

/* reipl type */

static int reipl_set_type(enum ipl_type type)
Expand All @@ -966,7 +974,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_CCW_VM;
else
reipl_method = REIPL_METHOD_CCW_CIO;
reipl_block_actual = reipl_block_ccw;
set_reipl_block_actual(reipl_block_ccw);
break;
case IPL_TYPE_FCP:
if (diag308_set_works)
Expand All @@ -975,7 +983,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_FCP_RO_VM;
else
reipl_method = REIPL_METHOD_FCP_RO_DIAG;
reipl_block_actual = reipl_block_fcp;
set_reipl_block_actual(reipl_block_fcp);
break;
case IPL_TYPE_FCP_DUMP:
reipl_method = REIPL_METHOD_FCP_DUMP;
Expand All @@ -985,7 +993,7 @@ static int reipl_set_type(enum ipl_type type)
reipl_method = REIPL_METHOD_NSS_DIAG;
else
reipl_method = REIPL_METHOD_NSS;
reipl_block_actual = reipl_block_nss;
set_reipl_block_actual(reipl_block_nss);
break;
case IPL_TYPE_UNKNOWN:
reipl_method = REIPL_METHOD_DEFAULT;
Expand Down Expand Up @@ -1257,6 +1265,29 @@ static int __init reipl_fcp_init(void)
return 0;
}

static int __init reipl_type_init(void)
{
enum ipl_type reipl_type = ipl_info.type;
struct ipl_parameter_block *reipl_block;
unsigned long size;

reipl_block = os_info_old_entry(OS_INFO_REIPL_BLOCK, &size);
if (!reipl_block)
goto out;
/*
* If we have an OS info reipl block, this will be used
*/
if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) {
memcpy(reipl_block_fcp, reipl_block, size);
reipl_type = IPL_TYPE_FCP;
} else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) {
memcpy(reipl_block_ccw, reipl_block, size);
reipl_type = IPL_TYPE_CCW;
}
out:
return reipl_set_type(reipl_type);
}

static int __init reipl_init(void)
{
int rc;
Expand All @@ -1278,10 +1309,7 @@ static int __init reipl_init(void)
rc = reipl_nss_init();
if (rc)
return rc;
rc = reipl_set_type(ipl_info.type);
if (rc)
return rc;
return 0;
return reipl_type_init();
}

static struct shutdown_action __refdata reipl_action = {
Expand Down
Loading

0 comments on commit 4857d4b

Please sign in to comment.