Skip to content

Commit

Permalink
[S390] s390: hibernation support for s390
Browse files Browse the repository at this point in the history
This patch introduces the hibernation backend support to the
s390 architecture. Now it is possible to suspend a mainframe Linux
guest using the following command:

echo disk > /sys/power/state

Signed-off-by: Hans-Joachim Picht <hans@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Hans-Joachim Picht authored and Martin Schwidefsky committed Jun 16, 2009
1 parent c369527 commit 155af2f
Show file tree
Hide file tree
Showing 12 changed files with 375 additions and 27 deletions.
9 changes: 9 additions & 0 deletions arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
config ARCH_ENABLE_MEMORY_HOTREMOVE
def_bool y

config ARCH_HIBERNATION_POSSIBLE
def_bool y if 64BIT

source "mm/Kconfig"

comment "I/O subsystem configuration"
Expand Down Expand Up @@ -592,6 +595,12 @@ config SECCOMP

endmenu

menu "Power Management"

source "kernel/power/Kconfig"

endmenu

source "net/Kconfig"

config PCMCIA
Expand Down
4 changes: 3 additions & 1 deletion arch/s390/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ LDFLAGS_vmlinux := -e start
head-y := arch/s390/kernel/head.o arch/s390/kernel/init_task.o

core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/
arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/ \
arch/s390/power/

libs-y += arch/s390/lib/
drivers-y += drivers/s390/
drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
Expand Down
10 changes: 10 additions & 0 deletions arch/s390/include/asm/suspend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef __ASM_S390_SUSPEND_H
#define __ASM_S390_SUSPEND_H

static inline int arch_prepare_suspend(void)
{
return 0;
}

#endif

22 changes: 16 additions & 6 deletions arch/s390/include/asm/system.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
/*
* include/asm-s390/system.h
* Copyright IBM Corp. 1999, 2009
*
* S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
*
* Derived from "include/asm-i386/system.h"
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/

#ifndef __ASM_SYSTEM_H
Expand Down Expand Up @@ -469,6 +465,20 @@ extern psw_t sysc_restore_trace_psw;
extern psw_t io_restore_trace_psw;
#endif

static inline int tprot(unsigned long addr)
{
int rc = -EFAULT;

asm volatile(
" tprot 0(%1),0\n"
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
EX_TABLE(0b,1b)
: "+d" (rc) : "a" (addr) : "cc");
return rc;
}

#endif /* __KERNEL__ */

#endif
6 changes: 3 additions & 3 deletions arch/s390/kernel/early.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* arch/s390/kernel/early.c
*
* Copyright IBM Corp. 2007
* Copyright IBM Corp. 2007, 2009
* Author(s): Hongjie Yang <hongjie@us.ibm.com>,
* Heiko Carstens <heiko.carstens@de.ibm.com>
*/
Expand Down Expand Up @@ -210,7 +210,7 @@ static noinline __init void detect_machine_type(void)
machine_flags |= MACHINE_FLAG_VM;
}

static __init void early_pgm_check_handler(void)
static void early_pgm_check_handler(void)
{
unsigned long addr;
const struct exception_table_entry *fixup;
Expand All @@ -222,7 +222,7 @@ static __init void early_pgm_check_handler(void)
S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE;
}

static noinline __init void setup_lowcore_early(void)
void setup_lowcore_early(void)
{
psw_t psw;

Expand Down
19 changes: 3 additions & 16 deletions arch/s390/kernel/mem_detect.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright IBM Corp. 2008
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
* Copyright IBM Corp. 2008, 2009
*
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
*/

#include <linux/kernel.h>
Expand All @@ -9,20 +10,6 @@
#include <asm/sclp.h>
#include <asm/setup.h>

static inline int tprot(unsigned long addr)
{
int rc = -EFAULT;

asm volatile(
" tprot 0(%1),0\n"
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
EX_TABLE(0b,1b)
: "+d" (rc) : "a" (addr) : "cc");
return rc;
}

#define ADDR2G (1ULL << 31)

static void find_memory_chunks(struct mem_chunk chunk[])
Expand Down
38 changes: 37 additions & 1 deletion arch/s390/kernel/smp.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* arch/s390/kernel/smp.c
*
* Copyright IBM Corp. 1999,2007
* Copyright IBM Corp. 1999, 2009
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
* Martin Schwidefsky (schwidefsky@de.ibm.com)
* Heiko Carstens (heiko.carstens@de.ibm.com)
Expand Down Expand Up @@ -1031,6 +1031,42 @@ static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf,
static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show,
dispatching_store);

/*
* If the resume kernel runs on another cpu than the suspended kernel,
* we have to switch the cpu IDs in the logical map.
*/
void smp_switch_boot_cpu_in_resume(u32 resume_phys_cpu_id,
struct _lowcore *suspend_lowcore)
{
int cpu, suspend_cpu_id, resume_cpu_id;
u32 suspend_phys_cpu_id;

suspend_phys_cpu_id = __cpu_logical_map[suspend_lowcore->cpu_nr];
suspend_cpu_id = suspend_lowcore->cpu_nr;

for_each_present_cpu(cpu) {
if (__cpu_logical_map[cpu] == resume_phys_cpu_id) {
resume_cpu_id = cpu;
goto found;
}
}
panic("Could not find resume cpu in logical map.\n");

found:
printk("Resume cpu ID: %i/%i\n", resume_phys_cpu_id, resume_cpu_id);
printk("Suspend cpu ID: %i/%i\n", suspend_phys_cpu_id, suspend_cpu_id);

__cpu_logical_map[resume_cpu_id] = suspend_phys_cpu_id;
__cpu_logical_map[suspend_cpu_id] = resume_phys_cpu_id;

lowcore_ptr[suspend_cpu_id]->cpu_addr = resume_phys_cpu_id;
}

u32 smp_get_phys_cpu_id(void)
{
return __cpu_logical_map[smp_processor_id()];
}

static int __init topology_init(void)
{
int cpu;
Expand Down
8 changes: 8 additions & 0 deletions arch/s390/power/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# Makefile for s390 PM support
#

obj-$(CONFIG_HIBERNATION) += suspend.o
obj-$(CONFIG_HIBERNATION) += swsusp.o
obj-$(CONFIG_HIBERNATION) += swsusp_64.o
obj-$(CONFIG_HIBERNATION) += swsusp_asm64.o
40 changes: 40 additions & 0 deletions arch/s390/power/suspend.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Suspend support specific for s390.
*
* Copyright IBM Corp. 2009
*
* Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
*/

#include <linux/mm.h>
#include <linux/suspend.h>
#include <linux/reboot.h>
#include <linux/pfn.h>
#include <asm/sections.h>
#include <asm/ipl.h>

/*
* References to section boundaries
*/
extern const void __nosave_begin, __nosave_end;

/*
* check if given pfn is in the 'nosave' or in the read only NSS section
*/
int pfn_is_nosave(unsigned long pfn)
{
unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end))
>> PAGE_SHIFT;
unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1;
unsigned long stext_pfn = PFN_DOWN(__pa(&_stext));

if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn)
return 1;
if (pfn >= stext_pfn && pfn <= eshared_pfn) {
if (ipl_info.type == IPL_TYPE_NSS)
return 1;
} else if ((tprot(pfn * PAGE_SIZE) && pfn > 0))
return 1;
return 0;
}
30 changes: 30 additions & 0 deletions arch/s390/power/swsusp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Support for suspend and resume on s390
*
* Copyright IBM Corp. 2009
*
* Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
*
*/


/*
* save CPU registers before creating a hibernation image and before
* restoring the memory state from it
*/
void save_processor_state(void)
{
/* implentation contained in the
* swsusp_arch_suspend function
*/
}

/*
* restore the contents of CPU registers
*/
void restore_processor_state(void)
{
/* implentation contained in the
* swsusp_arch_resume function
*/
}
17 changes: 17 additions & 0 deletions arch/s390/power/swsusp_64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Support for suspend and resume on s390
*
* Copyright IBM Corp. 2009
*
* Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com>
*
*/

#include <asm/system.h>
#include <linux/interrupt.h>

void do_after_copyback(void)
{
mb();
}

Loading

0 comments on commit 155af2f

Please sign in to comment.