Re: [RFC][PATCH] ARM: Add initial hibernation support for Cortex A8 and A9

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 21 December 2010 05:43, MyungJoo Ham <myungjoo.ham@xxxxxxxxxxx> wrote:
> Hibernation (Suspend-To-Disk) support for ARM Cortex A8 and A9.
>
> This patch is based on the work of Hiroshi DOYU at Nokia, which is
> stated to be based on the original work of Romit and Raghu at TI.
>
> The hibernation support is tested with S5PC210 (ARM Cortex A9 MP2). In
> order to add support for Cortex A9 on the original patch of Hiroshi
> DOYU, which support Cortex A8 only, we have edited the list of registers
> to be saved in the case of A9.
>
> In the original work of Hiroshi DOYU, arch/arm/kernel/vmlinux.lds.S was
> modified; however, we have reverted it because it only created build
> failure in our tested system.
>
> Signed-off-by: MyungJoo Ham <myungjoo.ham@xxxxxxxxxxx>
> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>

Please note that I only had a quick look at the code and I won't have
time to do a proper review before the end of the year. But I have a
few comments which are consider essential.

> --- /dev/null
> +++ b/arch/arm/kernel/hibernate.c
> @@ -0,0 +1,323 @@
> +/*
> + * Hibernation support specific for ARM
> + *
> + * Copyright (C) 2010 Nokia Corporation
> + * Copyright (C) 2010 Texas Instruments, Inc.
> + * Copyright (C) 2006 Rafael J. Wysocki <rjw@xxxxxxx>
> + *
> + * Contact: Hiroshi DOYU <Hiroshi.DOYU@xxxxxxxxx>
> + *
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#include <linux/module.h>
> +#include <linux/mm.h>
> +
> +
> +/* The following architectures are known to be CORTEX_A9 */
> +#if defined(CONFIG_ARCH_S5PV310) || defined(CONFIG_ARCH_U8500)
> +#define CORTEX_A9
> +#else
> +/* Assume CORTEX_A8 as default */
> +#define CORTEX_A8
> +#endif

We should use run-time detection of the CPU rather than #ifdef's. We
have the ability to build multiple processors support into the same
kernel image.

> +struct saved_context {
> +/*
> + * FIXME: Only support for Cortex A8 and Cortex A9 now
> + */
> + Â Â Â /* CR0 */
> + Â Â Â u32 cssr; Â Â Â /* Cache Size Selection */
> + Â Â Â /* CR1 */
> +#ifdef CORTEX_A8
> + Â Â Â u32 cr; Â Â Â Â /* Control */
> + Â Â Â u32 cacr; Â Â Â /* Coprocessor Access Control */
> +#elif defined(CORTEX_A9)
> + Â Â Â u32 cr;
> + Â Â Â u32 actlr;
> + Â Â Â u32 cacr;
> + Â Â Â u32 sder;
> + Â Â Â u32 vcr;
> +#endif

We could follow the ARM ARM and define a save_context structure which
has architected registers and implementation-defined ones. For the
latter you could use a union inside this structure to differentiate
between A8, A9 and other registers for different implementations.

> + Â Â Â /* CR2 */
> + Â Â Â u32 ttb_0r; Â Â /* Translation Table Base 0 */
> + Â Â Â u32 ttb_1r; Â Â /* Translation Table Base 1 */
> + Â Â Â u32 ttbcr; Â Â Â/* Translation Talbe Base Control */
> + Â Â Â /* CR3 */
> + Â Â Â u32 dacr; Â Â Â /* Domain Access Control */
> + Â Â Â /* CR5 */
> + Â Â Â u32 d_fsr; Â Â Â/* Data Fault Status */
> + Â Â Â u32 i_fsr; Â Â Â/* Instruction Fault Status */
> + Â Â Â u32 d_afsr; Â Â /* Data Auxilirary Fault Status */ Â Â Â ;
> + Â Â Â u32 i_afsr; Â Â /* Instruction Auxilirary Fault Status */;
> +       /* CR6 */
> +       u32 d_far;      /* Data Fault Address */
> +       u32 i_far;      /* Instruction Fault Address */

I haven't checked the ARM ARM but some registers may be read-only and
not really needing saving/restoring. Some of them also don't have any
information that is essential when coming back from hibernation (like
the FSR/FAR ones).

> +static inline void __save_processor_state(struct saved_context *ctxt)
> +{
> + Â Â Â /* CR0 */
> + Â Â Â asm volatile ("mrc p15, 2, %0, c0, c0, 0" : "=r"(ctxt->cssr));
> + Â Â Â /* CR1 */
> +#ifdef CORTEX_A8
> + Â Â Â asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(ctxt->cr));
> + Â Â Â asm volatile ("mrc p15, 0, %0, c1, c0, 2" : "=r"(ctxt->cacr));
> +#elif defined(CORTEX_A9)
> + Â Â Â asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r"(ctxt->cr));
> + Â Â Â asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r"(ctxt->actlr));
> + Â Â Â asm volatile ("mrc p15, 0, %0, c1, c0, 2" : "=r"(ctxt->cacr));
> + Â Â Â asm volatile ("mrc p15, 0, %0, c1, c1, 1" : "=r"(ctxt->sder));
> + Â Â Â asm volatile ("mrc p15, 0, %0, c1, c1, 3" : "=r"(ctxt->vcr));
> +#endif

I think this could be split into a generic state saving function and a
per-processor one. You can then do some checks on the CPU ID to and
call the corresponding implementation-specific save function.

> +static inline void __restore_processor_state(struct saved_context *ctxt)
> +{
[...]
> +#ifdef CORTEX_A8
> + Â Â Â asm volatile ("mcr p15, 1, %0, c9, c0, 0" : : "r"(ctxt->l2clr));
> +#endif

This register (and maybe others) is not always writable in non-secure
mode. If running in non-secure mode (which cannot easily be detected
at run-time), we should first check the Nonsecure Access Control
Register.

-- 
Catalin
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm



[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux