From: Russ Dill <Russ.Dill@ti.com>
To: Sebastian Capella <sebastian.capella@linaro.org>,
linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org,
linaro-kernel@lists.linaro.org,
linux-arm-kernel@lists.infradead.org
Cc: "Len Brown" <len.brown@intel.com>,
"Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>,
"Russell King" <linux@arm.linux.org.uk>,
"Jonathan Austin" <jonathan.austin@arm.com>,
"Nicolas Pitre" <nico@linaro.org>,
"Will Deacon" <will.deacon@arm.com>,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
"Rafael J. Wysocki" <rjw@rjwysocki.net>,
"Santosh Shilimkar" <santosh.shilimkar@ti.com>,
"Pavel Machek" <pavel@ucw.cz>,
"Catalin Marinas" <catalin.marinas@arm.com>,
"Stephen Boyd" <sboyd@codeaurora.org>
Subject: Re: [PATCH v4 2/2] ARM hibernation / suspend-to-disk
Date: Wed, 26 Feb 2014 11:18:13 -0800 [thread overview]
Message-ID: <530E3DF5.8000309@ti.com> (raw)
In-Reply-To: <1393441857-15472-3-git-send-email-sebastian.capella@linaro.org>
On 02/26/2014 11:10 AM, Sebastian Capella wrote:
> From: Russ Dill <Russ.Dill@ti.com>
>
> Enable hibernation for ARM architectures and provide ARM
> architecture specific calls used during hibernation.
>
> The swsusp hibernation framework depends on the
> platform first having functional suspend/resume.
>
> Then, in order to enable hibernation on a given platform, a
> platform_hibernation_ops structure may need to be registered with
> the system in order to save/restore any SoC-specific / cpu specific
> state needing (re)init over a suspend-to-disk/resume-from-disk cycle.
>
> For example:
>
> - "secure" SoCs that have different sets of control registers
> and/or different CR reg access patterns.
>
> - SoCs with L2 caches as the activation sequence there is
> SoC-dependent; a full off-on cycle for L2 is not done
> by the hibernation support code.
>
> - SoCs requiring steps on wakeup _before_ the "generic" parts
> done by cpu_suspend / cpu_resume can work correctly.
>
> - SoCs having persistent state which is maintained during suspend
> and resume, but will be lost during the power off cycle after
> suspend-to-disk.
>
> This is a rebase/rework of Frank Hofmann's v5 hibernation patchset.
>
> Cc: Russ Dill <Russ.Dill@ti.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> Signed-off-by: Sebastian Capella <sebastian.capella@linaro.org>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Len Brown <len.brown@intel.com>
> Cc: Pavel Machek <pavel@ucw.cz>
> Cc: Nicolas Pitre <nico@linaro.org>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Jonathan Austin <jonathan.austin@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Russ Dill <russ.dill@ti.com>
> ---
> arch/arm/include/asm/memory.h | 1 +
> arch/arm/kernel/Makefile | 1 +
> arch/arm/kernel/hibernate.c | 113 +++++++++++++++++++++++++++++++++++++++++
> arch/arm/mm/Kconfig | 5 ++
> include/linux/suspend.h | 2 +
> 5 files changed, 122 insertions(+)
> create mode 100644 arch/arm/kernel/hibernate.c
>
> diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
> index 8756e4b..1079ea8 100644
> --- a/arch/arm/include/asm/memory.h
> +++ b/arch/arm/include/asm/memory.h
> @@ -291,6 +291,7 @@ static inline void *phys_to_virt(phys_addr_t x)
> */
> #define __pa(x) __virt_to_phys((unsigned long)(x))
> #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
> +#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
> #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
>
> extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x);
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index a30fc9b..8afa848 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -39,6 +39,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
> obj-$(CONFIG_ISA_DMA) += dma-isa.o
> obj-$(CONFIG_PCI) += bios32.o isa.o
> obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
> +obj-$(CONFIG_HIBERNATION) += hibernate.o
> obj-$(CONFIG_SMP) += smp.o
> ifdef CONFIG_MMU
> obj-$(CONFIG_SMP) += smp_tlb.o
> diff --git a/arch/arm/kernel/hibernate.c b/arch/arm/kernel/hibernate.c
> new file mode 100644
> index 0000000..70e17d2
> --- /dev/null
> +++ b/arch/arm/kernel/hibernate.c
> @@ -0,0 +1,113 @@
> +/*
> + * Hibernation support specific for ARM
> + *
> + * Derived from work on ARM hibernation support by:
> + *
> + * Ubuntu project, hibernation support for mach-dove
> + * Copyright (C) 2010 Nokia Corporation (Hiroshi Doyu)
> + * Copyright (C) 2010 Texas Instruments, Inc. (Teerth Reddy et al.)
> + * https://lkml.org/lkml/2010/6/18/4
> + * https://lists.linux-foundation.org/pipermail/linux-pm/2010-June/027422.html
> + * https://patchwork.kernel.org/patch/96442/
> + *
> + * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/mm.h>
> +#include <linux/suspend.h>
> +#include <asm/tlbflush.h>
> +#include <asm/cacheflush.h>
> +#include <asm/system_misc.h>
> +#include <asm/idmap.h>
> +#include <asm/suspend.h>
> +
> +extern const void __nosave_begin, __nosave_end;
> +
> +int pfn_is_nosave(unsigned long pfn)
> +{
> + unsigned long nosave_begin_pfn =
> + __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
> + unsigned long nosave_end_pfn =
> + PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
> +
> + return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
> +}
> +
> +void notrace save_processor_state(void)
> +{
> + WARN_ON(num_online_cpus() != 1);
> + local_fiq_disable();
> +}
> +
> +void notrace restore_processor_state(void)
> +{
> + local_fiq_enable();
> +}
> +
> +/*
> + * Snapshot kernel memory and reset the system.
> + *
> + * swsusp_save() is executed in the suspend finisher so that the CPU
> + * context pointer and memory are part of the saved image, which is
> + * required by the resume kernel image to restart execution from
> + * swsusp_arch_suspend().
> + *
> + * soft_restart is not technically needed, but is used to get success
> + * returned from cpu_suspend.
> + *
> + * When soft reboot completes, the hibernation snapshot is written out.
> + */
> +static int notrace __swsusp_arch_save_image(unsigned long unused)
> +{
> + int ret;
> +
> + ret = swsusp_save();
> + if (ret == 0)
> + soft_restart(virt_to_phys(cpu_resume));
> + return ret;
> +}
> +
> +/*
> + * Save the current CPU state before suspend / poweroff.
> + */
> +int notrace swsusp_arch_suspend(void)
> +{
> + return cpu_suspend(0, __swsusp_arch_save_image);
> +}
> +
> +/*
> + * The framework loads the hibernation image into a linked list anchored
> + * at restore_pblist, for swsusp_arch_resume() to copy back to the proper
> + * destinations.
> + *
> + * To make this work if resume is triggered from initramfs, the
> + * pagetables need to be switched to allow writes to kernel mem.
> + */
> +static void notrace __swsusp_arch_restore_image(void *unused)
> +{
> + struct pbe *pbe;
> +
> + cpu_switch_mm(idmap_pgd, &init_mm);
> + for (pbe = restore_pblist; pbe; pbe = pbe->next)
> + copy_page(pbe->orig_address, pbe->address);
> +
> + soft_restart(virt_to_phys(cpu_resume));
> +}
> +
> +static u8 __swsusp_resume_stk[PAGE_SIZE/2] __nosavedata;
> +
> +/*
> + * Resume from the hibernation image.
> + * Due to the kernel heap / data restore, stack contents change underneath
> + * and that would make function calls impossible; switch to a temporary
> + * stack within the nosave region to avoid that problem.
> + */
> +int swsusp_arch_resume(void)
> +{
> + extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
> + call_with_stack(__swsusp_arch_restore_image, 0,
> + __swsusp_resume_stk + sizeof(__swsusp_resume_stk));
> + return 0;
> +}
> diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
> index 1f8fed9..83707702 100644
> --- a/arch/arm/mm/Kconfig
> +++ b/arch/arm/mm/Kconfig
> @@ -611,6 +611,11 @@ config CPU_USE_DOMAINS
> config IO_36
> bool
>
> +config ARCH_HIBERNATION_POSSIBLE
> + bool
> + depends on MMU
> + default y if CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V6K || CPU_V7
> +
> comment "Processor Features"
>
> config ARM_LPAE
> diff --git a/include/linux/suspend.h b/include/linux/suspend.h
> index f73cabf..38bbf95 100644
> --- a/include/linux/suspend.h
> +++ b/include/linux/suspend.h
> @@ -320,6 +320,8 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
> extern void hibernation_set_ops(const struct platform_hibernation_ops *ops);
> extern int hibernate(void);
> extern bool system_entering_hibernation(void);
> +asmlinkage int swsusp_save(void);
> +extern struct pbe *restore_pblist;
> #else /* CONFIG_HIBERNATION */
> static inline void register_nosave_region(unsigned long b, unsigned long e) {}
> static inline void register_nosave_region_late(unsigned long b, unsigned long e) {}
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: Russ.Dill@ti.com (Russ Dill)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4 2/2] ARM hibernation / suspend-to-disk
Date: Wed, 26 Feb 2014 11:18:13 -0800 [thread overview]
Message-ID: <530E3DF5.8000309@ti.com> (raw)
In-Reply-To: <1393441857-15472-3-git-send-email-sebastian.capella@linaro.org>
On 02/26/2014 11:10 AM, Sebastian Capella wrote:
> From: Russ Dill <Russ.Dill@ti.com>
>
> Enable hibernation for ARM architectures and provide ARM
> architecture specific calls used during hibernation.
>
> The swsusp hibernation framework depends on the
> platform first having functional suspend/resume.
>
> Then, in order to enable hibernation on a given platform, a
> platform_hibernation_ops structure may need to be registered with
> the system in order to save/restore any SoC-specific / cpu specific
> state needing (re)init over a suspend-to-disk/resume-from-disk cycle.
>
> For example:
>
> - "secure" SoCs that have different sets of control registers
> and/or different CR reg access patterns.
>
> - SoCs with L2 caches as the activation sequence there is
> SoC-dependent; a full off-on cycle for L2 is not done
> by the hibernation support code.
>
> - SoCs requiring steps on wakeup _before_ the "generic" parts
> done by cpu_suspend / cpu_resume can work correctly.
>
> - SoCs having persistent state which is maintained during suspend
> and resume, but will be lost during the power off cycle after
> suspend-to-disk.
>
> This is a rebase/rework of Frank Hofmann's v5 hibernation patchset.
>
> Cc: Russ Dill <Russ.Dill@ti.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> Signed-off-by: Sebastian Capella <sebastian.capella@linaro.org>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Len Brown <len.brown@intel.com>
> Cc: Pavel Machek <pavel@ucw.cz>
> Cc: Nicolas Pitre <nico@linaro.org>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Jonathan Austin <jonathan.austin@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: "Uwe Kleine-K?nig" <u.kleine-koenig@pengutronix.de>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Russ Dill <russ.dill@ti.com>
> ---
> arch/arm/include/asm/memory.h | 1 +
> arch/arm/kernel/Makefile | 1 +
> arch/arm/kernel/hibernate.c | 113 +++++++++++++++++++++++++++++++++++++++++
> arch/arm/mm/Kconfig | 5 ++
> include/linux/suspend.h | 2 +
> 5 files changed, 122 insertions(+)
> create mode 100644 arch/arm/kernel/hibernate.c
>
> diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
> index 8756e4b..1079ea8 100644
> --- a/arch/arm/include/asm/memory.h
> +++ b/arch/arm/include/asm/memory.h
> @@ -291,6 +291,7 @@ static inline void *phys_to_virt(phys_addr_t x)
> */
> #define __pa(x) __virt_to_phys((unsigned long)(x))
> #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
> +#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
> #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
>
> extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x);
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index a30fc9b..8afa848 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -39,6 +39,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
> obj-$(CONFIG_ISA_DMA) += dma-isa.o
> obj-$(CONFIG_PCI) += bios32.o isa.o
> obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
> +obj-$(CONFIG_HIBERNATION) += hibernate.o
> obj-$(CONFIG_SMP) += smp.o
> ifdef CONFIG_MMU
> obj-$(CONFIG_SMP) += smp_tlb.o
> diff --git a/arch/arm/kernel/hibernate.c b/arch/arm/kernel/hibernate.c
> new file mode 100644
> index 0000000..70e17d2
> --- /dev/null
> +++ b/arch/arm/kernel/hibernate.c
> @@ -0,0 +1,113 @@
> +/*
> + * Hibernation support specific for ARM
> + *
> + * Derived from work on ARM hibernation support by:
> + *
> + * Ubuntu project, hibernation support for mach-dove
> + * Copyright (C) 2010 Nokia Corporation (Hiroshi Doyu)
> + * Copyright (C) 2010 Texas Instruments, Inc. (Teerth Reddy et al.)
> + * https://lkml.org/lkml/2010/6/18/4
> + * https://lists.linux-foundation.org/pipermail/linux-pm/2010-June/027422.html
> + * https://patchwork.kernel.org/patch/96442/
> + *
> + * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/mm.h>
> +#include <linux/suspend.h>
> +#include <asm/tlbflush.h>
> +#include <asm/cacheflush.h>
> +#include <asm/system_misc.h>
> +#include <asm/idmap.h>
> +#include <asm/suspend.h>
> +
> +extern const void __nosave_begin, __nosave_end;
> +
> +int pfn_is_nosave(unsigned long pfn)
> +{
> + unsigned long nosave_begin_pfn =
> + __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
> + unsigned long nosave_end_pfn =
> + PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
> +
> + return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
> +}
> +
> +void notrace save_processor_state(void)
> +{
> + WARN_ON(num_online_cpus() != 1);
> + local_fiq_disable();
> +}
> +
> +void notrace restore_processor_state(void)
> +{
> + local_fiq_enable();
> +}
> +
> +/*
> + * Snapshot kernel memory and reset the system.
> + *
> + * swsusp_save() is executed in the suspend finisher so that the CPU
> + * context pointer and memory are part of the saved image, which is
> + * required by the resume kernel image to restart execution from
> + * swsusp_arch_suspend().
> + *
> + * soft_restart is not technically needed, but is used to get success
> + * returned from cpu_suspend.
> + *
> + * When soft reboot completes, the hibernation snapshot is written out.
> + */
> +static int notrace __swsusp_arch_save_image(unsigned long unused)
> +{
> + int ret;
> +
> + ret = swsusp_save();
> + if (ret == 0)
> + soft_restart(virt_to_phys(cpu_resume));
> + return ret;
> +}
> +
> +/*
> + * Save the current CPU state before suspend / poweroff.
> + */
> +int notrace swsusp_arch_suspend(void)
> +{
> + return cpu_suspend(0, __swsusp_arch_save_image);
> +}
> +
> +/*
> + * The framework loads the hibernation image into a linked list anchored
> + * at restore_pblist, for swsusp_arch_resume() to copy back to the proper
> + * destinations.
> + *
> + * To make this work if resume is triggered from initramfs, the
> + * pagetables need to be switched to allow writes to kernel mem.
> + */
> +static void notrace __swsusp_arch_restore_image(void *unused)
> +{
> + struct pbe *pbe;
> +
> + cpu_switch_mm(idmap_pgd, &init_mm);
> + for (pbe = restore_pblist; pbe; pbe = pbe->next)
> + copy_page(pbe->orig_address, pbe->address);
> +
> + soft_restart(virt_to_phys(cpu_resume));
> +}
> +
> +static u8 __swsusp_resume_stk[PAGE_SIZE/2] __nosavedata;
> +
> +/*
> + * Resume from the hibernation image.
> + * Due to the kernel heap / data restore, stack contents change underneath
> + * and that would make function calls impossible; switch to a temporary
> + * stack within the nosave region to avoid that problem.
> + */
> +int swsusp_arch_resume(void)
> +{
> + extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
> + call_with_stack(__swsusp_arch_restore_image, 0,
> + __swsusp_resume_stk + sizeof(__swsusp_resume_stk));
> + return 0;
> +}
> diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
> index 1f8fed9..83707702 100644
> --- a/arch/arm/mm/Kconfig
> +++ b/arch/arm/mm/Kconfig
> @@ -611,6 +611,11 @@ config CPU_USE_DOMAINS
> config IO_36
> bool
>
> +config ARCH_HIBERNATION_POSSIBLE
> + bool
> + depends on MMU
> + default y if CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V6K || CPU_V7
> +
> comment "Processor Features"
>
> config ARM_LPAE
> diff --git a/include/linux/suspend.h b/include/linux/suspend.h
> index f73cabf..38bbf95 100644
> --- a/include/linux/suspend.h
> +++ b/include/linux/suspend.h
> @@ -320,6 +320,8 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
> extern void hibernation_set_ops(const struct platform_hibernation_ops *ops);
> extern int hibernate(void);
> extern bool system_entering_hibernation(void);
> +asmlinkage int swsusp_save(void);
> +extern struct pbe *restore_pblist;
> #else /* CONFIG_HIBERNATION */
> static inline void register_nosave_region(unsigned long b, unsigned long e) {}
> static inline void register_nosave_region_late(unsigned long b, unsigned long e) {}
>
WARNING: multiple messages have this Message-ID (diff)
From: Russ Dill <Russ.Dill@ti.com>
To: Sebastian Capella <sebastian.capella@linaro.org>,
<linux-kernel@vger.kernel.org>, <linux-pm@vger.kernel.org>,
<linaro-kernel@lists.linaro.org>,
<linux-arm-kernel@lists.infradead.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>,
"Russell King" <linux@arm.linux.org.uk>,
"Len Brown" <len.brown@intel.com>, "Pavel Machek" <pavel@ucw.cz>,
"Nicolas Pitre" <nico@linaro.org>,
"Santosh Shilimkar" <santosh.shilimkar@ti.com>,
"Will Deacon" <will.deacon@arm.com>,
"Jonathan Austin" <jonathan.austin@arm.com>,
"Catalin Marinas" <catalin.marinas@arm.com>,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
"Stephen Boyd" <sboyd@codeaurora.org>,
"Lorenzo Pieralisi" <lorenzo.pieralisi@arm.com>
Subject: Re: [PATCH v4 2/2] ARM hibernation / suspend-to-disk
Date: Wed, 26 Feb 2014 11:18:13 -0800 [thread overview]
Message-ID: <530E3DF5.8000309@ti.com> (raw)
In-Reply-To: <1393441857-15472-3-git-send-email-sebastian.capella@linaro.org>
On 02/26/2014 11:10 AM, Sebastian Capella wrote:
> From: Russ Dill <Russ.Dill@ti.com>
>
> Enable hibernation for ARM architectures and provide ARM
> architecture specific calls used during hibernation.
>
> The swsusp hibernation framework depends on the
> platform first having functional suspend/resume.
>
> Then, in order to enable hibernation on a given platform, a
> platform_hibernation_ops structure may need to be registered with
> the system in order to save/restore any SoC-specific / cpu specific
> state needing (re)init over a suspend-to-disk/resume-from-disk cycle.
>
> For example:
>
> - "secure" SoCs that have different sets of control registers
> and/or different CR reg access patterns.
>
> - SoCs with L2 caches as the activation sequence there is
> SoC-dependent; a full off-on cycle for L2 is not done
> by the hibernation support code.
>
> - SoCs requiring steps on wakeup _before_ the "generic" parts
> done by cpu_suspend / cpu_resume can work correctly.
>
> - SoCs having persistent state which is maintained during suspend
> and resume, but will be lost during the power off cycle after
> suspend-to-disk.
>
> This is a rebase/rework of Frank Hofmann's v5 hibernation patchset.
>
> Cc: Russ Dill <Russ.Dill@ti.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> Signed-off-by: Sebastian Capella <sebastian.capella@linaro.org>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Len Brown <len.brown@intel.com>
> Cc: Pavel Machek <pavel@ucw.cz>
> Cc: Nicolas Pitre <nico@linaro.org>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Jonathan Austin <jonathan.austin@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Russ Dill <russ.dill@ti.com>
> ---
> arch/arm/include/asm/memory.h | 1 +
> arch/arm/kernel/Makefile | 1 +
> arch/arm/kernel/hibernate.c | 113 +++++++++++++++++++++++++++++++++++++++++
> arch/arm/mm/Kconfig | 5 ++
> include/linux/suspend.h | 2 +
> 5 files changed, 122 insertions(+)
> create mode 100644 arch/arm/kernel/hibernate.c
>
> diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
> index 8756e4b..1079ea8 100644
> --- a/arch/arm/include/asm/memory.h
> +++ b/arch/arm/include/asm/memory.h
> @@ -291,6 +291,7 @@ static inline void *phys_to_virt(phys_addr_t x)
> */
> #define __pa(x) __virt_to_phys((unsigned long)(x))
> #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
> +#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
> #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
>
> extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x);
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index a30fc9b..8afa848 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -39,6 +39,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
> obj-$(CONFIG_ISA_DMA) += dma-isa.o
> obj-$(CONFIG_PCI) += bios32.o isa.o
> obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
> +obj-$(CONFIG_HIBERNATION) += hibernate.o
> obj-$(CONFIG_SMP) += smp.o
> ifdef CONFIG_MMU
> obj-$(CONFIG_SMP) += smp_tlb.o
> diff --git a/arch/arm/kernel/hibernate.c b/arch/arm/kernel/hibernate.c
> new file mode 100644
> index 0000000..70e17d2
> --- /dev/null
> +++ b/arch/arm/kernel/hibernate.c
> @@ -0,0 +1,113 @@
> +/*
> + * Hibernation support specific for ARM
> + *
> + * Derived from work on ARM hibernation support by:
> + *
> + * Ubuntu project, hibernation support for mach-dove
> + * Copyright (C) 2010 Nokia Corporation (Hiroshi Doyu)
> + * Copyright (C) 2010 Texas Instruments, Inc. (Teerth Reddy et al.)
> + * https://lkml.org/lkml/2010/6/18/4
> + * https://lists.linux-foundation.org/pipermail/linux-pm/2010-June/027422.html
> + * https://patchwork.kernel.org/patch/96442/
> + *
> + * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/mm.h>
> +#include <linux/suspend.h>
> +#include <asm/tlbflush.h>
> +#include <asm/cacheflush.h>
> +#include <asm/system_misc.h>
> +#include <asm/idmap.h>
> +#include <asm/suspend.h>
> +
> +extern const void __nosave_begin, __nosave_end;
> +
> +int pfn_is_nosave(unsigned long pfn)
> +{
> + unsigned long nosave_begin_pfn =
> + __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
> + unsigned long nosave_end_pfn =
> + PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
> +
> + return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
> +}
> +
> +void notrace save_processor_state(void)
> +{
> + WARN_ON(num_online_cpus() != 1);
> + local_fiq_disable();
> +}
> +
> +void notrace restore_processor_state(void)
> +{
> + local_fiq_enable();
> +}
> +
> +/*
> + * Snapshot kernel memory and reset the system.
> + *
> + * swsusp_save() is executed in the suspend finisher so that the CPU
> + * context pointer and memory are part of the saved image, which is
> + * required by the resume kernel image to restart execution from
> + * swsusp_arch_suspend().
> + *
> + * soft_restart is not technically needed, but is used to get success
> + * returned from cpu_suspend.
> + *
> + * When soft reboot completes, the hibernation snapshot is written out.
> + */
> +static int notrace __swsusp_arch_save_image(unsigned long unused)
> +{
> + int ret;
> +
> + ret = swsusp_save();
> + if (ret == 0)
> + soft_restart(virt_to_phys(cpu_resume));
> + return ret;
> +}
> +
> +/*
> + * Save the current CPU state before suspend / poweroff.
> + */
> +int notrace swsusp_arch_suspend(void)
> +{
> + return cpu_suspend(0, __swsusp_arch_save_image);
> +}
> +
> +/*
> + * The framework loads the hibernation image into a linked list anchored
> + * at restore_pblist, for swsusp_arch_resume() to copy back to the proper
> + * destinations.
> + *
> + * To make this work if resume is triggered from initramfs, the
> + * pagetables need to be switched to allow writes to kernel mem.
> + */
> +static void notrace __swsusp_arch_restore_image(void *unused)
> +{
> + struct pbe *pbe;
> +
> + cpu_switch_mm(idmap_pgd, &init_mm);
> + for (pbe = restore_pblist; pbe; pbe = pbe->next)
> + copy_page(pbe->orig_address, pbe->address);
> +
> + soft_restart(virt_to_phys(cpu_resume));
> +}
> +
> +static u8 __swsusp_resume_stk[PAGE_SIZE/2] __nosavedata;
> +
> +/*
> + * Resume from the hibernation image.
> + * Due to the kernel heap / data restore, stack contents change underneath
> + * and that would make function calls impossible; switch to a temporary
> + * stack within the nosave region to avoid that problem.
> + */
> +int swsusp_arch_resume(void)
> +{
> + extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
> + call_with_stack(__swsusp_arch_restore_image, 0,
> + __swsusp_resume_stk + sizeof(__swsusp_resume_stk));
> + return 0;
> +}
> diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
> index 1f8fed9..83707702 100644
> --- a/arch/arm/mm/Kconfig
> +++ b/arch/arm/mm/Kconfig
> @@ -611,6 +611,11 @@ config CPU_USE_DOMAINS
> config IO_36
> bool
>
> +config ARCH_HIBERNATION_POSSIBLE
> + bool
> + depends on MMU
> + default y if CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V6K || CPU_V7
> +
> comment "Processor Features"
>
> config ARM_LPAE
> diff --git a/include/linux/suspend.h b/include/linux/suspend.h
> index f73cabf..38bbf95 100644
> --- a/include/linux/suspend.h
> +++ b/include/linux/suspend.h
> @@ -320,6 +320,8 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
> extern void hibernation_set_ops(const struct platform_hibernation_ops *ops);
> extern int hibernate(void);
> extern bool system_entering_hibernation(void);
> +asmlinkage int swsusp_save(void);
> +extern struct pbe *restore_pblist;
> #else /* CONFIG_HIBERNATION */
> static inline void register_nosave_region(unsigned long b, unsigned long e) {}
> static inline void register_nosave_region_late(unsigned long b, unsigned long e) {}
>
next prev parent reply other threads:[~2014-02-26 19:18 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-26 19:10 [PATCH v4 0/2] hibernation support on ARM Sebastian Capella
2014-02-26 19:10 ` Sebastian Capella
2014-02-26 19:10 ` [PATCH v4 1/2] ARM: avoid tracers in soft_restart Sebastian Capella
2014-02-26 19:10 ` Sebastian Capella
2014-02-26 23:37 ` Russell King - ARM Linux
2014-02-26 23:37 ` Russell King - ARM Linux
2014-02-27 0:18 ` Sebastian Capella
2014-02-27 0:18 ` Sebastian Capella
2014-02-26 19:10 ` [PATCH v4 2/2] ARM hibernation / suspend-to-disk Sebastian Capella
2014-02-26 19:10 ` Sebastian Capella
2014-02-26 19:18 ` Russ Dill [this message]
2014-02-26 19:18 ` Russ Dill
2014-02-26 19:18 ` Russ Dill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=530E3DF5.8000309@ti.com \
--to=russ.dill@ti.com \
--cc=catalin.marinas@arm.com \
--cc=jonathan.austin@arm.com \
--cc=len.brown@intel.com \
--cc=linaro-kernel@lists.linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=lorenzo.pieralisi@arm.com \
--cc=nico@linaro.org \
--cc=pavel@ucw.cz \
--cc=rjw@rjwysocki.net \
--cc=santosh.shilimkar@ti.com \
--cc=sboyd@codeaurora.org \
--cc=sebastian.capella@linaro.org \
--cc=u.kleine-koenig@pengutronix.de \
--cc=will.deacon@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.