On Fri, Jul 08, 2005 at 09:25:01PM +0900, Hiroki Kaminaga wrote: > # Original is at linux-pm ML. Cross posting... > > Here is swsusp for ARM architecture. It is still target specific. > Anyone doing similar work?
What are you suspending to? If this is an external device, how is your bootloader resuming the kernel? does it have a reserved area of memory to use for it's working data? > I managed to hibernate/wakeup on OSK on simple case, but when running > mplayer or when mmap'ed and image got bigger, kernel panic'ed on > wakeup, possibly due to pagedir table miss. > > Here is log: > >>> > Unable to handle kernel paging request at virtual address 80000000 > pgd = c1054000 > [80000000] *pgd=00000000 > <<< > > c1054000 was just after c03ff000. Until up to c03ff000, > pagedir_nosave.orig_address was a constant increase from c0000000 by > 0x00001000. > This is at arch/arm/power/swsusp.S:swsusp_arch_resume() > > Below are my trial & errors. > > > * increase entries of pagedir table > > I increased entry in arch/arm/kernel/head.S:__create_page_tables() from > 4MB to 8MB. This didn't fix the problem. > > * copy swapper_pg_dir and use at resume Hmm, I have no idea if this is correct... I assume it is not saving the page tables over suspend/resume, and that is why you are having trouble restoring the page table? > arch/i386/power/swsusp.S:swsusp_arch_resume() set pagedir table base at > inst: movl %ecx,%cr3. So I attempted similar process, memcpy swapper_pg_dir > to swsusp_pg_dir, and issued: mcr p15, 0, r0, c2, c0, 0, invalidating > cache, drain buffer before & invalidate TLB after this inst. > > This caused a crach at mcr inst. After translating from VA to PA, it > was still the same. > > Next, I overwrote swapper_pg_dir with swsusp_pg_dir. It didn't crash, > but result was still the same. > (works on simple case, fails with mplayer/mmap) > > * applying to 2.6.12 > > I got bigger image (about 2600 pages), and failed hibernate/wakeup > even on simple case. It was about 1350 pages on simple case, and about > 2400 page with mplayer running. The fail status was the same. > > > Any advice? > > I'm confused with the page table usase. On wakeup, kernel create table > (call it A). This table is used when copying swsusp image to mem. > However, there was also table before hibernate (call it B). To some > point, they are similar, so wakeup works. But at some point, wrong > table is used, or table gets corrupted, and result in above kernel > panic. This is my assumption. > > Perhaps I have to turn off MMU while copying pagedir_nosave, and turn > on later? > > Regards, > > HK. > -- > diff -uNrp linux-2.6.11.12-orig/arch/arm/Kconfig > linux-2.6.11.12/arch/arm/Kconfig > --- linux-2.6.11.12-orig/arch/arm/Kconfig 2005-07-05 14:09:26.000000000 > +0900 > +++ linux-2.6.11.12/arch/arm/Kconfig 2005-07-05 14:50:37.000000000 +0900 > @@ -504,25 +504,7 @@ source "fs/Kconfig.binfmt" > > source "drivers/base/Kconfig" > > -config PM > - bool "Power Management support" > - ---help--- > - "Power Management" means that parts of your computer are shut > - off or put into a power conserving "sleep" mode if they are not > - being used. There are two competing standards for doing this: APM > - and ACPI. If you want to use either one, say Y here and then also > - to the requisite support below. > - > - Power Management is most important for battery powered laptop > - computers; if you have a laptop, check out the Linux Laptop home > - page on the WWW at <http://www.linux-on-laptops.com/> or > - Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/> > - and the Battery Powered Linux mini-HOWTO, available from > - <http://www.tldp.org/docs.html#howto>. > - > - Note that, even if you say N here, Linux on the x86 architecture > - will issue the hlt instruction if nothing is to be done, thereby > - sending the processor to sleep and saving power. > +source "kernel/power/Kconfig" > > config PREEMPT > bool "Preemptible Kernel (EXPERIMENTAL)" > diff -uNrp linux-2.6.11.12-orig/arch/arm/Makefile > linux-2.6.11.12/arch/arm/Makefile > --- linux-2.6.11.12-orig/arch/arm/Makefile 2005-06-12 11:45:37.000000000 > +0900 > +++ linux-2.6.11.12/arch/arm/Makefile 2005-07-05 14:50:51.000000000 +0900 > @@ -146,6 +146,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/ > drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ > drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/ > drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/ > +drivers-$(CONFIG_PM) += arch/arm/power/ > > libs-y += arch/arm/lib/ > > diff -uNrp linux-2.6.11.12-orig/arch/arm/kernel/vmlinux.lds.S > linux-2.6.11.12/arch/arm/kernel/vmlinux.lds.S > --- linux-2.6.11.12-orig/arch/arm/kernel/vmlinux.lds.S 2005-06-12 > 11:45:37.000000000 +0900 > +++ linux-2.6.11.12/arch/arm/kernel/vmlinux.lds.S 2005-07-05 > 14:50:51.000000000 +0900 > @@ -75,6 +75,7 @@ SECTIONS > } > > .text : { /* Real text segment */ > + _kern_text_start = .; > _text = .; /* Text and read-only data */ > *(.text) > SCHED_TEXT > @@ -98,6 +99,7 @@ SECTIONS > RODATA > > _etext = .; /* End of text and rodata section */ > + _kern_text_end = .; > > #ifdef CONFIG_XIP_KERNEL > __data_loc = ALIGN(4); /* location in binary */ > @@ -124,12 +126,6 @@ SECTIONS > __init_end = .; > #endif > > - . = ALIGN(4096); > - __nosave_begin = .; > - *(.data.nosave) > - . = ALIGN(4096); > - __nosave_end = .; > - > /* > * then the cacheline aligned data > */ > @@ -145,6 +141,12 @@ SECTIONS > _edata = .; > } > > + . = ALIGN(4096); > + __nosave_begin = .; > + .data.nosave : { *(.data.nosave) } > + . = ALIGN(4096); > + __nosave_end = .; > + > .bss : { > __bss_start = .; /* BSS */ > *(.bss) > diff -uNrp linux-2.6.11.12-orig/arch/arm/mm/init.c > linux-2.6.11.12/arch/arm/mm/init.c > --- linux-2.6.11.12-orig/arch/arm/mm/init.c 2005-06-12 11:45:37.000000000 > +0900 > +++ linux-2.6.11.12/arch/arm/mm/init.c 2005-07-05 15:16:52.000000000 > +0900 > @@ -530,6 +530,20 @@ static inline void free_area(unsigned lo > printk(KERN_INFO "Freeing %s memory: %dK\n", s, size); > } > > +#if defined(CONFIG_PM_DISK) || defined(CONFIG_SOFTWARE_SUSPEND) > +/* > + * Swap suspend & friends need this for resume. > + */ > +/* pgd_t is unsigned long [2], so 2 * 4 (byte/word) */ > +char __nosavedata swsusp_pg_dir[PTRS_PER_PGD * 2 * 4] > +/* Translation Table Base must be on 16KB boundary. */ > +__attribute__ ((aligned (1UL << 14))); > +void swsusp_save_pg_dir(void) > +{ > + memcpy(swsusp_pg_dir, swapper_pg_dir, PTRS_PER_PGD * 2 * 4); > +} > +#endif > + > /* > * mem_init() marks the free areas in the mem_map and tells us how much > * memory is free. This is done after various parts of the system have > diff -uNrp linux-2.6.11.12-orig/arch/arm/power/Makefile > linux-2.6.11.12/arch/arm/power/Makefile > --- linux-2.6.11.12-orig/arch/arm/power/Makefile 1970-01-01 > 09:00:00.000000000 +0900 > +++ linux-2.6.11.12/arch/arm/power/Makefile 2005-07-05 14:50:51.000000000 > +0900 > @@ -0,0 +1 @@ > +obj-$(CONFIG_SOFTWARE_SUSPEND) += cpu.o swsusp.o > diff -uNrp linux-2.6.11.12-orig/arch/arm/power/cpu.c > linux-2.6.11.12/arch/arm/power/cpu.c > --- linux-2.6.11.12-orig/arch/arm/power/cpu.c 1970-01-01 09:00:00.000000000 > +0900 > +++ linux-2.6.11.12/arch/arm/power/cpu.c 2005-07-05 19:59:58.000000000 > +0900 > @@ -0,0 +1,100 @@ > +/* > + * cpu.c - Suspend support specific for ARM. > + * based on arch/i386/power/cpu.c > + * > + * Distribute under GPLv2 > + * > + * Copyright (c) 2002 Pavel Machek <[EMAIL PROTECTED]> > + * Copyright (c) 2001 Patrick Mochel <[EMAIL PROTECTED]> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > +#include <linux/config.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/init.h> > +#include <linux/types.h> > +#include <linux/spinlock.h> > +#include <linux/poll.h> > +#include <linux/delay.h> > +#include <linux/sysrq.h> > +#include <linux/proc_fs.h> > +#include <linux/pm.h> > +#include <linux/device.h> > +#include <linux/suspend.h> > +#include <asm/irq.h> > +#include <asm/uaccess.h> > +#include <asm/tlbflush.h> > + > +static struct saved_context saved_context; > + > +extern void enable_sep_cpu(void *); > + > +void __save_processor_state(struct saved_context *ctxt) > +{ > + /* save preempt state and disable it */ > + preempt_disable(); > + > + /* save coprocessor 15 registers */ > + asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r" (ctxt->CR)); Dangerous, you could be restoring items like FastBus select without checking what state the system is left in on return > + asm volatile ("mrc p15, 0, %0, c3, c0, 0" : "=r" (ctxt->DACR)); > + asm volatile ("mrc p15, 0, %0, c5, c0, 0" : "=r" (ctxt->D_FSR)); > + asm volatile ("mrc p15, 0, %0, c5, c0, 1" : "=r" (ctxt->I_FSR)); > + asm volatile ("mrc p15, 0, %0, c6, c0, 0" : "=r" (ctxt->FAR)); > + asm volatile ("mrc p15, 0, %0, c9, c0, 0" : "=r" (ctxt->D_CLR)); > + asm volatile ("mrc p15, 0, %0, c9, c0, 1" : "=r" (ctxt->I_CLR)); > + asm volatile ("mrc p15, 0, %0, c9, c1, 0" : "=r" (ctxt->D_TCMRR)); > + asm volatile ("mrc p15, 0, %0, c9, c1, 1" : "=r" (ctxt->I_TCMRR)); > + asm volatile ("mrc p15, 0, %0, c10, c0, 0" : "=r" (ctxt->TLBLR)); > + asm volatile ("mrc p15, 0, %0, c13, c0, 0" : "=r" (ctxt->FCSE)); > + asm volatile ("mrc p15, 0, %0, c13, c0, 1" : "=r" (ctxt->CID)); > + asm volatile ("mrc p15, 0, %0, c2, c0, 0" : "=r" (ctxt->TTBR)); I think half of these are items that do not need saving (write-only control registers) > + > +extern void swsusp_save_pg_dir(void); > +void save_processor_state(void) > +{ > + __save_processor_state(&saved_context); > +} > + > +void __restore_processor_state(struct saved_context *ctxt) > +{ > + /* restore coprocessor 15 registers */ > + asm volatile ("mcr p15, 0, %0, c2, c0, 0" : : "r" (ctxt->TTBR)); > + asm volatile ("mcr p15, 0, %0, c13, c0, 1" : : "r" (ctxt->CID)); > + asm volatile ("mcr p15, 0, %0, c13, c0, 0" : : "r" (ctxt->FCSE)); > + asm volatile ("mcr p15, 0, %0, c10, c0, 0" : : "r" (ctxt->TLBLR)); > + asm volatile ("mcr p15, 0, %0, c9, c1, 1" : : "r" (ctxt->I_TCMRR)); > + asm volatile ("mcr p15, 0, %0, c9, c1, 0" : : "r" (ctxt->D_TCMRR)); > + asm volatile ("mcr p15, 0, %0, c9, c0, 1" : : "r" (ctxt->I_CLR)); > + asm volatile ("mcr p15, 0, %0, c9, c0, 0" : : "r" (ctxt->D_CLR)); > + asm volatile ("mcr p15, 0, %0, c6, c0, 0" : : "r" (ctxt->FAR)); > + asm volatile ("mcr p15, 0, %0, c5, c0, 1" : : "r" (ctxt->I_FSR)); > + asm volatile ("mcr p15, 0, %0, c5, c0, 0" : : "r" (ctxt->D_FSR)); > + asm volatile ("mcr p15, 0, %0, c3, c0, 0" : : "r" (ctxt->DACR)); > + asm volatile ("mcr p15, 0, %0, c1, c0, 0" : : "r" (ctxt->CR)); > + > + /* restore preempt state */ > + preempt_enable(); > +} > + > +void restore_processor_state(void) > +{ > + __restore_processor_state(&saved_context); > +} > + > + > +EXPORT_SYMBOL(save_processor_state); > +EXPORT_SYMBOL(restore_processor_state); > diff -uNrp linux-2.6.11.12-orig/arch/arm/power/swsusp.S > linux-2.6.11.12/arch/arm/power/swsusp.S > --- linux-2.6.11.12-orig/arch/arm/power/swsusp.S 1970-01-01 > 09:00:00.000000000 +0900 > +++ linux-2.6.11.12/arch/arm/power/swsusp.S 2005-07-05 19:52:48.000000000 > +0900 > @@ -0,0 +1,321 @@ > +/* > + * swsusp.S - This file is based on arch/i386/power/swsusp.S; > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +/* > + * This may not use any stack, nor any variable that is not "NoSave": > + * > + * Its rewriting one kernel image with another. What is stack in "old" > + * image could very well be data page in "new" image, and overwriting > + * your own stack under you is bad idea. > + */ > + > +/* > + * FIXME: Work needs to be done for core with fp. > + */ > + > +#include <linux/linkage.h> > +#include <asm/segment.h> > +#include <asm/page.h> > + > + .text > + > +#define LOCAL_WORD(x) \ > + .data ; \ > + .p2align 2 ; \ > + .type x, #object ; \ > + .size x, 4 ; \ > +x: ; \ > + .long 1 > + > +#define WORD_ADDR(x) \ > + .align 2 ; \ > +.L##x: ; \ > + .word x > + > +#define FUNC(x) \ > + .text ; \ > + .p2align 2 ; \ > + .globl x ; \ > + .type x, #function ; \ > +x: > + > +#define FUNC_END(x) \ > + .size x, .-x > + > +#define CHANGE_MODE(x) \ > + mov r1, r0 ; \ > + bic r1, r1, #0x1f ; \ > + orr r1, r1, #0x##x ; \ > + msr cpsr_c, r1 > + > +/* nonvolatile int registers */ > +#ifdef DEBUG > + .globl saved_context_r0 // for debug > +#endif > + LOCAL_WORD(saved_context_r0) > + LOCAL_WORD(saved_context_r1) > + LOCAL_WORD(saved_context_r2) > + LOCAL_WORD(saved_context_r3) > + LOCAL_WORD(saved_context_r4) > + LOCAL_WORD(saved_context_r5) > + LOCAL_WORD(saved_context_r6) > + LOCAL_WORD(saved_context_r7) > + LOCAL_WORD(saved_context_r8) > + LOCAL_WORD(saved_context_r9) > + LOCAL_WORD(saved_context_r10) > + LOCAL_WORD(saved_context_r11) > + LOCAL_WORD(saved_context_r12) > + LOCAL_WORD(saved_context_r13) > + LOCAL_WORD(saved_context_r14) > + LOCAL_WORD(saved_cpsr) > + > + LOCAL_WORD(saved_context_r8_fiq) > + LOCAL_WORD(saved_context_r9_fiq) > + LOCAL_WORD(saved_context_r10_fiq) > + LOCAL_WORD(saved_context_r11_fiq) > + LOCAL_WORD(saved_context_r12_fiq) > + LOCAL_WORD(saved_context_r13_fiq) > + LOCAL_WORD(saved_context_r14_fiq) > + LOCAL_WORD(saved_spsr_fiq) > + > + LOCAL_WORD(saved_context_r13_irq) > + LOCAL_WORD(saved_context_r14_irq) > + LOCAL_WORD(saved_spsr_irq) > + > + LOCAL_WORD(saved_context_r13_svc) > + LOCAL_WORD(saved_context_r14_svc) > + LOCAL_WORD(saved_spsr_svc) > + > + LOCAL_WORD(saved_context_r13_abt) > + LOCAL_WORD(saved_context_r14_abt) > + LOCAL_WORD(saved_spsr_abt) > + > + LOCAL_WORD(saved_context_r13_und) > + LOCAL_WORD(saved_context_r14_und) > + LOCAL_WORD(saved_spsr_und) > + > +/* > + * non volatile fpu registers > + * s16 - s31 > + */ > + /* XXX:TBD */ > + > +FUNC(swsusp_arch_suspend) > + > + /* save current program status register */ > + ldr r3, .Lsaved_cpsr > + mrs r1, cpsr > + str r1, [r3] > + > + /* hold current mode */ > + mrs r0, cpsr > + > + CHANGE_MODE(1f) /* change to system(user) mode */ > + /* save nonvolatile int register */ > + ldr r3, .Lsaved_context_r0 > + stmia r3, {r0-r14} > + > + CHANGE_MODE(11) /* change to fiq mode */ > + /* save nonvolatile int register */ > + ldr r3, .Lsaved_context_r8_fiq > + stmia r3, {r8-r14} > + /* save spsr_fiq register */ > + ldr r3, .Lsaved_spsr_fiq > + mrs r1, spsr > + str r1, [r3] > + > + CHANGE_MODE(12) /* change to irq mode */ > + /* save nonvolatile int register */ > + ldr r3, .Lsaved_context_r13_irq > + stmia r3, {r13-r14} > + /* save spsr_irq register */ > + ldr r3, .Lsaved_spsr_irq > + mrs r1, spsr > + str r1, [r3] > + > + CHANGE_MODE(13) /* change to svc mode */ > + /* save nonvolatile int register */ > + ldr r3, .Lsaved_context_r13_svc > + stmia r3, {r13-r14} > + /* save spsr_svc register */ > + ldr r3, .Lsaved_spsr_svc > + mrs r1, spsr > + str r1, [r3] > + > + CHANGE_MODE(17) /* change to abt mode */ > + /* save nonvolatile int register */ > + ldr r3, .Lsaved_context_r13_abt > + stmia r3, {r13-r14} > + /* save spsr_abt register */ > + ldr r3, .Lsaved_spsr_abt > + mrs r1, spsr > + str r1, [r3] > + > + CHANGE_MODE(1b) /* change to und mode */ > + /* save nonvolatile int register */ > + ldr r3, .Lsaved_context_r13_und > + stmia r3, {r13-r14} > + /* save spsr_und register */ > + ldr r3, .Lsaved_spsr_und > + mrs r1, spsr > + str r1, [r3] > + > + /* go back to original mode */ > + msr cpsr_c, r0 > + > + /* > + * save nonvolatile fp registers > + * and fp status/system registers, if needed > + */ > + /* XXX:TBD */ > + > + /* call swsusp_save */ > + bl swsusp_save > + > + /* restore return address */ > + ldr r3, .Lsaved_context_r14_svc > + ldr lr, [r3] > + mov pc, lr > + > + WORD_ADDR(saved_context_r0) > + WORD_ADDR(saved_cpsr) > + WORD_ADDR(saved_context_r8_fiq) > + WORD_ADDR(saved_spsr_fiq) > + WORD_ADDR(saved_context_r13_irq) > + WORD_ADDR(saved_spsr_irq) > + WORD_ADDR(saved_context_r13_svc) > + WORD_ADDR(saved_context_r14_svc) > + WORD_ADDR(saved_spsr_svc) > + WORD_ADDR(saved_context_r13_abt) > + WORD_ADDR(saved_spsr_abt) > + WORD_ADDR(saved_context_r13_und) > + WORD_ADDR(saved_spsr_und) > + > +FUNC_END(swsusp_arch_suspend) > + > +FUNC(swsusp_arch_resume) > + /* set page table if needed */ > + > + /* > + * retore "nr_copy_pages" pages which are saved and specified > + * at "pagedir_nosave" > + */ > + > + ldr r0, .Lpagedir_nosave > + ldr r6, [r0] > + ldr r0, .Lnr_copy_pages > + ldr r7, [r0] > + > +.Lcopy_loop: > + ldr r4, [r6] /* src */ > + ldr r5, [r6, #4] /* dst */ > + mov r9, #1024 > + > + /* this loop could be optimized by using stm and ldm. */ > +.Lcopy_one_page: > + ldr r8, [r4] > + str r8, [r5] > + > + add r4, r4, #4 > + add r5, r5, #4 > + sub r9, r9, #1 > + cmp r9, #0 > + bne .Lcopy_one_page > + > + add r6, r6, #16 /* 16 means sizeof(suspend_pagedir_t) */ > + sub r7, r7, #1 > + cmp r7, #0 > + bne .Lcopy_loop > + > + /* hold current mode */ > + mrs r0, cpsr > + > + CHANGE_MODE(1f) /* change to system(user) mode */ > + /* restore nonvolatile int register */ > + ldr r3, .Lsaved_context_r0 > + ldmia r3, {r0-r14} > + /* restore current program status register */ > + ldr r3, .Lsaved_cpsr > + ldr r1, [r3] > + msr cpsr_cxsf, r1 > + > + CHANGE_MODE(11) /* change to fiq mode */ > + /* restore nonvolatile int register */ > + ldr r3, .Lsaved_context_r8_fiq > + ldmia r3, {r8-r14} > + /* restore spsr_fiq register */ > + ldr r3, .Lsaved_spsr_fiq > + ldr r1, [r3] > + msr spsr_cxsf, r1 > + > + CHANGE_MODE(12) /* change to irq mode */ > + /* restore nonvolatile int register */ > + ldr r3, .Lsaved_context_r13_irq > + ldmia r3, {r13-r14} > + /* restore spsr_irq register */ > + ldr r3, .Lsaved_spsr_irq > + ldr r1, [r3] > + msr spsr_cxsf, r1 > + > + CHANGE_MODE(13) /* change to svc mode */ > + /* restore nonvolatile int register */ > + ldr r3, .Lsaved_context_r13_svc > + ldmia r3, {r13-r14} > + /* restore spsr_svc register */ > + ldr r3, .Lsaved_spsr_svc > + ldr r1, [r3] > + msr spsr_cxsf, r1 > + > + CHANGE_MODE(17) /* change to abt mode */ > + /* restore nonvolatile int register */ > + ldr r3, .Lsaved_context_r13_abt > + ldmia r3, {r13-r14} > + /* restore spsr_abt register */ > + ldr r3, .Lsaved_spsr_abt > + ldr r1, [r3] > + msr spsr_cxsf, r1 > + > + CHANGE_MODE(1b) /* change to und mode */ > + /* restore nonvolatile int register */ > + ldr r3, .Lsaved_context_r13_und > + ldmia r3, {r13-r14} > + /* restore spsr_und register */ > + ldr r3, .Lsaved_spsr_und > + ldr r1, [r3] > + msr spsr_cxsf, r1 > + > + /* go back to original mode */ > + msr cpsr_c, r0 > + > + /* > + * restore nonvolatile fp registers > + * and fp status/system registers, if needed > + */ > + /* XXX:TBD */ > + > + /* call swsusp_restore */ > + bl swsusp_restore > + > + /* restore return address */ > + ldr r3, .Lsaved_context_r14_svc > + ldr lr, [r3] > + mov pc, lr > + > + WORD_ADDR(nr_copy_pages) > + WORD_ADDR(pagedir_nosave) > + > +FUNC_END(swsusp_arch_resume) > diff -uNrp linux-2.6.11.12-orig/include/asm-arm/suspend.h > linux-2.6.11.12/include/asm-arm/suspend.h > --- linux-2.6.11.12-orig/include/asm-arm/suspend.h 2005-06-12 > 11:45:37.000000000 +0900 > +++ linux-2.6.11.12/include/asm-arm/suspend.h 2005-07-05 14:52:20.000000000 > +0900 > @@ -1,4 +1,45 @@ > #ifndef _ASMARM_SUSPEND_H > #define _ASMARM_SUSPEND_H > > +/* > + * Based on code include/asm-i386/suspend.h > + * Copyright 2001-2002 Pavel Machek <[EMAIL PROTECTED]> > + * Copyright 2001 Patrick Mochel <[EMAIL PROTECTED]> > + */ > + > + > +static inline int > +arch_prepare_suspend(void) > +{ > + return 0; > +} > + > +/* image of the saved processor state */ > +struct saved_context { > + /* > + * Structure saved_context would be used to hold processor state > + * except caller and callee registers, just before suspending. > + */ > + > + /* coprocessor 15 registers */ > +// __u32 ID_code; /* read only reg */ > +// __u32 cache_type; /* read only reg */ > +// __u32 TCM_stat; /* read only reg */ > + __u32 CR; > + __u32 TTBR; > + __u32 DACR; > + __u32 D_FSR; > + __u32 I_FSR; > + __u32 FAR; > +// __u32 COR; /*write only reg */ > +// __u32 TLBOR; /*write only reg */ > + __u32 D_CLR; > + __u32 I_CLR; > + __u32 D_TCMRR; > + __u32 I_TCMRR; > + __u32 TLBLR; > + __u32 FCSE; > + __u32 CID; > +}; > + > #endif > diff -uNrp linux-2.6.11.12-orig/include/asm-arm/tlbflush.h > linux-2.6.11.12/include/asm-arm/tlbflush.h > --- linux-2.6.11.12-orig/include/asm-arm/tlbflush.h 2005-06-12 > 11:45:37.000000000 +0900 > +++ linux-2.6.11.12/include/asm-arm/tlbflush.h 2005-07-05 > 14:50:51.000000000 +0900 > @@ -253,6 +253,9 @@ static inline void flush_tlb_all(void) > asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); > } > > +#define __flush_tlb_all flush_tlb_all > +#define __flush_tlb_global flush_tlb_all > + > static inline void flush_tlb_mm(struct mm_struct *mm) > { > const int zero = 0; > diff -uNrp linux-2.6.11.12-orig/include/linux/suspend.h > linux-2.6.11.12/include/linux/suspend.h > --- linux-2.6.11.12-orig/include/linux/suspend.h 2005-06-12 > 11:45:37.000000000 +0900 > +++ linux-2.6.11.12/include/linux/suspend.h 2005-07-05 15:04:10.000000000 > +0900 > @@ -1,7 +1,7 @@ > #ifndef _LINUX_SWSUSP_H > #define _LINUX_SWSUSP_H > > -#if defined(CONFIG_X86) || defined(CONFIG_FRV) > +#if defined(CONFIG_PM_DISK) || defined(CONFIG_SOFTWARE_SUSPEND) > #include <asm/suspend.h> > #endif > #include <linux/swap.h> > diff -uNrp linux-2.6.11.12-orig/arch/arm/mach-omap/common.c > linux-2.6.11.12/arch/arm/mach-omap/common.c > --- linux-2.6.11.12-orig/arch/arm/mach-omap/common.c 2005-07-05 > 14:09:26.000000000 +0900 > +++ linux-2.6.11.12/arch/arm/mach-omap/common.c 2005-07-05 > 14:50:37.000000000 +0900 > @@ -442,8 +442,16 @@ void __init omap_serial_init(int ports[O > } > } > > +static void omap_power_off(void) > +{ > + printk("System Halted\n"); > + local_irq_disable(); > + while (1) ; > +} > + > static int __init omap_init(void) > { > + pm_power_off = omap_power_off; > return platform_device_register(&serial_device); > } > arch_initcall(omap_init); > diff -uNrp linux-2.6.11.12-orig/drivers/mtd/mtdblock.c > linux-2.6.11.12/drivers/mtd/mtdblock.c > --- linux-2.6.11.12-orig/drivers/mtd/mtdblock.c 2005-06-12 > 11:45:37.000000000 +0900 > +++ linux-2.6.11.12/drivers/mtd/mtdblock.c 2005-07-05 14:49:01.000000000 > +0900 > @@ -321,6 +321,24 @@ static int mtdblock_release(struct mtd_b > return 0; > } > > +#if defined(CONFIG_SWSUSP_MTDBLOCK_FLUSH) > +/* XXXX: quick hack, need to be rewrite later */ > +int swsusp_mtdblock_flush(void) > +{ > +#if defined CONFIG_MACH_OMAP_OSK > + struct mtdblk_dev *mtdblk = mtdblks[3]; > +#endif > + > + down(&mtdblk->cache_sem); > + write_cached_data(mtdblk); > + up(&mtdblk->cache_sem); > + > + if (mtdblk->mtd->sync) > + mtdblk->mtd->sync(mtdblk->mtd); > + return 0; > +} > +#endif > + > static int mtdblock_flush(struct mtd_blktrans_dev *dev) > { > struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; > + * Based on code > diff -uNrp linux-2.6.11.12-orig/kernel/power/Kconfig > linux-2.6.11.12/kernel/power/Kconfig > --- linux-2.6.11.12-orig/kernel/power/Kconfig 2005-06-12 11:45:37.000000000 > +0900 > +++ linux-2.6.11.12/kernel/power/Kconfig 2005-07-05 14:49:01.000000000 > +0900 > @@ -72,3 +72,10 @@ config PM_STD_PARTITION > suspended image to. It will simply pick the first available swap > device. > > +config SWSUSP_MTDBLOCK_FLUSH > + bool "Flush MTD block" > + depends on SOFTWARE_SUSPEND > + default "y" > + ---help--- > + When suspend to disk (software suspend), flush the MTD block. > + > diff -uNrp linux-2.6.11.12-orig/kernel/power/disk.c > linux-2.6.11.12/kernel/power/disk.c > --- linux-2.6.11.12-orig/kernel/power/disk.c 2005-06-12 11:45:37.000000000 > +0900 > +++ linux-2.6.11.12/kernel/power/disk.c 2005-07-05 14:49:01.000000000 > +0900 > @@ -48,6 +48,11 @@ static void power_down(suspend_disk_meth > unsigned long flags; > int error = 0; > > +#if defined(CONFIG_SWSUSP_MTDBLOCK_FLUSH) > +/* XXXX: quick hack, need to be rewrite later */ > + printk(KERN_CRIT "flush MTD\n"); > + swsusp_mtdblock_flush(); > +#endif > local_irq_save(flags); > switch(mode) { > case PM_DISK_PLATFORM: -- Ben ([EMAIL PROTECTED], http://www.fluff.org/) 'a smiley only costs 4 bytes' - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/