public inbox for linux-sh@vger.kernel.org
 help / color / mirror / Atom feed
From: Francesco VIRLINZI <francesco.virlinzi@st.com>
To: linux-sh@vger.kernel.org
Subject: Re: [PATCH] sh: hibernation support
Date: Fri, 06 Mar 2009 07:06:42 +0000	[thread overview]
Message-ID: <49B0CB82.7030708@st.com> (raw)
In-Reply-To: <20090306064156.27281.35572.sendpatchset@rx1.opensource.se>

Hi Magnus
I was looking your patch and I have few question.
Is it also for sh4 with PMB? If so how are you managing the PMB?
Moreover what about interrupt controller? This means after a resume from 
hibernation
 you could have a resumed device (and driver) but the interrupt 
controller has the right irq-line not initialized.

Regards
 Francesco

Magnus Damm ha scritto:
> From: Magnus Damm <damm@igel.co.jp>
>
> Add Suspend-to-disk / swsusp / CONFIG_HIBERNATION support
> to the SuperH architecture.
>
> To suspend, use "swapon /dev/sda2; echo disk > /sys/power/state"
> To resume, pass "resume=/dev/sda2" on the kernel command line.
>
> The patch "pm: rework includes, remove arch ifdefs V2" is
> needed to allow the generic swsusp code to build properly.
>
> Hibernation is not enabled with this patch though, a patch
> setting ARCH_HIBERNATION_POSSIBLE will be submitted later.
>
> Signed-off-by: Magnus Damm <damm@igel.co.jp>
> ---
>
>  Tested on a sh7785lcr board.
>
>  arch/sh/include/asm/suspend.h  |   14 +++
>  arch/sh/kernel/Makefile_32     |    1 
>  arch/sh/kernel/asm-offsets.c   |    8 ++
>  arch/sh/kernel/cpu/sh3/entry.S |  144 +++++++++++++++++++++++++++++++++++++++-
>  arch/sh/kernel/pm.c            |   39 ++++++++++
>  5 files changed, 203 insertions(+), 3 deletions(-)
>
> --- /dev/null
> +++ work/arch/sh/include/asm/suspend.h	2009-03-02 15:23:59.000000000 +0900
> @@ -0,0 +1,14 @@
> +#ifndef _ASM_SH_SUSPEND_H
> +#define _ASM_SH_SUSPEND_H
> +
> +static inline int arch_prepare_suspend(void) { return 0; }
> +extern const void __nosave_begin, __nosave_end;
> +
> +#include <asm/ptrace.h>
> +
> +struct swsusp_arch_regs {
> +	struct pt_regs user_regs;
> +	unsigned long bank1_regs[8];
> +};
> +
> +#endif /* _ASM_SH_SUSPEND_H */
> --- 0001/arch/sh/kernel/Makefile_32
> +++ work/arch/sh/kernel/Makefile_32	2009-03-02 15:23:59.000000000 +0900
> @@ -30,5 +30,6 @@ obj-$(CONFIG_KPROBES)		+= kprobes.o
>  obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
>  obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
>  obj-$(CONFIG_DUMP_CODE)		+= disassemble.o
> +obj-$(CONFIG_PM)		+= pm.o
>  
>  EXTRA_CFLAGS += -Werror
> --- 0001/arch/sh/kernel/asm-offsets.c
> +++ work/arch/sh/kernel/asm-offsets.c	2009-03-02 15:23:59.000000000 +0900
> @@ -12,8 +12,10 @@
>  #include <linux/types.h>
>  #include <linux/mm.h>
>  #include <linux/kbuild.h>
> +#include <linux/suspend.h>
>  
>  #include <asm/thread_info.h>
> +#include <asm/suspend.h>
>  
>  int main(void)
>  {
> @@ -25,5 +27,11 @@ int main(void)
>  	DEFINE(TI_PRE_COUNT,	offsetof(struct thread_info, preempt_count));
>  	DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
>  
> +#ifdef CONFIG_HIBERNATION
> +	DEFINE(pbe_address, offsetof(struct pbe, address));
> +	DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
> +	DEFINE(pbe_next, offsetof(struct pbe, next));
> +	DEFINE(SWSUSP_ARCH_REGS_SIZE, sizeof(struct swsusp_arch_regs));
> +#endif
>  	return 0;
>  }
> --- 0001/arch/sh/kernel/cpu/sh3/entry.S
> +++ work/arch/sh/kernel/cpu/sh3/entry.S	2009-03-02 15:26:57.000000000 +0900
> @@ -323,6 +323,76 @@ skip_restore:
>  #endif
>  7:	.long	0x30000000
>  
> +#ifdef CONFIG_HIBERNATION
> +! swsusp_arch_resume()
> +! - copy restore_pblist pages
> +! - restore registers from swsusp_arch_regs_cpu0
> +
> +ENTRY(swsusp_arch_resume)
> +	mov.l	4f, r15
> +	mov.l	1f, r4
> +	mov.l	@r4, r4
> +
> +copy_loop:
> +	mov	r4, r0
> +	cmp/eq	#0, r0
> +	bt	do_restore_regs
> +
> +	mov.l	@(pbe_address, r4), r2
> +	mov.l	@(pbe_orig_address, r4), r5
> +
> +	mov.l	2f, r3
> +	shlr2	r3
> +	shlr2	r3
> +copy_page:
> +	dt	r3
> +	mov.l	@r2+,r1   /*  16n+0 */
> +	mov.l	r1,@r5
> +	add	#4,r5
> +	mov.l	@r2+,r1	  /*  16n+4 */
> +	mov.l	r1,@r5
> +	add	#4,r5
> +	mov.l	@r2+,r1   /*  16n+8 */
> +	mov.l	r1,@r5
> +	add	#4,r5
> +	mov.l	@r2+,r1   /*  16n+12 */
> +	mov.l	r1,@r5
> +	bf/s	copy_page
> +	 add	#4,r5
> +
> +	bra	copy_loop
> +	 mov.l	@(pbe_next, r4), r4
> +
> +do_restore_regs:
> +	! BL=0: R7->R0 is bank0
> +	mov.l	3f, r8
> +	bsr	restore_regs
> +	 nop
> +
> +	! BL=1: R7->R0 is bank1
> +	lds	k2, pr
> +	ldc	k3, ssr
> +
> +	mov.l	@r15+, r0
> +	mov.l	@r15+, r1
> +	mov.l	@r15+, r2
> +	mov.l	@r15+, r3
> +	mov.l	@r15+, r4
> +	mov.l	@r15+, r5
> +	mov.l	@r15+, r6
> +	mov.l	@r15+, r7
> +
> +	rte
> +	 nop
> +	! BL=0: R7->R0 is bank0
> +
> +	.align	2
> +1:	.long	restore_pblist
> +2:	.long	PAGE_SIZE
> +3:	.long	0x20000000 ! RB=1
> +4:	.long	swsusp_arch_regs_cpu0
> +#endif /* CONFIG_HIBERNATION */
> +
>  ! common exception handler
>  #include "../../entry-common.S"
>  	
> @@ -362,8 +432,10 @@ general_exception:
>  	 nop
>  
>  	! Save registers / Switch to bank 0
> +	mov.l	k4, k2		! keep vector in k2
> +	mov.l	1f, k4		! SR bits to clear in k4
>  	bsr	save_regs	! needs original pr value in k3
> -	 mov	k4, k2		! keep vector in k2
> +	 nop
>  
>  	bra	handle_exception_special
>  	 nop
> @@ -471,6 +543,7 @@ handle_exception:
>  
>  	! Save registers / Switch to bank 0
>  	mov.l	5f, k2		! vector register address
> +	mov.l	1f, k4		! SR bits to clear in k4
>  	bsr	save_regs	! needs original pr value in k3
>  	 mov.l	@k2, k2		! read out vector and keep in k2
>  
> @@ -495,7 +568,7 @@ handle_exception_special:
>  ! k0 contains original stack pointer*
>  ! k1 trashed
>  ! k3 passes original pr*
> -! k4 trashed
> +! k4 passes SR bitmask
>  ! BL=1 on entry, on exit BL=0.
>  
>  save_regs:
> @@ -518,8 +591,16 @@ save_regs:
>  	mov.l	r8, @-r15
>  
>  	mov.l	0f, k3		! SR bits to set in k3
> -	mov.l	1f, k4		! SR bits to clear in k4
>  
> +	! fall-through
> +
> +! save_low_regs()
> +! - modify SR for bank switch
> +! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
> +! k3 passes bits to set in SR
> +! k4 passes bits to clear in SR
> +
> +save_low_regs:
>  	stc	sr, r8
>  	or	k3, r8
>  	and	k4, r8
> @@ -565,6 +646,7 @@ ENTRY(handle_interrupt)
>  	 PREF(k0)
>  
>  	! Save registers / Switch to bank 0
> +	mov.l	1f, k4		! SR bits to clear in k4
>  	bsr	save_regs	! needs original pr value in k3
>  	 mov	#-1, k2		! default vector kept in k2
>  
> @@ -591,3 +673,59 @@ exception_data:
>  5:	.long	EXPEVT
>  6:	.long	exception_handling_table
>  7:	.long	ret_from_exception
> +
> +#ifdef CONFIG_HIBERNATION
> +! swsusp_arch_suspend()
> +! - prepare pc for resume, return from function without swsusp_save on resume
> +! - save registers in swsusp_arch_regs_cpu0
> +! - call swsusp_save write suspend image
> +
> +ENTRY(swsusp_arch_suspend)
> +	sts	pr, r0		! save pr in r0
> +	mov	r15, r2		! save sp in r2
> +	mov	r8, r5		! save r8 in r5
> +	stc	sr, r1
> +	ldc	r1, ssr		! save sr in ssr
> +	mov.l	1f, r1
> +	ldc	r1, spc		! setup pc value for resuming
> +	mov.l	5f, r15		! use swsusp_arch_regs_cpu0 as stack
> +	mov.l	6f, r3
> +	add	r3, r15		! save from top of structure
> +
> +	! BL=0: R7->R0 is bank0
> +	mov.l	2f, r3		! get new SR value for bank1
> +	mov	#0, r4
> +	bsr	save_low_regs	! switch to bank1 and save bank1 r7->r0
> +	 not	r4, r4
> +
> +	! BL=1: R7->R0 is bank1
> +	stc	r2_bank, k0	! fetch old sp from r2_bank0
> +	mov.l	3f, k4		! SR bits to clear in k4
> +	bsr	save_regs	! switch to bank0 and save all regs
> +	 stc	r0_bank, k3	! fetch old pr from r0_bank0
> +
> +	! BL=0: R7->R0 is bank0
> +	mov	r2, r15		! restore old sp
> +	mov	r5, r8		! restore old r8
> +	stc	ssr, r1
> +	ldc	r1, sr		! restore old sr
> +	lds	r0, pr		! restore old pr
> +	mov.l	4f, r0
> +	jmp	@r0
> +	 nop
> +
> +do_swsusp_save:
> +	mov	r2, r15		! restore old sp
> +	mov	r5, r8		! restore old r8
> +	lds	r0, pr		! restore old pr
> +	rts
> +	 mov	#0, r0
> +
> +	.align	2
> +1:	.long	do_swsusp_save
> +2:	.long	0x20000000 ! RB=1
> +3:	.long	0xdfffffff ! RB=0
> +4:	.long	swsusp_save
> +5:	.long	swsusp_arch_regs_cpu0
> +6:	.long	SWSUSP_ARCH_REGS_SIZE
> +#endif /* CONFIG_HIBERNATION */
> --- /dev/null
> +++ work/arch/sh/kernel/pm.c	2009-03-02 15:23:59.000000000 +0900
> @@ -0,0 +1,39 @@
> +/*
> + * pm.c - SuperH power management code
> + *
> + * Copyright (C) 2009 Magnus Damm
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License.  See the file "COPYING" in the main directory of this archive
> + * for more details.
> + */
> +
> +#include <linux/mm.h>
> +#include <linux/sched.h>
> +#include <linux/suspend.h>
> +#include <asm/suspend.h>
> +#include <asm/tlbflush.h>
> +#include <asm/page.h>
> +#include <asm/fpu.h>
> +
> +#ifdef CONFIG_HIBERNATION
> +struct swsusp_arch_regs swsusp_arch_regs_cpu0;
> +
> +int pfn_is_nosave(unsigned long pfn)
> +{
> +	unsigned long begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
> +	unsigned long end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
> +
> +	return (pfn >= begin_pfn) && (pfn < end_pfn);
> +}
> +
> +void save_processor_state(void)
> +{
> +	init_fpu(current);
> +}
> +
> +void restore_processor_state(void)
> +{
> +	local_flush_tlb_all();
> +}
> +#endif
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>   


  parent reply	other threads:[~2009-03-06  7:06 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-06  6:41 [PATCH] sh: hibernation support Magnus Damm
2009-03-06  6:57 ` Paul Mundt
2009-03-06  7:06 ` Francesco VIRLINZI [this message]
2009-03-06  9:53 ` Magnus Damm
2009-03-06 10:05 ` Francesco VIRLINZI
2009-03-06 10:17 ` Francesco VIRLINZI
2009-03-06 17:29 ` Jean-Christophe PLAGNIOL-VILLARD
2009-03-07  6:12 ` Paul Mundt
2009-03-07  6:20 ` Paul Mundt
2009-03-09  9:12 ` Francesco VIRLINZI
2009-03-09  9:16 ` Magnus Damm
2009-03-09  9:27 ` Francesco VIRLINZI
2009-03-09 10:03 ` Francesco VIRLINZI
2009-03-09 10:57 ` Magnus Damm
2009-03-09 17:35 ` Paul Mundt
2009-03-10 13:19 ` Francesco VIRLINZI
2009-03-11  4:26 ` Magnus Damm
2009-03-11  6:50 ` Francesco VIRLINZI
2009-03-11  7:29 ` Magnus Damm
2009-03-11 13:20 ` Francesco VIRLINZI
2009-03-12  5:47 ` Magnus Damm
2009-03-12  8:54 ` Francesco VIRLINZI

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=49B0CB82.7030708@st.com \
    --to=francesco.virlinzi@st.com \
    --cc=linux-sh@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox