Skip to content

Commit

Permalink
[S390] kernel: Add z/VM LGR detection
Browse files Browse the repository at this point in the history
Currently the following mechanisms are available to move active
Linux on System z instances between machines:
* z/VM 6.2 SSI (Single System Image)
* Suspend/resume
For moving Linux instances in this patch the term LGR (Linux Guest
Relocation) is used. Because such an operation is critical, it
should be detectable from Linux. With this patch for both, a live
system and a kernel dump, the information about LGRs is accessible.
To identify a guest, stsi and stfle data is used. A new function
lgr_info_log() compares the current data (lgr_info_cur) with the
last recorded one (lgr_info_last). In case the two data sets differ,
lgr_info_cur is logged to the "lgr" s390dbf.

The following trigger points call lgr_info_log():
* panic
* die
* kdump
* LGR timer
* PSW restart
* QDIO recovery
* resume

This patch also changes the s390dbf hex_ascii view. Now only printable ASCII
characters are shown.

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 Mar 11, 2012
1 parent fde15c3 commit 3ab121a
Show file tree
Hide file tree
Showing 13 changed files with 297 additions and 31 deletions.
1 change: 1 addition & 0 deletions arch/s390/include/asm/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ void debug_unregister(debug_info_t* id);

void debug_set_level(debug_info_t* id, int new_level);

void debug_set_critical(void);
void debug_stop_all(void);

static inline debug_entry_t*
Expand Down
1 change: 1 addition & 0 deletions arch/s390/include/asm/ipl.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,6 @@ enum diag308_rc {
extern int diag308(unsigned long subcode, void *addr);
extern void diag308_reset(void);
extern void store_status(void);
extern void lgr_info_log(void);

#endif /* _ASM_S390_IPL_H */
34 changes: 34 additions & 0 deletions arch/s390/include/asm/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#ifndef __ASM_SYSTEM_H
#define __ASM_SYSTEM_H

#include <linux/preempt.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/setup.h>
Expand Down Expand Up @@ -248,6 +250,38 @@ static inline int test_facility(unsigned long nr)
return (*ptr & (0x80 >> (nr & 7))) != 0;
}

/**
* stfle - Store facility list extended
* @stfle_fac_list: array where facility list can be stored
* @size: size of passed in array in double words
*/
static inline void stfle(u64 *stfle_fac_list, int size)
{
unsigned long nr;

preempt_disable();
S390_lowcore.stfl_fac_list = 0;
asm volatile(
" .insn s,0xb2b10000,0(0)\n" /* stfl */
"0:\n"
EX_TABLE(0b, 0b)
: "=m" (S390_lowcore.stfl_fac_list));
nr = 4; /* bytes stored by stfl */
memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
if (S390_lowcore.stfl_fac_list & 0x01000000) {
/* More facility bits available with stfle */
register unsigned long reg0 asm("0") = size - 1;

asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */
: "+d" (reg0)
: "a" (stfle_fac_list)
: "memory", "cc");
nr = (reg0 + 1) * 8; /* # bytes stored by stfle */
}
memset((char *) stfle_fac_list + nr, 0, size * 8 - nr);
preempt_enable();
}

static inline unsigned short stap(void)
{
unsigned short cpu_address;
Expand Down
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
sysinfo.o jump_label.o lgr.o

obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
Expand Down
40 changes: 31 additions & 9 deletions arch/s390/kernel/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* arch/s390/kernel/debug.c
* S/390 debug facility
*
* Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Copyright IBM Corp. 1999, 2012
*
* Author(s): Michael Holzheu (holzheu@de.ibm.com),
* Holger Smolinski (Holger.Smolinski@de.ibm.com)
*
Expand Down Expand Up @@ -167,6 +167,7 @@ static debug_info_t *debug_area_last = NULL;
static DEFINE_MUTEX(debug_mutex);

static int initialized;
static int debug_critical;

static const struct file_operations debug_file_ops = {
.owner = THIS_MODULE,
Expand Down Expand Up @@ -932,6 +933,11 @@ debug_stop_all(void)
}


void debug_set_critical(void)
{
debug_critical = 1;
}

/*
* debug_event_common:
* - write debug entry with given size
Expand All @@ -945,7 +951,11 @@ debug_event_common(debug_info_t * id, int level, const void *buf, int len)

if (!debug_active || !id->areas)
return NULL;
spin_lock_irqsave(&id->lock, flags);
if (debug_critical) {
if (!spin_trylock_irqsave(&id->lock, flags))
return NULL;
} else
spin_lock_irqsave(&id->lock, flags);
active = get_active_entry(id);
memset(DEBUG_DATA(active), 0, id->buf_size);
memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
Expand All @@ -968,7 +978,11 @@ debug_entry_t

if (!debug_active || !id->areas)
return NULL;
spin_lock_irqsave(&id->lock, flags);
if (debug_critical) {
if (!spin_trylock_irqsave(&id->lock, flags))
return NULL;
} else
spin_lock_irqsave(&id->lock, flags);
active = get_active_entry(id);
memset(DEBUG_DATA(active), 0, id->buf_size);
memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
Expand Down Expand Up @@ -1013,7 +1027,11 @@ debug_sprintf_event(debug_info_t* id, int level,char *string,...)
return NULL;
numargs=debug_count_numargs(string);

spin_lock_irqsave(&id->lock, flags);
if (debug_critical) {
if (!spin_trylock_irqsave(&id->lock, flags))
return NULL;
} else
spin_lock_irqsave(&id->lock, flags);
active = get_active_entry(id);
curr_event=(debug_sprintf_entry_t *) DEBUG_DATA(active);
va_start(ap,string);
Expand Down Expand Up @@ -1047,7 +1065,11 @@ debug_sprintf_exception(debug_info_t* id, int level,char *string,...)

numargs=debug_count_numargs(string);

spin_lock_irqsave(&id->lock, flags);
if (debug_critical) {
if (!spin_trylock_irqsave(&id->lock, flags))
return NULL;
} else
spin_lock_irqsave(&id->lock, flags);
active = get_active_entry(id);
curr_event=(debug_sprintf_entry_t *)DEBUG_DATA(active);
va_start(ap,string);
Expand Down Expand Up @@ -1428,10 +1450,10 @@ debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
rc += sprintf(out_buf + rc, "| ");
for (i = 0; i < id->buf_size; i++) {
unsigned char c = in_buf[i];
if (!isprint(c))
rc += sprintf(out_buf + rc, ".");
else
if (isascii(c) && isprint(c))
rc += sprintf(out_buf + rc, "%c", c);
else
rc += sprintf(out_buf + rc, ".");
}
rc += sprintf(out_buf + rc, "\n");
return rc;
Expand Down
22 changes: 3 additions & 19 deletions arch/s390/kernel/early.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <asm/sysinfo.h>
#include <asm/cpcmd.h>
#include <asm/sclp.h>
#include <asm/system.h>
#include "entry.h"

/*
Expand Down Expand Up @@ -262,25 +263,8 @@ static noinline __init void setup_lowcore_early(void)

static noinline __init void setup_facility_list(void)
{
unsigned long nr;

S390_lowcore.stfl_fac_list = 0;
asm volatile(
" .insn s,0xb2b10000,0(0)\n" /* stfl */
"0:\n"
EX_TABLE(0b,0b) : "=m" (S390_lowcore.stfl_fac_list));
memcpy(&S390_lowcore.stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
nr = 4; /* # bytes stored by stfl */
if (test_facility(7)) {
/* More facility bits available with stfle */
register unsigned long reg0 asm("0") = MAX_FACILITY_BIT/64 - 1;
asm volatile(".insn s,0xb2b00000,%0" /* stfle */
: "=m" (S390_lowcore.stfle_fac_list), "+d" (reg0)
: : "cc");
nr = (reg0 + 1) * 8; /* # bytes stored by stfle */
}
memset((char *) S390_lowcore.stfle_fac_list + nr, 0,
MAX_FACILITY_BIT/8 - nr);
stfle(S390_lowcore.stfle_fac_list,
ARRAY_SIZE(S390_lowcore.stfle_fac_list));
}

static noinline __init void setup_hpage(void)
Expand Down
6 changes: 6 additions & 0 deletions arch/s390/kernel/ipl.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/fs.h>
#include <linux/gfp.h>
#include <linux/crash_dump.h>
#include <linux/debug_locks.h>
#include <asm/ipl.h>
#include <asm/smp.h>
#include <asm/setup.h>
Expand All @@ -26,6 +27,7 @@
#include <asm/reset.h>
#include <asm/sclp.h>
#include <asm/checksum.h>
#include <asm/debug.h>
#include "entry.h"

#define IPL_PARM_BLOCK_VERSION 0
Expand Down Expand Up @@ -1692,6 +1694,7 @@ static struct kobj_attribute on_panic_attr =

static void do_panic(void)
{
lgr_info_log();
on_panic_trigger.action->fn(&on_panic_trigger);
stop_run(&on_panic_trigger);
}
Expand Down Expand Up @@ -1729,6 +1732,9 @@ static void __do_restart(void *ignore)

void do_restart(void)
{
tracing_off();
debug_locks_off();
lgr_info_log();
smp_call_online_cpu(__do_restart, NULL);
}

Expand Down
Loading

0 comments on commit 3ab121a

Please sign in to comment.