All of lore.kernel.org
 help / color / mirror / Atom feed
* Help port swsusp to ppc.
@ 2004-01-19  2:52 Hugang
  2004-01-19  3:04 ` Nigel Cunningham
  2004-01-19  3:35 ` Benjamin Herrenschmidt
  0 siblings, 2 replies; 80+ messages in thread
From: Hugang @ 2004-01-19  2:52 UTC (permalink / raw)
  To: ncunningham, linux-kernel, debian-powerpc

[-- Attachment #1: Type: text/plain, Size: 1349 bytes --]

Hello guys:

I'm try to porting Software Suspend to PowerPC. But I'm not family with
PowerPC assemble languae. So need someone to help me write the save
process state function in assemble language.

1: Download i386 suspend patch for 2.6.1 from swsusp.sf.net
 you need two patch 
 software-suspend-core-2.0-rc4-whole.bz2
 software-suspend-linux-2.6.1-rev1-whole.bz2
2: first you need apply linux-2.6.1 to 2.6.1 clean kernel
   then apply core-2.0-rc4 to current patched kernel
3: then apply ppc-swsusp.patch to patched kernel
4: do make menuconfig
 CONFIG_SOFTWARE_SUSPEND2=y
 CONFIG_SOFTWARE_SUSPEND_DEBUG=y
 CONFIG_SOFTWARE_SUSPEND_GZIP_COMPRESSION=y
 CONFIG_SOFTWARE_SUSPEND_KEEP_IMAGE=y
 CONFIG_SOFTWARE_SUSPEND_LZF_COMPRESSION=y
 CONFIG_SOFTWARE_SUSPEND_SWAPWRITER=y
5: test with swsusp enable kernel.
 in yaboot prompt:
 /vmlinux.swsusp root=/dev/hda13 resume2=swap:/dev/hda10 init=/bin/sh
 
 /dev/hda13 is the root device name
 /dev/hda10 is swap device name
 
6: run suspend script to do software suspend, now the machine will power
 off.

7: power on machin, in yaboot prompt:
  /vmlinux.swsusp root=/dev/hda13 resume2=swap:/dev/hda10 init=/bin/sh

But for now the save and restore processor state is not finish, the
resume will oops.

-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

[-- Attachment #2: ppc_swsusp.diff --]
[-- Type: text/plain, Size: 22643 bytes --]

Index: include/asm-ppc/suspend.h
===================================================================
--- include/asm-ppc/suspend.h	(revision 0)
+++ include/asm-ppc/suspend.h	(revision 0)
@@ -0,0 +1,6 @@
+#ifndef _PPC_SUSPEND_H
+#define _PPC_SUSPEND_H
+
+/* Nothing */
+
+#endif
Index: arch/ppc/Kconfig
===================================================================
--- arch/ppc/Kconfig	(revision 192)
+++ arch/ppc/Kconfig	(working copy)
@@ -193,6 +193,8 @@
 
 	  If in doubt, say Y here.
 
+source kernel/power/Kconfig
+
 source arch/ppc/platforms/4xx/Kconfig
 
 config PPC64BRIDGE
Index: arch/ppc/kernel/swsusp2-asm.S
===================================================================
--- arch/ppc/kernel/swsusp2-asm.S	(revision 0)
+++ arch/ppc/kernel/swsusp2-asm.S	(revision 0)
@@ -0,0 +1,523 @@
+	.file	"swsusp2.c"
+gcc2_compiled.:
+	.section	".rodata"
+	.align 2
+.LC0:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/cpumask.h"
+	.align 2
+.LC1:
+	.string	"next_online_cpu"
+	.align 2
+.LC2:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/module.h"
+	.align 2
+.LC3:
+	.string	"__module_get"
+	.align 2
+.LC4:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/dcache.h"
+	.align 2
+.LC5:
+	.string	"dget"
+	.align 2
+.LC6:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/mm.h"
+	.align 2
+.LC7:
+	.string	"put_page"
+	.align 2
+.LC8:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/highmem.h"
+	.align 2
+.LC9:
+	.string	"memclear_highpage_flush"
+	.align 2
+.LC10:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/blkdev.h"
+	.align 2
+.LC11:
+	.string	"blkdev_dequeue_request"
+	.align 2
+.LC12:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/skbuff.h"
+	.align 2
+.LC13:
+	.string	"__skb_put"
+	.align 2
+.LC14:
+	.string	"skb_put"
+	.align 2
+.LC15:
+	.string	"__skb_pull"
+	.align 2
+.LC16:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/netdevice.h"
+	.align 2
+.LC17:
+	.string	"netif_rx_complete"
+	.align 2
+.LC18:
+	.string	"__netif_rx_complete"
+	.align 2
+.LC19:
+	.string	"BUG: dst underflow %d: %p\n"
+	.align 2
+.LC20:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/net/sock.h"
+	.align 2
+.LC21:
+	.string	"sk_del_node_init"
+	.align 2
+.LC22:
+	.string	"sk_set_owner"
+	.align 2
+.LC23:
+	.string	"kiocb_to_siocb"
+	.align 2
+.LC24:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/kernel_stat.h"
+	.align 2
+.LC25:
+	.string	"kstat_irqs"
+	.align 2
+.LC26:
+	.string	"/scm/svn/dell/pub/linux-kernel/2.6/tags/linux-2.6.1-swsusp2/include/linux/raid/md_k.h"
+	.align 2
+.LC27:
+	.string	"pers_to_level"
+	.section	".data.nosave","aw"
+	.align 2
+	.type	 loop,@object
+	.size	 loop,4
+loop:
+	.long 0
+	.align 2
+	.type	 state1,@object
+	.size	 state1,4
+state1:
+	.long 0
+	.align 2
+	.type	 state2,@object
+	.size	 state2,4
+state2:
+	.long 0
+	.align 2
+	.type	 state3,@object
+	.size	 state3,4
+state3:
+	.long 0
+	.align 2
+	.type	 c_loops_per_jiffy_ref,@object
+	.size	 c_loops_per_jiffy_ref,4
+c_loops_per_jiffy_ref:
+	.long 0
+	.align 2
+	.type	 cpu_khz_ref,@object
+	.size	 cpu_khz_ref,4
+cpu_khz_ref:
+	.long 0
+	.section	".text"
+	.align 2
+	.globl do_swsusp_lowlevel
+	.type	 do_swsusp_lowlevel,@function
+do_swsusp_lowlevel:
+	stwu 1,-48(1)
+	mflr 0
+	stmw 23,12(1)
+	stw 0,52(1)
+	cmpwi 0,3,0
+	bc 4,2,.L3612
+	bl do_swsusp2_suspend_1
+	//bl ppc_save_reg
+	/* bl save_processor_state
+	bl save_stack */
+	bl do_swsusp2_suspend_2
+	b .L3611
+.L3612:
+	lis	2,swapper_pg_dir@ha	   
+	addi 2,2,swapper_pg_dir@l
+	bl do_swsusp2_resume_1
+	lis 9,swsusp_action@ha
+	lwz 0,swsusp_action@l(9)
+	lis 11,swsusp_debug_state@ha
+	lis 9,state1@ha
+	stw 0,state1@l(9)
+	lwz 8,swsusp_debug_state@l(11)
+	lis 10,console_printk@ha
+	lis 9,state2@ha
+	lis 11,pagedir_resume@ha
+	stw 8,state2@l(9)
+	la 11,pagedir_resume@l(11)
+	lwz 0,console_printk@l(10)
+	lwz 5,12(11)
+	lis 9,state3@ha
+	stw 0,state3@l(9)
+	lwz 10,0(5)
+	lwz 4,56(11)
+	lis 9,origoffset@ha
+	stw 10,origoffset@l(9)
+	lwz 0,0(4)
+	lis 11,copyoffset@ha
+	stw 0,copyoffset@l(11)
+	lwz 10,origoffset@l(9)
+	lwz 8,copyoffset@l(11)
+	slwi 9,10,2
+	slwi 11,8,2
+	add 9,9,10
+	add 11,11,8
+	lis 0,0xcccc
+	ori 0,0,52429
+	slwi 9,9,3
+	slwi 11,11,3
+	mullw 11,11,0
+	mullw 9,9,0
+	slwi 11,11,9
+	slwi 9,9,9
+	cmpwi 0,5,0
+	addis 9,9,0xc000
+	addis 11,11,0xc000
+	lis 7,origrange@ha
+	lis 6,copyrange@ha
+	lis 10,origpage@ha
+	lis 8,copypage@ha
+	lis 24,origrange@ha
+	lis 25,copyrange@ha
+	lis 12,origoffset@ha
+	lis 3,copyoffset@ha
+	stw 9,origpage@l(10)
+	stw 11,copypage@l(8)
+	stw 5,origrange@l(7)
+	stw 4,copyrange@l(6)
+	bc 12,2,.L3631
+	lis 4,0xcccc
+	lis 28,loop@ha
+	lis 26,origoffset@ha
+	lis 29,origrange@ha
+	lis 30,origpage@ha
+	ori 4,4,52429
+	lis 27,copyoffset@ha
+	lis 31,copypage@ha
+.L3617:
+	li 0,0
+	stw 0,loop@l(28)
+	lwz 9,loop@l(28)
+	cmplwi 0,9,1023
+	bc 12,1,.L3622
+	lis 7,loop@ha
+	lis 5,origpage@ha
+	lis 6,copypage@ha
+.L3620:
+	lwz 8,loop@l(7)
+	lwz 9,loop@l(7)
+	lwz 11,copypage@l(6)
+	slwi 9,9,2
+	lwzx 0,9,11
+	lwz 10,origpage@l(5)
+	slwi 8,8,2
+	stwx 0,8,10
+	lwz 9,loop@l(7)
+	addi 9,9,1
+	stw 9,loop@l(7)
+	lwz 0,loop@l(7)
+	cmplwi 0,0,1023
+	bc 4,1,.L3620
+.L3622:
+	lwz 11,origrange@l(29)
+	lwz 9,origoffset@l(26)
+	lwz 0,4(11)
+	cmplw 0,9,0
+	bc 4,0,.L3623
+	lwz 9,origoffset@l(12)
+	lwz 11,origpage@l(30)
+	addi 9,9,1
+	addi 11,11,4096
+	stw 9,origoffset@l(12)
+	stw 11,origpage@l(30)
+	b .L3624
+.L3623:
+	lwz 9,8(11)
+	cmpwi 0,9,0
+	stw 9,origrange@l(24)
+	bc 12,2,.L3624
+	lwz 9,0(9)
+	stw 9,origoffset@l(12)
+	lwz 0,origoffset@l(12)
+	slwi 9,0,2
+	add 9,9,0
+	slwi 9,9,3
+	mullw 9,9,4
+	slwi 9,9,9
+	addis 9,9,0xc000
+	stw 9,origpage@l(30)
+.L3624:
+	lis 9,copyrange@ha
+	lwz 9,copyrange@l(9)
+	lwz 11,copyoffset@l(27)
+	lwz 0,4(9)
+	cmplw 0,11,0
+	bc 4,0,.L3627
+	lwz 9,copyoffset@l(3)
+	lwz 11,copypage@l(31)
+	addi 9,9,1
+	addi 11,11,4096
+	stw 9,copyoffset@l(3)
+	stw 11,copypage@l(31)
+	b .L3615
+.L3627:
+	lwz 9,8(9)
+	cmpwi 0,9,0
+	stw 9,copyrange@l(25)
+	bc 12,2,.L3615
+	lwz 9,0(9)
+	stw 9,copyoffset@l(3)
+	lwz 0,copyoffset@l(3)
+	slwi 9,0,2
+	add 9,9,0
+	slwi 9,9,3
+	mullw 9,9,4
+	slwi 9,9,9
+	addis 9,9,0xc000
+	stw 9,copypage@l(31)
+.L3615:
+	lwz 0,origrange@l(29)
+	cmpwi 0,0,0
+	bc 4,2,.L3617
+.L3631:
+	lis 9,state1@ha
+	lwz 7,state1@l(9)
+	lis 11,state2@ha
+	lwz 8,state2@l(11)
+	lis 9,state3@ha
+	lwz 0,state3@l(9)
+	lis 11,swsusp_action@ha
+	lis 9,swsusp_debug_state@ha
+	lis 10,console_printk@ha
+	stw 7,swsusp_action@l(11)
+	stw 8,swsusp_debug_state@l(9)
+	stw 0,console_printk@l(10)
+	/* bl restore_stack
+	bl restore_processor_state */
+	//bl ppc_restore_reg
+	bl do_swsusp2_resume_2
+.L3611:
+	lwz 0,52(1)
+	mtlr 0
+	lmw 23,12(1)
+	la 1,48(1)
+	blr
+.Lfe1:
+	.size	 do_swsusp_lowlevel,.Lfe1-do_swsusp_lowlevel
+	.section	".data.nosave"
+	.align 2
+	.type	 origrange,@object
+	.size	 origrange,4
+origrange:
+	.space	4
+	.align 2
+	.type	 copyrange,@object
+	.size	 copyrange,4
+copyrange:
+	.space	4
+	.align 2
+	.type	 origoffset,@object
+	.size	 origoffset,4
+origoffset:
+	.space	4
+	.align 2
+	.type	 copyoffset,@object
+	.size	 copyoffset,4
+copyoffset:
+	.space	4
+	.align 2
+	.type	 origpage,@object
+	.size	 origpage,4
+origpage:
+	.space	4
+	.align 2
+	.type	 copypage,@object
+	.size	 copypage,4
+copypage:
+	.space	4
+	.align 2
+	.type	 orig_min_free,@object
+	.size	 orig_min_free,4
+orig_min_free:
+	.space	4
+	.section	".text"
+	.align 2
+	.globl do_swsusp2_copyback
+	.type	 do_swsusp2_copyback,@function
+do_swsusp2_copyback:
+	stwu 1,-48(1)
+	stmw 23,12(1)
+	lis 9,swsusp_action@ha
+	lwz 0,swsusp_action@l(9)
+	lis 11,swsusp_debug_state@ha
+	lis 9,state1@ha
+	stw 0,state1@l(9)
+	lwz 8,swsusp_debug_state@l(11)
+	lis 10,console_printk@ha
+	lis 9,state2@ha
+	lis 11,pagedir_resume@ha
+	stw 8,state2@l(9)
+	la 11,pagedir_resume@l(11)
+	lwz 0,console_printk@l(10)
+	lwz 5,12(11)
+	lis 9,state3@ha
+	stw 0,state3@l(9)
+	lwz 10,0(5)
+	lwz 4,56(11)
+	lis 9,origoffset@ha
+	stw 10,origoffset@l(9)
+	lwz 0,0(4)
+	lis 11,copyoffset@ha
+	stw 0,copyoffset@l(11)
+	lwz 10,origoffset@l(9)
+	lwz 8,copyoffset@l(11)
+	slwi 9,10,2
+	slwi 11,8,2
+	add 9,9,10
+	add 11,11,8
+	lis 0,0xcccc
+	ori 0,0,52429
+	slwi 9,9,3
+	slwi 11,11,3
+	mullw 11,11,0
+	mullw 9,9,0
+	slwi 11,11,9
+	slwi 9,9,9
+	cmpwi 0,5,0
+	addis 9,9,0xc000
+	addis 11,11,0xc000
+	lis 7,origrange@ha
+	lis 6,copyrange@ha
+	lis 10,origpage@ha
+	lis 8,copypage@ha
+	stw 9,origpage@l(10)
+	stw 11,copypage@l(8)
+	stw 5,origrange@l(7)
+	stw 4,copyrange@l(6)
+	lis 24,origrange@ha
+	lis 25,copyrange@ha
+	lis 12,origoffset@ha
+	lis 3,copyoffset@ha
+	bc 12,2,.L3594
+	lis 4,0xcccc
+	lis 28,loop@ha
+	lis 26,origoffset@ha
+	lis 29,origrange@ha
+	lis 30,origpage@ha
+	ori 4,4,52429
+	lis 27,copyoffset@ha
+	lis 31,copypage@ha
+.L3595:
+	li 0,0
+	stw 0,loop@l(28)
+	lwz 9,loop@l(28)
+	cmplwi 0,9,1023
+	bc 12,1,.L3597
+	lis 7,loop@ha
+	lis 5,origpage@ha
+	lis 6,copypage@ha
+.L3599:
+	lwz 8,loop@l(7)
+	lwz 9,loop@l(7)
+	lwz 11,copypage@l(6)
+	slwi 9,9,2
+	lwzx 0,9,11
+	lwz 10,origpage@l(5)
+	slwi 8,8,2
+	stwx 0,8,10
+	lwz 9,loop@l(7)
+	addi 9,9,1
+	stw 9,loop@l(7)
+	lwz 0,loop@l(7)
+	cmplwi 0,0,1023
+	bc 4,1,.L3599
+.L3597:
+	lwz 11,origrange@l(29)
+	lwz 9,origoffset@l(26)
+	lwz 0,4(11)
+	cmplw 0,9,0
+	bc 4,0,.L3601
+	lwz 9,origoffset@l(12)
+	lwz 11,origpage@l(30)
+	addi 9,9,1
+	addi 11,11,4096
+	stw 9,origoffset@l(12)
+	stw 11,origpage@l(30)
+	b .L3602
+.L3601:
+	lwz 9,8(11)
+	cmpwi 0,9,0
+	stw 9,origrange@l(24)
+	bc 12,2,.L3602
+	lwz 9,0(9)
+	stw 9,origoffset@l(12)
+	lwz 0,origoffset@l(12)
+	slwi 9,0,2
+	add 9,9,0
+	slwi 9,9,3
+	mullw 9,9,4
+	slwi 9,9,9
+	addis 9,9,0xc000
+	stw 9,origpage@l(30)
+.L3602:
+	lis 9,copyrange@ha
+	lwz 9,copyrange@l(9)
+	lwz 11,copyoffset@l(27)
+	lwz 0,4(9)
+	cmplw 0,11,0
+	bc 4,0,.L3605
+	lwz 9,copyoffset@l(3)
+	lwz 11,copypage@l(31)
+	addi 9,9,1
+	addi 11,11,4096
+	stw 9,copyoffset@l(3)
+	stw 11,copypage@l(31)
+	b .L3593
+.L3605:
+	lwz 9,8(9)
+	cmpwi 0,9,0
+	stw 9,copyrange@l(25)
+	bc 12,2,.L3593
+	lwz 9,0(9)
+	stw 9,copyoffset@l(3)
+	lwz 0,copyoffset@l(3)
+	slwi 9,0,2
+	add 9,9,0
+	slwi 9,9,3
+	mullw 9,9,4
+	slwi 9,9,9
+	addis 9,9,0xc000
+	stw 9,copypage@l(31)
+.L3593:
+	lwz 0,origrange@l(29)
+	cmpwi 0,0,0
+	bc 4,2,.L3595
+.L3594:
+	lis 9,state1@ha
+	lwz 7,state1@l(9)
+	lis 11,state2@ha
+	lwz 8,state2@l(11)
+	lis 9,state3@ha
+	lwz 0,state3@l(9)
+	lis 11,swsusp_action@ha
+	lis 9,swsusp_debug_state@ha
+	lis 10,console_printk@ha
+	stw 7,swsusp_action@l(11)
+	stw 8,swsusp_debug_state@l(9)
+	stw 0,console_printk@l(10)
+	lmw 23,12(1)
+	la 1,48(1)
+	blr
+.Lfe2:
+	.size	 do_swsusp2_copyback,.Lfe2-do_swsusp2_copyback
+	.align 2
+	.globl flush_tlb_all
+	.type	 flush_tlb_all,@function
+flush_tlb_all:
+	blr
+.Lfe3:
+	.size	 flush_tlb_all,.Lfe3-flush_tlb_all
+	.ident	"GCC: (GNU) 2.95.4 20011002 (Debian prerelease)"
Index: arch/ppc/kernel/Makefile
===================================================================
--- arch/ppc/kernel/Makefile	(revision 192)
+++ arch/ppc/kernel/Makefile	(working copy)
@@ -34,3 +34,5 @@
 obj-$(CONFIG_8xx)		+= softemu8xx.o
 endif
 
+obj-$(CONFIG_SOFTWARE_SUSPEND2) += swsusp2-asm.o
+obj-$(CONFIG_SOFTWARE_SUSPEND2) += ppc_reg.o
Index: arch/ppc/kernel/ppc_reg.S
===================================================================
--- arch/ppc/kernel/ppc_reg.S	(revision 0)
+++ arch/ppc/kernel/ppc_reg.S	(revision 0)
@@ -0,0 +1,250 @@
+/*
+ * This file contains sleep low-level functions for PowerBook G3.
+ *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *    and Paul Mackerras (paulus@samba.org).
+ *
+ * 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, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
+
+#define MAGIC	0x4c617273	/* 'Lars' */
+
+/*
+ * Structure for storing CPU registers on the stack.
+ */
+#define SL_SP		0
+#define SL_PC		4
+#define SL_MSR		8
+#define SL_SDR1		0xc
+#define SL_SPRG0	0x10	/* 4 sprg's */
+#define SL_DBAT0	0x20
+#define SL_IBAT0	0x28
+#define SL_DBAT1	0x30
+#define SL_IBAT1	0x38
+#define SL_DBAT2	0x40
+#define SL_IBAT2	0x48
+#define SL_DBAT3	0x50
+#define SL_IBAT3	0x58
+#define SL_TB		0x60
+#define SL_R2		0x68
+#define SL_CR		0x6c
+#define SL_R12		0x70	/* r12 to r31 */
+#define SL_SIZE		(SL_R12 + 80)
+
+	.section .text
+	.align	5
+
+/* This gets called by via-pmu.c late during the sleep process.
+ * The PMU was already send the sleep command and will shut us down
+ * soon. We need to save all that is needed and setup the wakeup
+ * vector that will be called by the ROM on wakeup
+ */
+_GLOBAL(ppc_save_reg)
+	mflr	r0
+	stw	r0,4(r1)
+	stwu	r1,-SL_SIZE(r1)
+	mfcr	r0
+	stw	r0,SL_CR(r1)
+	stw	r2,SL_R2(r1)
+	stmw	r12,SL_R12(r1)
+
+	/* Save MSR & SDR1 */
+	mfmsr	r4
+	stw	r4,SL_MSR(r1)
+	mfsdr1	r4
+	stw	r4,SL_SDR1(r1)
+
+	/* Get a stable timebase and save it */
+1:	mftbu	r4
+	stw	r4,SL_TB(r1)
+	mftb	r5
+	stw	r5,SL_TB+4(r1)
+	mftbu	r3
+	cmpw	r3,r4
+	bne	1b
+
+	/* Save SPRGs */
+	mfsprg	r4,0
+	stw	r4,SL_SPRG0(r1)
+	mfsprg	r4,1
+	stw	r4,SL_SPRG0+4(r1)
+	mfsprg	r4,2
+	stw	r4,SL_SPRG0+8(r1)
+	mfsprg	r4,3
+	stw	r4,SL_SPRG0+12(r1)
+
+	/* Save BATs */
+	mfdbatu	r4,0
+	stw	r4,SL_DBAT0(r1)
+	mfdbatl	r4,0
+	stw	r4,SL_DBAT0+4(r1)
+	mfdbatu	r4,1
+	stw	r4,SL_DBAT1(r1)
+	mfdbatl	r4,1
+	stw	r4,SL_DBAT1+4(r1)
+	mfdbatu	r4,2
+	stw	r4,SL_DBAT2(r1)
+	mfdbatl	r4,2
+	stw	r4,SL_DBAT2+4(r1)
+	mfdbatu	r4,3
+	stw	r4,SL_DBAT3(r1)
+	mfdbatl	r4,3
+	stw	r4,SL_DBAT3+4(r1)
+	mfibatu	r4,0
+	stw	r4,SL_IBAT0(r1)
+	mfibatl	r4,0
+	stw	r4,SL_IBAT0+4(r1)
+	mfibatu	r4,1
+	stw	r4,SL_IBAT1(r1)
+	mfibatl	r4,1
+	stw	r4,SL_IBAT1+4(r1)
+	mfibatu	r4,2
+	stw	r4,SL_IBAT2(r1)
+	mfibatl	r4,2
+	stw	r4,SL_IBAT2+4(r1)
+	mfibatu	r4,3
+	stw	r4,SL_IBAT3(r1)
+	mfibatl	r4,3
+	stw	r4,SL_IBAT3+4(r1)
+
+	/* Backup various CPU config stuffs */
+	bl	__save_cpu_setup
+
+	/* Store a pointer to our backup storage into
+	 * a kernel global
+	 */
+	lis r3,sleep_storage@ha
+	addi r3,r3,sleep_storage@l
+	stw r5,0(r3)
+	
+_GLOBAL(ppc_restore_reg)
+	/* Recover sleep storage */
+	lis	r3,sleep_storage@ha
+	addi	r3,r3,sleep_storage@l
+	tophys(r3,r3)
+	lwz	r1,0(r3)
+	
+	/* Restore various CPU config stuffs */
+	bl	__restore_cpu_setup
+
+	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
+	lwz	r4,SL_SDR1(r1)
+	mtsdr1	r4
+	lwz	r4,SL_SPRG0(r1)
+	mtsprg	0,r4
+	lwz	r4,SL_SPRG0+4(r1)
+	mtsprg	1,r4
+	lwz	r4,SL_SPRG0+8(r1)
+	mtsprg	2,r4
+	lwz	r4,SL_SPRG0+12(r1)
+	mtsprg	3,r4
+
+	lwz	r4,SL_DBAT0(r1)
+	mtdbatu	0,r4
+	lwz	r4,SL_DBAT0+4(r1)
+	mtdbatl	0,r4
+	lwz	r4,SL_DBAT1(r1)
+	mtdbatu	1,r4
+	lwz	r4,SL_DBAT1+4(r1)
+	mtdbatl	1,r4
+	lwz	r4,SL_DBAT2(r1)
+	mtdbatu	2,r4
+	lwz	r4,SL_DBAT2+4(r1)
+	mtdbatl	2,r4
+	lwz	r4,SL_DBAT3(r1)
+	mtdbatu	3,r4
+	lwz	r4,SL_DBAT3+4(r1)
+	mtdbatl	3,r4
+	lwz	r4,SL_IBAT0(r1)
+	mtibatu	0,r4
+	lwz	r4,SL_IBAT0+4(r1)
+	mtibatl	0,r4
+	lwz	r4,SL_IBAT1(r1)
+	mtibatu	1,r4
+	lwz	r4,SL_IBAT1+4(r1)
+	mtibatl	1,r4
+	lwz	r4,SL_IBAT2(r1)
+	mtibatu	2,r4
+	lwz	r4,SL_IBAT2+4(r1)
+	mtibatl	2,r4
+	lwz	r4,SL_IBAT3(r1)
+	mtibatu	3,r4
+	lwz	r4,SL_IBAT3+4(r1)
+	mtibatl	3,r4
+BEGIN_FTR_SECTION
+	li	r4,0
+	mtspr	SPRN_DBAT4U,r4
+	mtspr	SPRN_DBAT4L,r4
+	mtspr	SPRN_DBAT5U,r4
+	mtspr	SPRN_DBAT5L,r4
+	mtspr	SPRN_DBAT6U,r4
+	mtspr	SPRN_DBAT6L,r4
+	mtspr	SPRN_DBAT7U,r4
+	mtspr	SPRN_DBAT7L,r4
+	mtspr	SPRN_IBAT4U,r4
+	mtspr	SPRN_IBAT4L,r4
+	mtspr	SPRN_IBAT5U,r4
+	mtspr	SPRN_IBAT5L,r4
+	mtspr	SPRN_IBAT6U,r4
+	mtspr	SPRN_IBAT6L,r4
+	mtspr	SPRN_IBAT7U,r4
+	mtspr	SPRN_IBAT7L,r4
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
+
+#if 0
+	/* Flush all TLBs */
+	lis	r4,0x1000
+1:	addic.	r4,r4,-0x1000
+	tlbie	r4
+	blt	1b
+	sync
+
+	/* restore the MSR and turn on the MMU */
+	lwz	r3,SL_MSR(r1)
+	bl	turn_on_mmu
+
+	/* get back the stack pointer */
+	tovirt(r1,r1)
+
+	/* Restore TB */
+	li	r3,0
+	mttbl	r3
+	lwz	r3,SL_TB(r1)
+	lwz	r4,SL_TB+4(r1)
+	mttbu	r3
+	mttbl	r4
+
+	/* Restore the callee-saved registers and return */
+	lwz	r0,SL_CR(r1)
+	mtcr	r0
+	lwz	r2,SL_R2(r1)
+	lmw	r12,SL_R12(r1)
+	addi	r1,r1,SL_SIZE
+	lwz	r0,4(r1)
+	mtlr	r0
+	blr
+
+turn_on_mmu:
+	mflr	r4
+	tovirt(r4,r4)
+	mtsrr0	r4
+	mtsrr1	r3
+	sync
+	isync
+	rfi
+#endif
+	.section .data
+sleep_storage:
+	.long 0
Index: arch/ppc/kernel/vmlinux.lds.S
===================================================================
--- arch/ppc/kernel/vmlinux.lds.S	(revision 192)
+++ arch/ppc/kernel/vmlinux.lds.S	(working copy)
@@ -72,6 +72,12 @@
     CONSTRUCTORS
   }
 
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
Index: arch/ppc/kernel/swsusp2.c
===================================================================
--- arch/ppc/kernel/swsusp2.c	(revision 0)
+++ arch/ppc/kernel/swsusp2.c	(revision 0)
@@ -0,0 +1,153 @@
+ /*
+  * Copyright 2003 Nigel Cunningham.
+  *
+  * This is the code that the code in swsusp2-asm.S for
+  * copying back the original kernel is based upon. It
+  * was based upon code that is...
+  * Copyright 2001-2002 Pavel Machek <pavel@suse.cz>
+  * Based on code
+  * Copyright 2001 Patrick Mochel <mochel@osdl.org>
+  */
+#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/irq.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/suspend-debug.h>
+#include <linux/suspend-common.h>
+#include <asm/uaccess.h>
+
+/* Local variables for do_swsusp2_suspend */
+volatile static int loop __nosavedata = 0;
+volatile static int state1 __nosavedata = 0;
+volatile static int state2 __nosavedata = 0;
+volatile static int state3 __nosavedata = 0;
+volatile static struct range *origrange __nosavedata;
+volatile static struct range *copyrange __nosavedata;
+volatile static int origoffset __nosavedata;
+volatile static int copyoffset __nosavedata;
+volatile static unsigned long * origpage __nosavedata;
+volatile static unsigned long * copypage __nosavedata;
+volatile static int orig_min_free __nosavedata;
+#ifndef CONFIG_SMP
+static unsigned long c_loops_per_jiffy_ref __nosavedata = 0;
+static unsigned long cpu_khz_ref __nosavedata = 0;
+#endif
+
+extern void do_swsusp2_suspend_1(void);
+extern void do_swsusp2_suspend_2(void);
+extern void do_swsusp2_resume_1(void);
+extern void do_swsusp2_resume_2(void);
+extern struct pagedir __nosavedata pagedir_resume;
+
+/*
+ * FIXME: This function should really be written in assembly. Actually
+ * requirement is that it does not touch stack, because %esp will be
+ * wrong during resume before restore_processor_context(). Check
+ * assembly if you modify this.
+ */
+inline void do_swsusp2_copyback(void)
+{
+#ifdef CONFIG_PREEMPT
+	/*
+	 * Preempt disabled in kernel we're about to restore.
+	 * Make sure we match state now.
+	 */
+	preempt_disable();
+	PRINTPREEMPTCOUNT("Prior to copying old kernel back.");
+#endif
+
+	state1 = swsusp_action;
+	state2 = swsusp_debug_state;
+	state3 = console_loglevel;
+
+#ifndef CONFIG_SMP
+	//c_loops_per_jiffy_ref = cpu_data->loops_per_jiffy;
+	//cpu_khz_ref = cpu_khz;
+#endif
+	
+	origrange = pagedir_resume.origranges.first;
+	copyrange = pagedir_resume.destranges.first;
+	origoffset = origrange->minimum;
+	copyoffset = copyrange->minimum;
+	origpage = (unsigned long *) (page_address(mem_map + origoffset));
+	copypage = (unsigned long *) (page_address(mem_map + copyoffset));
+	//orig_min_free = swsusp_min_free;
+
+	while (origrange) {
+		for (loop=0; loop < (PAGE_SIZE / sizeof(unsigned long)); loop++)
+			*(origpage + loop) = *(copypage + loop);
+		
+		if (origoffset < origrange->maximum) {
+			origoffset++;
+			origpage += (PAGE_SIZE / sizeof(unsigned long));
+		} else {
+			origrange = origrange->next;
+			if (origrange) {
+				origoffset = origrange->minimum;
+				origpage = (unsigned long *) (page_address(mem_map + origoffset));
+			}
+		}
+
+		if (copyoffset < copyrange->maximum) {
+			copyoffset++;
+			copypage += (PAGE_SIZE / sizeof(unsigned long));
+		} else {
+			copyrange = copyrange->next;
+			if (copyrange) {
+				copyoffset = copyrange->minimum;
+				copypage = (unsigned long *) (page_address(mem_map + copyoffset));
+			}
+		}
+	}
+	
+/* Ahah, we now run with our old stack, and with registers copied from
+   suspend time */
+
+#ifndef CONFIG_SMP
+	//cpu_data->loops_per_jiffy = c_loops_per_jiffy_ref;
+	//loops_per_jiffy = c_loops_per_jiffy_ref;
+	//cpu_khz = cpu_khz_ref;
+#endif
+	swsusp_action = state1;
+	swsusp_debug_state = state2;
+	console_loglevel = state3;
+	//swsusp_min_free = orig_min_free;
+}
+
+extern void save_process_state();
+extern void restore_process_state();
+extern void save_stack();
+extern void restore_stack();
+
+void do_swsusp_lowlevel(int resume)
+{
+	if (!resume) {
+		do_swsusp2_suspend_1();
+		save_processor_state();
+		save_stack();
+		do_swsusp2_suspend_2();
+		return;
+	}
+	__asm__ __volatile__("lis %%r2, %0":"=m"(swapper_pg_dir));	
+//	__asm__ __volatile__("addi %%r2, %%r2, %0":"memory"(swapper_pg_dir));
+	do_swsusp2_resume_1();
+	do_swsusp2_copyback();
+	restore_stack();
+	restore_processor_state();
+	do_swsusp2_resume_2();
+	return;
+}
+
+void flush_tlb_all()
+{
+}
Index: kernel/power/swsusp2.c
===================================================================
--- kernel/power/swsusp2.c	(revision 192)
+++ kernel/power/swsusp2.c	(working copy)
@@ -54,7 +54,9 @@
 
 #include <linux/suspend-common.h>
 #include <linux/suspend-version-specific.h>
+#ifdef  CONFIG_X86
 #include <asm/i387.h> /* for kernel_fpu_end */
+#endif
 #ifdef	CONFIG_KDB
 #include <linux/kdb.h>
 #endif	/* CONFIG_KDB */
@@ -327,7 +329,9 @@
 	preempt_enable();
 #endif
 
+#ifdef CONFIG_X86
 	kernel_fpu_end();
+#endif
 
 	PRINTPREEMPTCOUNT("Prior to resuming drivers.");
 
@@ -486,10 +490,10 @@
 #endif
 
 	PRINTPREEMPTCOUNT("In resume_2 after copy back.");
-
+#ifdef CONFIG_X86
 	kernel_fpu_end();
-
 	PRINTPREEMPTCOUNT("In resume_2 after fpu end.");
+#endif
 	
 #ifdef CONFIG_PREEMPT
 	preempt_enable();

[-- Attachment #3: suspend --]
[-- Type: application/octet-stream, Size: 318 bytes --]

#!/bin/sh

swapon -a
sync
sync


for i in `lsmod | awk '{print $1}'`
do
	rmmod $i
done

mount -t proc none /proc
mount /sys

echo -n "disk" > /sys/power/state
echo -n "6" > /proc/swsusp/default_console_level
echo -n "1" > /proc/swsusp/slow
echo -n "1" > /proc/swsusp/debug_sections
echo -n "1" > /proc/swsusp/activate

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19  2:52 Help port swsusp to ppc Hugang
@ 2004-01-19  3:04 ` Nigel Cunningham
  2004-01-19  3:35 ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-19  3:04 UTC (permalink / raw)
  To: Hugang; +Cc: ncunningham, Linux Kernel Mailing List, debian-powerpc

[-- Attachment #1: Type: text/plain, Size: 1756 bytes --]

Hi.

I'd love to be able to help, but unfortunately the old assembly I know
is good old 6502 :> Hopefully someone else will pipe up and get you
going.

Once you do get it going, I'll be happy to help keep the other parts
updated, so far as I'm able.

Regards,

Nigel

On Mon, 2004-01-19 at 15:52, Hugang wrote:
> Hello guys:
> 
> I'm try to porting Software Suspend to PowerPC. But I'm not family with
> PowerPC assemble languae. So need someone to help me write the save
> process state function in assemble language.
> 
> 1: Download i386 suspend patch for 2.6.1 from swsusp.sf.net
>  you need two patch 
>  software-suspend-core-2.0-rc4-whole.bz2
>  software-suspend-linux-2.6.1-rev1-whole.bz2
> 2: first you need apply linux-2.6.1 to 2.6.1 clean kernel
>    then apply core-2.0-rc4 to current patched kernel
> 3: then apply ppc-swsusp.patch to patched kernel
> 4: do make menuconfig
>  CONFIG_SOFTWARE_SUSPEND2=y
>  CONFIG_SOFTWARE_SUSPEND_DEBUG=y
>  CONFIG_SOFTWARE_SUSPEND_GZIP_COMPRESSION=y
>  CONFIG_SOFTWARE_SUSPEND_KEEP_IMAGE=y
>  CONFIG_SOFTWARE_SUSPEND_LZF_COMPRESSION=y
>  CONFIG_SOFTWARE_SUSPEND_SWAPWRITER=y
> 5: test with swsusp enable kernel.
>  in yaboot prompt:
>  /vmlinux.swsusp root=/dev/hda13 resume2=swap:/dev/hda10 init=/bin/sh
>  
>  /dev/hda13 is the root device name
>  /dev/hda10 is swap device name
>  
> 6: run suspend script to do software suspend, now the machine will power
>  off.
> 
> 7: power on machin, in yaboot prompt:
>   /vmlinux.swsusp root=/dev/hda13 resume2=swap:/dev/hda10 init=/bin/sh
> 
> But for now the save and restore processor state is not finish, the
> resume will oops.
-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19  2:52 Help port swsusp to ppc Hugang
  2004-01-19  3:04 ` Nigel Cunningham
@ 2004-01-19  3:35 ` Benjamin Herrenschmidt
  2004-01-19  5:20   ` Nigel Cunningham
  1 sibling, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-19  3:35 UTC (permalink / raw)
  To: Hugang; +Cc: ncunningham, Linux Kernel list, debian-powerpc

Hi !

Some comments...

>Index: arch/ppc/kernel/swsusp2-asm.S
>===================================================================
>--- arch/ppc/kernel/swsusp2-asm.S	(revision 0)
>+++ arch/ppc/kernel/swsusp2-asm.S	(revision 0)


What is this file ? It's absolutely horrible....


>Index: arch/ppc/kernel/Makefile
>===================================================================
>--- arch/ppc/kernel/Makefile	(revision 192)
>+++ arch/ppc/kernel/Makefile	(working copy)
>@@ -34,3 +34,5 @@
> obj-$(CONFIG_8xx)		+= softemu8xx.o
> endif
>
>+obj-$(CONFIG_SOFTWARE_SUSPEND2) += swsusp2-asm.o
>+obj-$(CONFIG_SOFTWARE_SUSPEND2) += ppc_reg.o

You could have put both of these on the same line.


>Index: arch/ppc/kernel/vmlinux.lds.S
>===================================================================
>--- arch/ppc/kernel/vmlinux.lds.S	(revision 192)
>+++ arch/ppc/kernel/vmlinux.lds.S	(working copy)
>@@ -72,6 +72,12 @@
>     CONSTRUCTORS
>   }
> 
>+  . = ALIGN(4096);
>+  __nosave_begin = .;
>+  .data_nosave : { *(.data.nosave) }
>+  . = ALIGN(4096);
>+  __nosave_end = .;
>+
>   . = ALIGN(32);
>   .data.cacheline_aligned : { *(.data.cacheline_aligned) }

Why do you need the above for ?




^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19  3:35 ` Benjamin Herrenschmidt
@ 2004-01-19  5:20   ` Nigel Cunningham
  2004-01-19 11:39     ` Benjamin Herrenschmidt
  2004-01-19 20:40     ` Pavel Machek
  0 siblings, 2 replies; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-19  5:20 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Hugang, ncunningham, Linux Kernel Mailing List, debian-powerpc

[-- Attachment #1: Type: text/plain, Size: 1354 bytes --]

Hi.

I can answer a couple of the questions:

On Mon, 2004-01-19 at 16:35, Benjamin Herrenschmidt wrote:
> What is this file ? It's absolutely horrible....

It should contain the .S equivalent to the swsusp2.c file. It would be
best if swsusp2.c could simply be compiled, but it appears that it can't
at the moment on x86 (I need to learn x86 assembly so I can understand
why).


> >Index: arch/ppc/kernel/vmlinux.lds.S
> >===================================================================
> >--- arch/ppc/kernel/vmlinux.lds.S	(revision 192)
> >+++ arch/ppc/kernel/vmlinux.lds.S	(working copy)
> >@@ -72,6 +72,12 @@
> >     CONSTRUCTORS
> >   }
> > 
> >+  . = ALIGN(4096);
> >+  __nosave_begin = .;
> >+  .data_nosave : { *(.data.nosave) }
> >+  . = ALIGN(4096);
> >+  __nosave_end = .;
> >+
> >   . = ALIGN(32);
> >   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
> 
> Why do you need the above for ?

That idea is to have a section that doesn't get replaced when we copy
the original kernel back. Thus, small amounts of data that suspend uses
or stores can be given the __nosave attribute. An example is the cpu
frequency value, which should match the boot kernel, not the value at
suspend time.

Regards,

Nigel


-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19  5:20   ` Nigel Cunningham
@ 2004-01-19 11:39     ` Benjamin Herrenschmidt
  2004-01-19 17:56       ` Nigel Cunningham
  2004-01-19 20:45       ` Help port swsusp to ppc Pavel Machek
  2004-01-19 20:40     ` Pavel Machek
  1 sibling, 2 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-19 11:39 UTC (permalink / raw)
  To: ncunningham
  Cc: Hugang, ncunningham, Linux Kernel Mailing List, debian-powerpc


> It should contain the .S equivalent to the swsusp2.c file. It would be
> best if swsusp2.c could simply be compiled, but it appears that it can't
> at the moment on x86 (I need to learn x86 assembly so I can understand
> why).

I see no reason why this would be needed on ppc, only the last step,
that is the actual CPU state save, should matter.

> That idea is to have a section that doesn't get replaced when we copy
> the original kernel back. Thus, small amounts of data that suspend uses
> or stores can be given the __nosave attribute. An example is the cpu
> frequency value, which should match the boot kernel, not the value at
> suspend time.

That's very hairy... You basically assume the boot kernel and the
restore kernel are completely identical, which isn't something I would
do. I didn't have time to dive into it, but I do/did intend to implement
swsusp on ppc and I would eventually resume the whole environement
straight from the bootloader without kernel help.

If you want to pass some infos between the "loader" kernel and the "loaded"
one, I strongly suggest you define some well specified interface for doing
so that is immune to kernel versions.

Also, I haven't looked in details, but when switching to the "new" kernel
from the "loader" (boot) one, do you shut down all devices properly ?
This switch could actually be fairly similar to a kexec pass in this
regard.

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 11:39     ` Benjamin Herrenschmidt
@ 2004-01-19 17:56       ` Nigel Cunningham
  2004-01-19 22:03         ` Benjamin Herrenschmidt
  2004-01-19 20:45       ` Help port swsusp to ppc Pavel Machek
  1 sibling, 1 reply; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-19 17:56 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Hugang, ncunningham, Linux Kernel Mailing List, debian-powerpc

[-- Attachment #1: Type: text/plain, Size: 1977 bytes --]

Hi.

On Tue, 2004-01-20 at 00:39, Benjamin Herrenschmidt wrote:
> I see no reason why this would be needed on ppc, only the last step,
> that is the actual CPU state save, should matter.

Besides saving the CPU state, the code copies the original kernel back.
It sort of defeats the purpose to remove that code :>

> That's very hairy... You basically assume the boot kernel and the
> restore kernel are completely identical, which isn't something I would
> do. I didn't have time to dive into it, but I do/did intend to implement
> swsusp on ppc and I would eventually resume the whole environement
> straight from the bootloader without kernel help.

Well, the whole things is pretty hairy :> But I don't think there's
anything wrong with assuming the boot and restored kernels are
identical. After all, we're calling it suspending and resuming, not
kexec. It does sound nice to do it all from the bootloader without
kernel help.

> If you want to pass some infos between the "loader" kernel and the "loaded"
> one, I strongly suggest you define some well specified interface for doing
> so that is immune to kernel versions.

It is a well defined interface: a section of memory marked nosave, with
variables given the matching attribute. Not my idea, by the way. If you
have a problem, you should be taking it up with Pavel or Linus. We
should also note that the interface can't be too well defined - there
has to be room for development over time.

> Also, I haven't looked in details, but when switching to the "new" kernel
> from the "loader" (boot) one, do you shut down all devices properly ?
> This switch could actually be fairly similar to a kexec pass in this
> regard.

Yes. we device_suspend. Regarding the similarities with kexec, I fully
agree. In fact, there is also LKCD to think off. There should be a
synergy here.

Regards,

Nigel
-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19  5:20   ` Nigel Cunningham
  2004-01-19 11:39     ` Benjamin Herrenschmidt
@ 2004-01-19 20:40     ` Pavel Machek
  2004-01-19 23:40       ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-19 20:40 UTC (permalink / raw)
  To: Nigel Cunningham
  Cc: Benjamin Herrenschmidt, Hugang, ncunningham,
	Linux Kernel Mailing List, debian-powerpc

Hi!

> I can answer a couple of the questions:
> 
> > What is this file ? It's absolutely horrible....
> 
> It should contain the .S equivalent to the swsusp2.c file. It would be
> best if swsusp2.c could simply be compiled, but it appears that it can't
> at the moment on x86 (I need to learn x86 assembly so I can understand
> why).

You need to check resulting assembly for stack accesses. So yes, you
can compile it from .c file, _but you have to read it_.
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 11:39     ` Benjamin Herrenschmidt
  2004-01-19 17:56       ` Nigel Cunningham
@ 2004-01-19 20:45       ` Pavel Machek
  2004-01-19 23:38         ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-19 20:45 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc

Hi!

> > That idea is to have a section that doesn't get replaced when we copy
> > the original kernel back. Thus, small amounts of data that suspend uses
> > or stores can be given the __nosave attribute. An example is the cpu
> > frequency value, which should match the boot kernel, not the value at
> > suspend time.
> 
> That's very hairy... You basically assume the boot kernel and the
> restore kernel are completely identical, which isn't something I would
> do. I didn't have time to dive into it, but I do/did intend to implement
> swsusp on ppc and I would eventually resume the whole environement
> straight from the bootloader without kernel help.

Well, then what you do is not swsusp.

swsusp does assume same kernel during suspend and resume. Doing resume
within bootloader (and thus avoiding this) would be completely
different design.

> Also, I haven't looked in details, but when switching to the "new" kernel
> from the "loader" (boot) one, do you shut down all devices properly ?
> This switch could actually be fairly similar to a kexec pass in this
> regard.

I hope we do shut devices down. In my tree at least.
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 17:56       ` Nigel Cunningham
@ 2004-01-19 22:03         ` Benjamin Herrenschmidt
  2004-01-20 20:44           ` Pavel Machek
  2004-01-22 13:17           ` Hugang
  0 siblings, 2 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-19 22:03 UTC (permalink / raw)
  To: ncunningham
  Cc: Hugang, ncunningham, Linux Kernel Mailing List, debian-powerpc

On Tue, 2004-01-20 at 04:56, Nigel Cunningham wrote:
> Hi.
> 
> On Tue, 2004-01-20 at 00:39, Benjamin Herrenschmidt wrote:
> > I see no reason why this would be needed on ppc, only the last step,
> > that is the actual CPU state save, should matter.
> 
> Besides saving the CPU state, the code copies the original kernel back.
> It sort of defeats the purpose to remove that code :>

Ok, you mean copying the memory pages back down ? That should be done
with hand-made assembly or C code located specifically elsewhere then.
I do not want to see any kind of this ugly C-generated assembly in
arch/ppc.
 
> Well, the whole things is pretty hairy :> But I don't think there's
> anything wrong with assuming the boot and restored kernels are
> identical. After all, we're calling it suspending and resuming, not
> kexec. It does sound nice to do it all from the bootloader without
> kernel help.

I think that's a wrong assumption. I see personally _NO_ reason to
assume the boot and restored kernel are the same. They absolutely
don't need to do at all.

> It is a well defined interface: a section of memory marked nosave, with
> variables given the matching attribute. Not my idea, by the way. If you
> have a problem, you should be taking it up with Pavel or Linus. We
> should also note that the interface can't be too well defined - there
> has to be room for development over time.

Still... That makes assumptions about how it's located and organised
that plain wrong (c). Please get rid of that, at least I won't let a PPC
version do that. Depending on how much time I can spare, I'll try to
work on that PPC port later this week. If you need something like clock
calibration data down to the loaded kernel, then either re-calculate it
in the wakeup code path, or pass it via some _sane_ interface (at
_least_ a versioned data structure, better, a tagged list of values like
some bootloaders do).

> Yes. we device_suspend. Regarding the similarities with kexec, I fully
> agree. In fact, there is also LKCD to think off. There should be a
> synergy here.

device_suspend is, imho, hairy too. We have some semantics that need
cleanup here, I'll have to talk to Patrick about them. Putting devices
to an idle state is what you need and what kexec need, and doesn't mean
putting them to _sleep_. Or maybe we could pass a specific state to
device_suspend for that. For example, it makes little sense to spin down
the hard disk at this stage, or to power off the video chip...

Ben.
 


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 20:45       ` Help port swsusp to ppc Pavel Machek
@ 2004-01-19 23:38         ` Benjamin Herrenschmidt
  2004-01-20  0:04           ` Pavel Machek
  2004-01-20  9:53           ` Geert Uytterhoeven
  0 siblings, 2 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-19 23:38 UTC (permalink / raw)
  To: Pavel Machek
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc


> Well, then what you do is not swsusp.
> 
> swsusp does assume same kernel during suspend and resume. Doing resume
> within bootloader (and thus avoiding this) would be completely
> different design.

Wait... what the hell in swsusp requires this assumption ? It seems to
me like a completely unnecessary design limitation.

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 20:40     ` Pavel Machek
@ 2004-01-19 23:40       ` Benjamin Herrenschmidt
  2004-01-19 23:59         ` Pavel Machek
  0 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-19 23:40 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Nigel Cunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc


> You need to check resulting assembly for stack accesses. So yes, you
> can compile it from .c file, _but you have to read it_.

Hrm... That's awful and terribly fragile. You should either write
it entirely in assembly (thus readable & commented) or write it in
C with a temporary stack or whatever that makes it safe. I'll certainly
not let something like that sneak into arch/ppc anyway.

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 23:40       ` Benjamin Herrenschmidt
@ 2004-01-19 23:59         ` Pavel Machek
  0 siblings, 0 replies; 80+ messages in thread
From: Pavel Machek @ 2004-01-19 23:59 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Nigel Cunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc

Hi!

> > You need to check resulting assembly for stack accesses. So yes, you
> > can compile it from .c file, _but you have to read it_.
> 
> Hrm... That's awful and terribly fragile. You should either write
> it entirely in assembly (thus readable & commented) or write it in

Take a look before commenting.

Long time ago I took .c version, compiled it into assembly,
handcleaned (etc) and now its used.

But if someone wants to do ppc, taking .c version, compiling it into
assembly, then checking/fixing is probably easiest way...

								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 23:38         ` Benjamin Herrenschmidt
@ 2004-01-20  0:04           ` Pavel Machek
  2004-01-20  1:06             ` Benjamin Herrenschmidt
  2004-01-20  9:53           ` Geert Uytterhoeven
  1 sibling, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-20  0:04 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc

Hi!

> > Well, then what you do is not swsusp.
> > 
> > swsusp does assume same kernel during suspend and resume. Doing resume
> > within bootloader (and thus avoiding this) would be completely
> > different design.
> 
> Wait... what the hell in swsusp requires this assumption ? It seems to
> me like a completely unnecessary design limitation.

(1) There's routine during resume that copies pages to their old
locations. If you (would want to) have different kernel during resume,
how do you guarantee that that "kernel being resumed" does not use
memory ocupied by copying routine?

(2) Plus number of problems with devices grows with number of versions
squared. To guarantee it works properly you'd have to test all
combinations of "suspend kernel" and "resume kernel".

[(1) Could be solved by reserving 4KB somewhere for copy routine, and
making sure copy routine is never bigger than 4KB etc. But I'd like to
keep it simple and really don't want to deal with (2).]
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20  0:04           ` Pavel Machek
@ 2004-01-20  1:06             ` Benjamin Herrenschmidt
  2004-01-20 10:02               ` Pavel Machek
  0 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-20  1:06 UTC (permalink / raw)
  To: Pavel Machek
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc


> (1) There's routine during resume that copies pages to their old
> locations. If you (would want to) have different kernel during resume,
> how do you guarantee that that "kernel being resumed" does not use
> memory ocupied by copying routine?

By having the copy routine sit elsewhere. You can have the copy routine
be in a known location of the kernel beeing resumed (that is it uses
its own copy routine) that is aligned on a page boundary and knows how
to copy itself. Fairly trivial.

> (2) Plus number of problems with devices grows with number of versions
> squared. To guarantee it works properly you'd have to test all
> combinations of "suspend kernel" and "resume kernel".

Why ? You aren't passing any device/driver information from the boot
kernel and the resumed one... do you ?

> [(1) Could be solved by reserving 4KB somewhere for copy routine, and
> making sure copy routine is never bigger than 4KB etc. But I'd like to
> keep it simple and really don't want to deal with (2).]

Then you don't wnat to do things properly...

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 23:38         ` Benjamin Herrenschmidt
  2004-01-20  0:04           ` Pavel Machek
@ 2004-01-20  9:53           ` Geert Uytterhoeven
  2004-01-20 10:04             ` Pavel Machek
  2004-01-20 11:22             ` Benjamin Herrenschmidt
  1 sibling, 2 replies; 80+ messages in thread
From: Geert Uytterhoeven @ 2004-01-20  9:53 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Pavel Machek, ncunningham, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC

On Tue, 20 Jan 2004, Benjamin Herrenschmidt wrote:
> > Well, then what you do is not swsusp.
> >
> > swsusp does assume same kernel during suspend and resume. Doing resume
> > within bootloader (and thus avoiding this) would be completely
> > different design.
>
> Wait... what the hell in swsusp requires this assumption ? It seems to
> me like a completely unnecessary design limitation.

Swsusp saves the data structures from the suspended kernel, so they have to
match the data structures of the resumed kernel, right?

I't s a bit like trying insmod -f on a module compiled for a completely
different kernel version... *bang*

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20  1:06             ` Benjamin Herrenschmidt
@ 2004-01-20 10:02               ` Pavel Machek
  2004-01-20 11:25                 ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-20 10:02 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc

Hi!

> > (1) There's routine during resume that copies pages to their old
> > locations. If you (would want to) have different kernel during resume,
> > how do you guarantee that that "kernel being resumed" does not use
> > memory ocupied by copying routine?
> 
> By having the copy routine sit elsewhere. You can have the copy routine
> be in a known location of the kernel beeing resumed (that is it uses
> its own copy routine) that is aligned on a page boundary and knows how
> to copy itself. Fairly trivial.

I said it is possible to solve. But "copy routine" becomes even more
nasty than it is already.

> > (2) Plus number of problems with devices grows with number of versions
> > squared. To guarantee it works properly you'd have to test all
> > combinations of "suspend kernel" and "resume kernel".
> 
> Why ? You aren't passing any device/driver information from the boot
> kernel and the resumed one... do you ?

I'm not passing device information, but devices *do* have internal
state. I quiesce them before booting new kernel, but there's probably
more than one way to quiesce devices...

> > [(1) Could be solved by reserving 4KB somewhere for copy routine, and
> > making sure copy routine is never bigger than 4KB etc. But I'd like to
> > keep it simple and really don't want to deal with (2).]
> 
> Then you don't wnat to do things properly...

No, I really do not want to make things more complicated in 2.6. And
you should not want to complicate it, too.
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20  9:53           ` Geert Uytterhoeven
@ 2004-01-20 10:04             ` Pavel Machek
  2004-01-20 11:26               ` Benjamin Herrenschmidt
  2004-01-20 11:22             ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-20 10:04 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Benjamin Herrenschmidt, ncunningham, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC

Hi!

> > > Well, then what you do is not swsusp.
> > >
> > > swsusp does assume same kernel during suspend and resume. Doing resume
> > > within bootloader (and thus avoiding this) would be completely
> > > different design.
> >
> > Wait... what the hell in swsusp requires this assumption ? It seems to
> > me like a completely unnecessary design limitation.
> 
> Swsusp saves the data structures from the suspended kernel, so they have to
> match the data structures of the resumed kernel, right?

Well, *all* the data pages are saved, so that would be okay (even if
they changed, as I'm replacing all the data pages, that should work),
but I'm not saving kernel text for example.
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20  9:53           ` Geert Uytterhoeven
  2004-01-20 10:04             ` Pavel Machek
@ 2004-01-20 11:22             ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-20 11:22 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Pavel Machek, ncunningham, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC


> Swsusp saves the data structures from the suspended kernel, so they have to
> match the data structures of the resumed kernel, right?
> 
> I't s a bit like trying insmod -f on a module compiled for a completely
> different kernel version... *bang*

No, swsusp saves the whole memory image, including the old kernel. The
"boot" kernel is only used as a loader until all pages are put back in
place and control can be given back to the old kernel. Well, that might
not exactly be what x86 does but that's definitely waht I'll do on PPC :)

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 10:02               ` Pavel Machek
@ 2004-01-20 11:25                 ` Benjamin Herrenschmidt
  2004-01-20 11:44                   ` Pavel Machek
  0 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-20 11:25 UTC (permalink / raw)
  To: Pavel Machek
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc


> I'm not passing device information, but devices *do* have internal
> state. I quiesce them before booting new kernel, but there's probably
> more than one way to quiesce devices...

Not that many. You don't quite know in what state they are when
the BIOS calls you neither in most cases :) Nor when waking up
from BIOS-managed state.... It's usually safe if they just don't
bust master and are idle.

> No, I really do not want to make things more complicated in 2.6. And
> you should not want to complicate it, too.

I will not impose that limitation on a ppc implementation. I don't
even want to load the resume image from the boot kernel, it's much more
easier to load it from the bootloader for me anyway. And the copy routine
is just a tricky bit of asm, not even _that_ tricky I'd say (well, I don't
do x86 asm, but I've certainly had to deal with more tricky stuffs on
ppc so far).

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 10:04             ` Pavel Machek
@ 2004-01-20 11:26               ` Benjamin Herrenschmidt
  2004-01-20 11:36                 ` Pavel Machek
  0 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-20 11:26 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Geert Uytterhoeven, ncunningham, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC

On Tue, 2004-01-20 at 21:04, Pavel Machek wrote:

> Well, *all* the data pages are saved, so that would be okay (even if
> they changed, as I'm replacing all the data pages, that should work),
> but I'm not saving kernel text for example.

Ahh... that's an interesting point. You aren't saving kernel text. I'm
not sure how that could be a problem for me. I think i'll just save it
along with the image though. I think there is much risk screwing up
because an uncompatible boot/load kernel pair here than because devices
aren't fully idle.

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 11:26               ` Benjamin Herrenschmidt
@ 2004-01-20 11:36                 ` Pavel Machek
  2004-01-20 11:44                   ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-20 11:36 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Geert Uytterhoeven, ncunningham, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC

Hi!

> > Well, *all* the data pages are saved, so that would be okay (even if
> > they changed, as I'm replacing all the data pages, that should work),
> > but I'm not saving kernel text for example.
> 
> Ahh... that's an interesting point. You aren't saving kernel text. I'm
> not sure how that could be a problem for me. I think i'll just save it
> along with the image though. 

Also pay attetion to page tables. I know that page tables "copy"
routine is running from are same between suspend and resume kernel.

								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 11:36                 ` Pavel Machek
@ 2004-01-20 11:44                   ` Benjamin Herrenschmidt
  2004-01-20 11:57                     ` Pavel Machek
  2004-01-20 18:30                     ` Nigel Cunningham
  0 siblings, 2 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-20 11:44 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Geert Uytterhoeven, ncunningham, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC

On Tue, 2004-01-20 at 22:36, Pavel Machek wrote:
> Hi!
> 
> > > Well, *all* the data pages are saved, so that would be okay (even if
> > > they changed, as I'm replacing all the data pages, that should work),
> > > but I'm not saving kernel text for example.
> > 
> > Ahh... that's an interesting point. You aren't saving kernel text. I'm
> > not sure how that could be a problem for me. I think i'll just save it
> > along with the image though. 
> 
> Also pay attetion to page tables. I know that page tables "copy"
> routine is running from are same between suspend and resume kernel.

I plan to run everything provided by the suspended kernel actually. My idea
is to keep a handle to a page of the suspended kernel that contains that
code and just kick into it. Copying pages to their final location without
overriding the source pages is a bit of a funky job, but I had to do it
already with BootX so ... I'll work on that during one of the upcoming few
weeks hopefully, I'm a bit swamped with 3 different things at the moment.

ben.
 


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 11:25                 ` Benjamin Herrenschmidt
@ 2004-01-20 11:44                   ` Pavel Machek
  0 siblings, 0 replies; 80+ messages in thread
From: Pavel Machek @ 2004-01-20 11:44 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc

Hi!

> > No, I really do not want to make things more complicated in 2.6. And
> > you should not want to complicate it, too.
> 
> I will not impose that limitation on a ppc implementation. I don't
> even want to load the resume image from the boot kernel, it's much more
> easier to load it from the bootloader for me anyway. And the copy
> routine

Well, if you have just one common bootloader on ppc, no problem, go
ahead at load it from bootloader. You'll not have to worry about page
tables etc. I could not do that on i386 because there are many
bootloaders in use here.

You are going to have completely different resume phase, through. [And
if someone wants suspend-to-disk on ppc, *now*, it might still be
easiest to write those two screens of assembly to port swsusp to ppc.]

								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 11:44                   ` Benjamin Herrenschmidt
@ 2004-01-20 11:57                     ` Pavel Machek
  2004-01-20 18:30                     ` Nigel Cunningham
  1 sibling, 0 replies; 80+ messages in thread
From: Pavel Machek @ 2004-01-20 11:57 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Geert Uytterhoeven, ncunningham, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC

Hi!

> > > > Well, *all* the data pages are saved, so that would be okay (even if
> > > > they changed, as I'm replacing all the data pages, that should work),
> > > > but I'm not saving kernel text for example.
> > > 
> > > Ahh... that's an interesting point. You aren't saving kernel text. I'm
> > > not sure how that could be a problem for me. I think i'll just save it
> > > along with the image though. 
> > 
> > Also pay attetion to page tables. I know that page tables "copy"
> > routine is running from are same between suspend and resume kernel.
> 
> I plan to run everything provided by the suspended kernel actually. My idea
> is to keep a handle to a page of the suspended kernel that contains that
> code and just kick into it. Copying pages to their final location without
> overriding the source pages is a bit of a funky job, but I had to do it
> already with BootX so ... I'll work on that during one of the upcoming few
> weeks hopefully, I'm a bit swamped with 3 different things at the
> moment.

You actually *know* that half of memory is free during resume, so you
can load kernel-to-be-resumed data into that free memory. That's how
swsusp works. It makes it quite simple...
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 11:44                   ` Benjamin Herrenschmidt
  2004-01-20 11:57                     ` Pavel Machek
@ 2004-01-20 18:30                     ` Nigel Cunningham
  2004-01-20 21:43                       ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-20 18:30 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Pavel Machek, Geert Uytterhoeven, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC

[-- Attachment #1: Type: text/plain, Size: 874 bytes --]

I'm really interested to see how you are going to initiate and execute
the suspend.

Perhaps I'm just ignorant, but I can't see how you can do it without
resorting to the same tricks we use now with regards to CPU context. I
think you're going to find yourself reinventing the wheel.

Regards,

Nigel

> I plan to run everything provided by the suspended kernel actually. My idea
> is to keep a handle to a page of the suspended kernel that contains that
> code and just kick into it. Copying pages to their final location without
> overriding the source pages is a bit of a funky job, but I had to do it
> already with BootX so ... I'll work on that during one of the upcoming few
> weeks hopefully, I'm a bit swamped with 3 different things at the moment.
> 
> ben.
>  
-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 22:03         ` Benjamin Herrenschmidt
@ 2004-01-20 20:44           ` Pavel Machek
  2004-01-20 21:54             ` Benjamin Herrenschmidt
  2004-01-22 13:17           ` Hugang
  1 sibling, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-20 20:44 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc

Hi!

> > On Tue, 2004-01-20 at 00:39, Benjamin Herrenschmidt wrote:
> > > I see no reason why this would be needed on ppc, only the last step,
> > > that is the actual CPU state save, should matter.
> > 
> > Besides saving the CPU state, the code copies the original kernel back.
> > It sort of defeats the purpose to remove that code :>
> 
> Ok, you mean copying the memory pages back down ? That should be done
> with hand-made assembly or C code located specifically elsewhere then.
> I do not want to see any kind of this ugly C-generated assembly in
> arch/ppc.

FYI, this is that "ugly C-generated assembly" we are talking about. I
do not think it is so bad.

.text

/* Originally gcc generated, modified by hand */

#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/page.h>

	.text

ENTRY(do_magic)
	pushl %ebx
	cmpl $0,8(%esp)
	jne .L1450
	call do_magic_suspend_1
	call save_processor_state

	movl %esp, saved_context_esp
	movl %eax, saved_context_eax
	movl %ebx, saved_context_ebx
	movl %ecx, saved_context_ecx
	movl %edx, saved_context_edx
	movl %ebp, saved_context_ebp
	movl %esi, saved_context_esi
	movl %edi, saved_context_edi
	pushfl ; popl saved_context_eflags

	call do_magic_suspend_2
	jmp .L1449
	.p2align 4,,7
.L1450:
	movl $swapper_pg_dir-__PAGE_OFFSET,%ecx
	movl %ecx,%cr3

	call do_magic_resume_1
	movl $0,loop
	cmpl $0,nr_copy_pages
	je .L1453
	.p2align 4,,7
.L1455:
	movl $0,loop2
	.p2align 4,,7
.L1459:
	movl pagedir_nosave,%ecx
	movl loop,%eax
	movl loop2,%edx
	sall $4,%eax
	movl 4(%ecx,%eax),%ebx
	movl (%ecx,%eax),%eax
	movb (%edx,%eax),%al
	movb %al,(%edx,%ebx)
	movl %cr3, %eax;              
	movl %eax, %cr3;  # flush TLB 

	movl loop2,%eax
	leal 1(%eax),%edx
	movl %edx,loop2
	movl %edx,%eax
	cmpl $4095,%eax
	jbe .L1459
	movl loop,%eax
	leal 1(%eax),%edx
	movl %edx,loop
	movl %edx,%eax
	cmpl nr_copy_pages,%eax
	jb .L1455
	.p2align 4,,7
.L1453:
	movl $__USER_DS,%eax

	movw %ax, %ds
	movw %ax, %es
	movl saved_context_esp, %esp
	movl saved_context_ebp, %ebp
	movl saved_context_eax, %eax
	movl saved_context_ebx, %ebx
	movl saved_context_ecx, %ecx
	movl saved_context_edx, %edx
	movl saved_context_esi, %esi
	movl saved_context_edi, %edi
	call restore_processor_state
	pushl saved_context_eflags ; popfl
	call do_magic_resume_2
.L1449:
	popl %ebx
	ret

       .section .data.nosave
loop:
       .quad 0
loop2:
       .quad 0
       .previous


> > It is a well defined interface: a section of memory marked nosave, with
> > variables given the matching attribute. Not my idea, by the way. If you
> > have a problem, you should be taking it up with Pavel or Linus. We
> > should also note that the interface can't be too well defined - there
> > has to be room for development over time.
> 
> Still... That makes assumptions about how it's located and organised
> that plain wrong (c). Please get rid of that, at least I won't let a
> PPC

FYI, there are exactly 6 variables in "nosave" section. Two loop
variables you can see in above code, one spinlock, number of pages to
save, pointer to directory of pages to be copied, and its length.

I could probably move spinlock and length of pgdir out of there...

> > Yes. we device_suspend. Regarding the similarities with kexec, I fully
> > agree. In fact, there is also LKCD to think off. There should be a
> > synergy here.
> 
> device_suspend is, imho, hairy too. We have some semantics that need
> cleanup here, I'll have to talk to Patrick about them. Putting devices
> to an idle state is what you need and what kexec need, and doesn't mean
> putting them to _sleep_. Or maybe we could pass a specific state to

Okay, I can agree that putting them into sleep is not ideal [it
puzzles users, at least]. But it is quite simple and should work
okay. I do not want another round of device_suspend changes in
2.6.X... [Well, perhaps if it was done in right&compatible way (tm),
it would be acceptable...]
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 18:30                     ` Nigel Cunningham
@ 2004-01-20 21:43                       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-20 21:43 UTC (permalink / raw)
  To: ncunningham
  Cc: Pavel Machek, Geert Uytterhoeven, Hugang, ncunningham,
	Linux Kernel Mailing List, Debian GNU/Linux PPC

On Wed, 2004-01-21 at 05:30, Nigel Cunningham wrote:
> I'm really interested to see how you are going to initiate and execute
> the suspend.
> 
> Perhaps I'm just ignorant, but I can't see how you can do it without
> resorting to the same tricks we use now with regards to CPU context. I
> think you're going to find yourself reinventing the wheel.

CPU context ? I don't think swsusp needs anything different than
suspend-to-RAM in this regard (at least the pmac version of suspend-to
-RAM that wakes up on a CPU reset). The CPU setup will be saved as part
of the kernel data and will be restored after the pages are back in
place the same way it is restored when waking up from RAM. The code
is already there (and actually, that ppc port of swsusp borrowed it).

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 20:44           ` Pavel Machek
@ 2004-01-20 21:54             ` Benjamin Herrenschmidt
  2004-01-20 22:07               ` Nigel Cunningham
  2004-01-20 22:42               ` Pavel Machek
  0 siblings, 2 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-20 21:54 UTC (permalink / raw)
  To: Pavel Machek
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc


> FYI, this is that "ugly C-generated assembly" we are talking about. I
> do not think it is so bad.

The x86 version has been cleaned up and isn't _that_ bad, though it
could definitely use some comments and I don't like the "Lxxx" labels,
I'd rather either use number with the "nb" or "nf" GAS constructs or
use real words labels. Looking at it though, I fail to see the need
to get it generated by gcc in the first place :)

The PPC version that was proposed is horrible.

> FYI, there are exactly 6 variables in "nosave" section. Two loop
> variables you can see in above code, one spinlock, number of pages to
> save, pointer to directory of pages to be copied, and its length.
> 
> I could probably move spinlock and length of pgdir out of there...

That's not too much, you could probably afford having a one page header
to the suspend image with those informations and the page copy loop
(provided by the suspended kernel so you don't have _any_ compatibility
issue and can even do it from the bootloader one day...)
 
> > device_suspend is, imho, hairy too. We have some semantics that need
> > cleanup here, I'll have to talk to Patrick about them. Putting devices
> > to an idle state is what you need and what kexec need, and doesn't mean
> > putting them to _sleep_. Or maybe we could pass a specific state to
> 
> Okay, I can agree that putting them into sleep is not ideal [it
> puzzles users, at least]. But it is quite simple and should work
> okay. I do not want another round of device_suspend changes in
> 2.6.X... [Well, perhaps if it was done in right&compatible way (tm),
> it would be acceptable...]

We already have the shutdown() callback or we can simply use device_suspend()
with a D1 parameter instead of D3 or D4. That's what I'd do...

Looking at swsusp code in current 2.6, when do you do that pass ? On the
shutdown pass, you call devices_suspend(4); which is fine. But I don't see
where you call devices_suspend(X) on the resume path. IMHO, that should be
done from the boot kernel after loading the suspend image and before
starting the resume process. Your mdelay(1000) for waiting for DMA to settle
down is PLAIN WRONG imho, even dangerous. (And typically, an USB controller
will still be hapilly be DMA'ing all over your memory). That's what I call
idling devices at this point, and that's where I'd call devices_suspend(1),
and we should do that for kexec too.

Ben.




^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 21:54             ` Benjamin Herrenschmidt
@ 2004-01-20 22:07               ` Nigel Cunningham
  2004-01-20 22:42               ` Pavel Machek
  1 sibling, 0 replies; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-20 22:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Pavel Machek, Hugang, Linux Kernel Mailing List, debian-powerpc

[-- Attachment #1: Type: text/plain, Size: 1954 bytes --]

Hi.

On Wed, 2004-01-21 at 10:54, Benjamin Herrenschmidt wrote:
> > FYI, this is that "ugly C-generated assembly" we are talking about. I
> > do not think it is so bad.
> 
> The x86 version has been cleaned up and isn't _that_ bad, though it
> could definitely use some comments and I don't like the "Lxxx" labels,
> I'd rather either use number with the "nb" or "nf" GAS constructs or
> use real words labels. Looking at it though, I fail to see the need
> to get it generated by gcc in the first place :)

The 2.4 version works from C, even the SMP version I've prepared.
Something in 2.6 is different, and I don't understand what/why (Pavel
might be able to explain). If I understood that, I could get SMP support
for 2.6 going too.

> The PPC version that was proposed is horrible.

I think he wanted help with cleaning it up.

> > FYI, there are exactly 6 variables in "nosave" section. Two loop
> > variables you can see in above code, one spinlock, number of pages to
> > save, pointer to directory of pages to be copied, and its length.
> > 
> > I could probably move spinlock and length of pgdir out of there...
> 
> That's not too much, you could probably afford having a one page header
> to the suspend image with those informations and the page copy loop
> (provided by the suspended kernel so you don't have _any_ compatibility
> issue and can even do it from the bootloader one day...)

Well, we do have a header at the moment with that info, (but not
containing the page copy loop :>)
 
> Looking at swsusp code in current 2.6, when do you do that pass ? On the
> shutdown pass, you call devices_suspend(4); which is fine. But I don't see
> where you call devices_suspend(X) on the resume path. IMHO, that should be

Hmm. Perhaps it's just my version that does it? I couldn't find it
either.

Regards,

Nigel

-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-20 21:54             ` Benjamin Herrenschmidt
  2004-01-20 22:07               ` Nigel Cunningham
@ 2004-01-20 22:42               ` Pavel Machek
  1 sibling, 0 replies; 80+ messages in thread
From: Pavel Machek @ 2004-01-20 22:42 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: ncunningham, Hugang, ncunningham, Linux Kernel Mailing List,
	debian-powerpc

Hi!

> > FYI, this is that "ugly C-generated assembly" we are talking about. I
> > do not think it is so bad.
> 
> The x86 version has been cleaned up and isn't _that_ bad, though it
> could definitely use some comments and I don't like the "Lxxx" labels,
> I'd rather either use number with the "nb" or "nf" GAS constructs or
> use real words labels. Looking at it though, I fail to see the need
> to get it generated by gcc in the first place :)

Well, I had C version that was working (and it was slightly easier to
code it in C), and really did not want to introduce errors at that
point.

> The PPC version that was proposed is horrible.

Sorry, I missed that one.

> > FYI, there are exactly 6 variables in "nosave" section. Two loop
> > variables you can see in above code, one spinlock, number of pages to
> > save, pointer to directory of pages to be copied, and its length.
> > 
> > I could probably move spinlock and length of pgdir out of there...
> 
> That's not too much, you could probably afford having a one page header
> to the suspend image with those informations and the page copy loop
> (provided by the suspended kernel so you don't have _any_ compatibility
> issue and can even do it from the bootloader one day...)

Unfortunately the copy loop has quite complicated interface. It
expects tables already loaded into memory, at non-conflicting
addresses etc.

> > > device_suspend is, imho, hairy too. We have some semantics that need
> > > cleanup here, I'll have to talk to Patrick about them. Putting devices
> > > to an idle state is what you need and what kexec need, and doesn't mean
> > > putting them to _sleep_. Or maybe we could pass a specific state to
> > 
> > Okay, I can agree that putting them into sleep is not ideal [it
> > puzzles users, at least]. But it is quite simple and should work
> > okay. I do not want another round of device_suspend changes in
> > 2.6.X... [Well, perhaps if it was done in right&compatible way (tm),
> > it would be acceptable...]
> 
> We already have the shutdown() callback or we can simply use device_suspend()
> with a D1 parameter instead of D3 or D4. That's what I'd do...

We need to do something with those 1,3s and 4s. IIRC there's no such
thing as D4 (or is it expected to be == D3cold?). This needs to be
documented somewhere.

> Looking at swsusp code in current 2.6, when do you do that pass ? On the
> shutdown pass, you call devices_suspend(4); which is fine. But I don't see
> where you call devices_suspend(X) on the resume path. IMHO, that
> should be

My fault, the patch is in my tree only. (Its here for quite a long
time. I synced it to Patrick and then he disappeared.).

> done from the boot kernel after loading the suspend image and before
> starting the resume process. Your mdelay(1000) for waiting for DMA to settle
> down is PLAIN WRONG imho, even dangerous. (And typically, an USB controller
> will still be hapilly be DMA'ing all over your memory). That's what I call
> idling devices at this point, and that's where I'd call devices_suspend(1),
> and we should do that for kexec too.

Yes, that's right solution. Here's the patch.

Index: linux/kernel/power/swsusp.c
===================================================================
--- linux.orig/kernel/power/swsusp.c	2004-01-13 22:52:40.000000000 +0100
+++ linux/kernel/power/swsusp.c	2004-01-09 20:33:05.000000000 +0100
@@ -488,33 +492,6 @@
 	printk("|\n");
 }
 
-/* Make disk drivers accept operations, again */
-static void drivers_unsuspend(void)
-{
-	device_resume();
-}
-
-/* Called from process context */
-static int drivers_suspend(void)
-{
-	return device_suspend(4);
-}
-
-#define RESUME_PHASE1 1 /* Called from interrupts disabled */
-#define RESUME_PHASE2 2 /* Called with interrupts enabled */
-#define RESUME_ALL_PHASES (RESUME_PHASE1 | RESUME_PHASE2)
-static void drivers_resume(int flags)
-{
-	if (flags & RESUME_PHASE1) {
-		device_resume();
-	}
-  	if (flags & RESUME_PHASE2) {
-#ifdef SUSPEND_CONSOLE
-		update_screen(fg_console);	/* Hmm, is this the problem? */
-#endif
-	}
-}
-
 static int suspend_prepare_image(void)
 {
 	struct sysinfo i;
@@ -569,7 +546,7 @@
 
 static void suspend_save_image(void)
 {
-	drivers_unsuspend();
+	device_resume();
 
 	lock_swapdevices();
 	write_suspend_image();
@@ -615,6 +592,7 @@
 	mb();
 	spin_lock_irq(&suspend_pagedir_lock);	/* Done to disable interrupts */ 
 
+	device_power_down(4);
 	PRINTK( "Waiting for DMAs to settle down...\n");
 	mdelay(1000);	/* We do not want some readahead with DMA to corrupt our memory, right?
 			   Do it with disabled interrupts for best effect. That way, if some
@@ -630,8 +608,10 @@
 
 	PRINTK( "Freeing prev allocated pagedir\n" );
 	free_suspend_pagedir((unsigned long) pagedir_save);
+	device_power_up();
 	spin_unlock_irq(&suspend_pagedir_lock);
-	drivers_resume(RESUME_ALL_PHASES);
+	device_resume();
+	update_screen(fg_console);	/* Hmm, is this the problem? */
 
 	PRINTK( "Fixing swap signatures... " );
 	mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
@@ -672,7 +652,9 @@
 {
 	int is_problem;
 	read_swapfiles();
+	device_power_down(4);
 	is_problem = suspend_prepare_image();
+	device_power_up();
 	spin_unlock_irq(&suspend_pagedir_lock);
 	if (!is_problem) {
 		kernel_fpu_end();	/* save_processor_state() does kernel_fpu_begin, and we need to revert it in order to pass in_atomic() checks */
@@ -716,7 +709,7 @@
 		blk_run_queues();
 
 		/* Save state of all device drivers, and stop them. */		   
-		if(drivers_suspend()==0)
+		if ((res = device_suspend(4))==0)
 			/* If stopping device drivers worked, we proceed basically into
 			 * suspend_save_image.
 			 *
@@ -1091,6 +1072,7 @@
 	printk( "resuming from %s\n", resume_file);
 	if (read_suspend_image(resume_file, 0))
 		goto read_failure;
+	device_suspend(4);
 	do_magic(1);
 	panic("This never returns");
 



-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-19 22:03         ` Benjamin Herrenschmidt
  2004-01-20 20:44           ` Pavel Machek
@ 2004-01-22 13:17           ` Hugang
  2004-01-22 17:53             ` Nigel Cunningham
  2004-01-23  7:12             ` Benjamin Herrenschmidt
  1 sibling, 2 replies; 80+ messages in thread
From: Hugang @ 2004-01-22 13:17 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: ncunningham, ncunningham, Linux Kernel Mailing List, debian-powerpc

[-- Attachment #1: Type: text/plain, Size: 919 bytes --]

On Tue, 20 Jan 2004 09:03:11 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Tue, 2004-01-20 at 04:56, Nigel Cunningham wrote:
> > Hi.
> > 
> > On Tue, 2004-01-20 at 00:39, Benjamin Herrenschmidt wrote:
> > > I see no reason why this would be needed on ppc, only the last
> > > step, that is the actual CPU state save, should matter.
> > 
> > Besides saving the CPU state, the code copies the original kernel
> > back. It sort of defeats the purpose to remove that code :>
> 

Attached file is current version of port swsusp to ppc, STILL can not
works, Benjamin, gave me some comments.

I has add one files swsusp2-asm.S. The save/restore processor state base
on pmac_sleep.S. The copybackup is copy from gcc generate assmeble.

Now the suspend has no problem, resume can not works, strange.

-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

[-- Attachment #2: arch_ppc.diff --]
[-- Type: text/plain, Size: 17639 bytes --]

Index: linux-2.6.1-suspend/arch/ppc/Kconfig
===================================================================
--- linux-2.6.1-suspend/arch/ppc/Kconfig	(revision 192)
+++ linux-2.6.1-suspend/arch/ppc/Kconfig	(working copy)
@@ -193,6 +193,8 @@
 
 	  If in doubt, say Y here.
 
+source kernel/power/Kconfig
+
 source arch/ppc/platforms/4xx/Kconfig
 
 config PPC64BRIDGE
@@ -681,6 +683,7 @@
 
 config NR_CPUS
 	int "Maximum number of CPUs (2-32)"
+	range 2 32
 	depends on SMP
 	default "4"
 
Index: linux-2.6.1-suspend/arch/ppc/kernel/swsusp2-asm.S
===================================================================
--- linux-2.6.1-suspend/arch/ppc/kernel/swsusp2-asm.S	(revision 0)
+++ linux-2.6.1-suspend/arch/ppc/kernel/swsusp2-asm.S	(revision 0)
@@ -0,0 +1,516 @@
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
+
+/*
+ * Structure for storing CPU registers on the stack.
+ */
+#define SL_SP		0
+#define SL_PC		4
+#define SL_MSR		8
+#define SL_SDR1		0xc
+#define SL_SPRG0	0x10	/* 4 sprg's */
+#define SL_DBAT0	0x20
+#define SL_IBAT0	0x28
+#define SL_DBAT1	0x30
+#define SL_IBAT1	0x38
+#define SL_DBAT2	0x40
+#define SL_IBAT2	0x48
+#define SL_DBAT3	0x50
+#define SL_IBAT3	0x58
+#define SL_TB		0x60
+#define SL_R2		0x68
+#define SL_CR		0x6c
+#define SL_R12		0x70	/* r12 to r31 */
+#define SL_SIZE		(SL_R12 + 80)
+	
+	.section .text
+	.align 5
+_GLOBAL(do_swsusp_lowlevel)
+	cmpwi	0,r3,0
+	bc	4,2,.L3627
+	
+	mflr	r0	
+	stw	r0,4(r1)
+	stwu	r1,-SL_SIZE(r1)
+
+	mfcr	r0
+	stw	r0,SL_CR(r1)
+	stw	r2,SL_R2(r1)
+	stmw	r12,SL_R12(r1)
+	
+	bl	do_swsusp2_suspend_1
+		
+	stw	r0,SL_PC(r1)	/* saving r0 */
+
+	mfcr	r0			/* move from condition register to r0 */
+	stw	r0,SL_CR(r1)
+	stw	r2,SL_R2(r1)
+	stmw	r12,SL_R12(r1)
+
+	/* Save MSR & SDR1 */
+	mfmsr	r4
+	stw	r4,SL_MSR(r1)
+	mfsdr1	r4
+	stw	r4,SL_SDR1(r1)
+
+	/* Get a stable timebase and save it */
+1:	mftbu	r4
+	stw	r4,SL_TB(r1)
+	mftb	r5
+	stw	r5,SL_TB+4(r1)
+	mftbu	r3
+	cmpw	r3,r4
+	bne	1b
+
+	/* Save SPRGs */
+	mfsprg	r4,0
+	stw	r4,SL_SPRG0(r1)
+	mfsprg	r4,1
+	stw	r4,SL_SPRG0+4(r1)
+	mfsprg	r4,2
+	stw	r4,SL_SPRG0+8(r1)
+	mfsprg	r4,3
+	stw	r4,SL_SPRG0+12(r1)
+
+	/* Save BATs */
+	mfdbatu	r4,0
+	stw	r4,SL_DBAT0(r1)
+	mfdbatl	r4,0
+	stw	r4,SL_DBAT0+4(r1)
+	mfdbatu	r4,1
+	stw	r4,SL_DBAT1(r1)
+	mfdbatl	r4,1
+	stw	r4,SL_DBAT1+4(r1)
+	mfdbatu	r4,2
+	stw	r4,SL_DBAT2(r1)
+	mfdbatl	r4,2
+	stw	r4,SL_DBAT2+4(r1)
+	mfdbatu	r4,3
+	stw	r4,SL_DBAT3(r1)
+	mfdbatl	r4,3
+	stw	r4,SL_DBAT3+4(r1)
+	mfibatu	r4,0
+	stw	r4,SL_IBAT0(r1)
+	mfibatl	r4,0
+	stw	r4,SL_IBAT0+4(r1)
+	mfibatu	r4,1
+	stw	r4,SL_IBAT1(r1)
+	mfibatl	r4,1
+	stw	r4,SL_IBAT1+4(r1)
+	mfibatu	r4,2
+	stw	r4,SL_IBAT2(r1)
+	mfibatl	r4,2
+	stw	r4,SL_IBAT2+4(r1)
+	mfibatu	r4,3
+	stw	r4,SL_IBAT3(r1)
+	mfibatl	r4,3
+	stw	r4,SL_IBAT3+4(r1)
+
+	/* get r1 physical ptr */
+	tophys(r5,r1)
+	addi	r5,r5,SL_PC
+	
+	/* save storage ptr */	
+	lis	r3,pm_sleep_storage@ha
+	addi	r3,r3,pm_sleep_storage@l
+	stw	r5,0(r3)
+	
+	/* Backup various CPU configs stuffs */	
+	bl	__save_cpu_setup
+
+	bl	do_swsusp2_suspend_2
+
+	b	restore_stack
+		
+.L3627:
+	bl do_swsusp2_resume_1
+
+	lis r9,swsusp_action@ha
+	lwz r0,swsusp_action@l(r9)
+	lis r11,swsusp_debug_state@ha
+	lis r9,state1@ha
+	stw r0,state1@l(r9)
+	lwz r8,swsusp_debug_state@l(r11)
+	lis r10,console_printk@ha
+	lis r9,state2@ha
+	lis r11,pagedir_resume@ha
+	stw r8,state2@l(r9)
+	la r11,pagedir_resume@l(r11)
+	lwz r0,console_printk@l(r10)
+	lwz r5,12(r11)
+	lis r9,state3@ha
+	stw r0,state3@l(r9)
+	lwz r10,0(r5)
+	lwz r4,56(r11)
+	lis r9,origoffset@ha
+	stw r10,origoffset@l(r9)
+	lwz r0,0(r4)
+	lis r11,copyoffset@ha
+	stw r0,copyoffset@l(r11)
+	lwz r10,origoffset@l(r9)
+	lwz r8,copyoffset@l(r11)
+	slwi r9,r10,r2
+	slwi r11,r8,r2
+	add r9,r9,r10
+	add r11,r11,8
+	lis r0,0xcccc
+	ori r0,r0,52429
+	slwi r9,r9,r3
+	slwi r11,r11,r3
+	mullw r11,r11,r0
+	mullw r9,r9,r0
+	slwi r11,r11,r9
+	slwi r9,r9,r9
+	cmpwi r0,r5,r0
+	addis r9,r9,0xc000
+	addis r11,r11,0xc000
+	lis r7,origrange@ha
+	lis r6,copyrange@ha
+	lis r10,origpage@ha
+	lis r8,copypage@ha
+	lis r24,origrange@ha
+	lis r25,copyrange@ha
+	lis r12,origoffset@ha
+	lis r3,copyoffset@ha
+	stw r9,origpage@l(r10)
+	stw r11,copypage@l(r8)
+	stw r5,origrange@l(r7)
+	stw r4,copyrange@l(r6)
+	bc r12,r2,.L3646
+	lis r4,0xcccc
+	lis r28,loop@ha
+	lis r26,origoffset@ha
+	lis r29,origrange@ha
+	lis r30,origpage@ha
+	ori r4,r4,52429
+	lis r27,copyoffset@ha
+	lis r31,copypage@ha
+.L3632:
+	li r0,r0
+	stw r0,loop@l(r28)
+	lwz r9,loop@l(r28)
+	cmplwi r0,r9,1023
+	bc r12,r1,.L3637
+	lis r7,loop@ha
+	lis r5,origpage@ha
+	lis r6,copypage@ha
+.L3635:
+	lwz r8,loop@l(r7)
+	lwz r9,loop@l(r7)
+	lwz r11,copypage@l(r6)
+	slwi r9,r9,r2
+	lwzx r0,r9,r11
+	lwz r10,origpage@l(r5)
+	slwi r8,r8,r2
+	stwx r0,r8,r10
+	lwz r9,loop@l(r7)
+	addi r9,r9,r1
+	stw r9,loop@l(r7)
+	lwz r0,loop@l(r7)
+	cmplwi r0,r0,1023
+	bc r4,r1,.L3635
+.L3637:
+	lwz r11,origrange@l(r29)
+	lwz r9,origoffset@l(r26)
+	lwz r0,4(r11)
+	cmplw r0,r9,r0
+	bc r4,r0,.L3638
+	lwz r9,origoffset@l(r12)
+	lwz r11,origpage@l(r30)
+	addi r9,r9,r1
+	addi r11,r11,4096
+	stw r9,origoffset@l(r12)
+	stw r11,origpage@l(r30)
+	b .L3639
+.L3638:
+	lwz r9,8(r11)
+	cmpwi r0,r9,r0
+	stw r9,origrange@l(r24)
+	bc r12,r2,.L3639
+	lwz r9,0(r9)
+	stw r9,origoffset@l(r12)
+	lwz r0,origoffset@l(r12)
+	slwi r9,r0,r2
+	add r9,r9,r0
+	slwi r9,r9,r3
+	mullw r9,r9,r4
+	slwi r9,r9,r9
+	addis r9,r9,0xc000
+	stw r9,origpage@l(r30)
+.L3639:
+	lis r9,copyrange@ha
+	lwz r9,copyrange@l(r9)
+	lwz r11,copyoffset@l(r27)
+	lwz r0,4(r9)
+	cmplw r0,r11,r0
+	bc r4,r0,.L3642
+	lwz r9,copyoffset@l(r3)
+	lwz r11,copypage@l(r31)
+	addi r9,r9,r1
+	addi r11,r11,4096
+	stw r9,copyoffset@l(r3)
+	stw r11,copypage@l(r31)
+	b .L3630
+.L3642:
+	lwz r9,r8(r9)
+	cmpwi r0,r9,r0
+	stw r9,copyrange@l(r25)
+	bc r12,r2,.L3630
+	lwz r9,0(r9)
+	stw r9,copyoffset@l(r3)
+	lwz r0,copyoffset@l(r3)
+	slwi r9,r0,r2
+	add r9,r9,r0
+	slwi r9,r9,r3
+	mullw r9,r9,r4
+	slwi r9,r9,r9
+	addis r9,r9,0xc000
+	stw 9,copypage@l(r31)
+.L3630:
+	lwz r0,origrange@l(r29)
+	cmpwi r0,r0,r0
+	bc r4,r2,.L3632
+.L3646:
+	lis r9,state1@ha
+	lwz r7,state1@l(r9)
+	lis r11,state2@ha
+	lwz r8,state2@l(r11)
+	lis r9,state3@ha
+	lwz r0,state3@l(r9)
+	lis r11,swsusp_action@ha
+	lis r9,swsusp_debug_state@ha
+	lis r10,console_printk@ha
+	stw r7,swsusp_action@l(r11)
+	stw r8,swsusp_debug_state@l(r9)
+	stw r0,console_printk@l(r10)
+
+#if 0
+	bl	pm_turn_off_mmu
+//#else
+	mfmsr	r3
+	andi.	r0,r3,MSR_DR|MSR_IR		/* MMU enabled? */
+	beqlr
+	andc	r3,r3,r0
+	mtspr	SRR0,r4
+	mtspr	SRR1,r3
+	sync
+#endif
+
+#if 1
+	/* Turn off data relocation. */
+	mfmsr	r3		/* Save MSR in r7 */
+	rlwinm	r3,r3,0,28,26	/* Turn off DR bit */
+	sync
+	mtmsr	r3
+	isync
+
+	/* Make sure HID0 no longer contains any sleep bit */
+	mfspr	r3,HID0
+	rlwinm	r3,r3,0,11,7		/* clear SLEEP, NAP, DOZE bits */
+	mtspr	HID0,r3
+	sync
+	isync
+
+	/* Won't that cause problems on CPU that doesn't support it ? */
+	lis	r3, 0
+	mtspr	SPRN_MMCR0, r3
+
+	/* sanitize MSR */
+	mfmsr	r3
+	ori	r3,r3,MSR_EE|MSR_IP
+	xori	r3,r3,MSR_EE|MSR_IP
+	sync
+	isync
+	mtmsr	r3
+	sync
+	isync
+#endif	
+	/* Recover sleep storage */
+	lis	r3,pm_sleep_storage@ha
+	addi	r3,r3,pm_sleep_storage@l
+	tophys(r3,r3)
+	lwz	r1,0(r3)
+
+	/* Invalidate & enable L1 cache, we don't care about
+	 * whatever the ROM may have tried to write to memory
+	 */
+	bl	__inval_enable_L1
+
+	/* Restore the kernel's segment registers before
+	 * we do any r1 memory access as we are not sure they
+	 * are in a sane state above the first 256Mb region
+	 */
+	li	r0,16		/* load up segment register values */
+	mtctr	r0		/* for context 0 */
+	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,0x111	/* increment VSID */
+	addis	r4,r4,0x1000	/* address of next segment */
+	bdnz	3b
+	sync
+	isync
+
+	subi	r1,r1,SL_PC
+	
+	/* Restore various CPU config stuffs */
+	bl	__restore_cpu_setup
+			
+	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
+	lwz	r4,SL_SDR1(r1)
+	mtsdr1	r4
+	lwz	r4,SL_SPRG0(r1)
+	mtsprg	0,r4
+	lwz	r4,SL_SPRG0+4(r1)
+	mtsprg	1,r4
+	lwz	r4,SL_SPRG0+8(r1)
+	mtsprg	2,r4
+	lwz	r4,SL_SPRG0+12(r1)
+	mtsprg	3,r4
+
+	lwz	r4,SL_DBAT0(r1)
+	mtdbatu	0,r4
+	lwz	r4,SL_DBAT0+4(r1)
+	mtdbatl	0,r4
+	lwz	r4,SL_DBAT1(r1)
+	mtdbatu	1,r4
+	lwz	r4,SL_DBAT1+4(r1)
+	mtdbatl	1,r4
+	lwz	r4,SL_DBAT2(r1)
+	mtdbatu	2,r4
+	lwz	r4,SL_DBAT2+4(r1)
+	mtdbatl	2,r4
+	lwz	r4,SL_DBAT3(r1)
+	mtdbatu	3,r4
+	lwz	r4,SL_DBAT3+4(r1)
+	mtdbatl	3,r4
+	lwz	r4,SL_IBAT0(r1)
+	mtibatu	0,r4
+	lwz	r4,SL_IBAT0+4(r1)
+	mtibatl	0,r4
+	lwz	r4,SL_IBAT1(r1)
+	mtibatu	1,r4
+	lwz	r4,SL_IBAT1+4(r1)
+	mtibatl	1,r4
+	lwz	r4,SL_IBAT2(r1)
+	mtibatu	2,r4
+	lwz	r4,SL_IBAT2+4(r1)
+	mtibatl	2,r4
+	lwz	r4,SL_IBAT3(r1)
+	mtibatu	3,r4
+	lwz	r4,SL_IBAT3+4(r1)
+	mtibatl	3,r4
+
+BEGIN_FTR_SECTION
+	li	r4,0
+	mtspr	SPRN_DBAT4U,r4
+	mtspr	SPRN_DBAT4L,r4
+	mtspr	SPRN_DBAT5U,r4
+	mtspr	SPRN_DBAT5L,r4
+	mtspr	SPRN_DBAT6U,r4
+	mtspr	SPRN_DBAT6L,r4
+	mtspr	SPRN_DBAT7U,r4
+	mtspr	SPRN_DBAT7L,r4
+	mtspr	SPRN_IBAT4U,r4
+	mtspr	SPRN_IBAT4L,r4
+	mtspr	SPRN_IBAT5U,r4
+	mtspr	SPRN_IBAT5L,r4
+	mtspr	SPRN_IBAT6U,r4
+	mtspr	SPRN_IBAT6L,r4
+	mtspr	SPRN_IBAT7U,r4
+	mtspr	SPRN_IBAT7L,r4
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
+
+	/* Flush all TLBs */
+	lis	r4,0x1000
+1:	addic.	r4,r4,-0x1000
+	tlbie	r4
+	blt	1b
+	sync
+
+	/* restore the MSR and turn on the MMU */
+	lwz	r3,SL_MSR(r1)
+	bl	pm_turn_on_mmu
+		
+	/* get back the stack pointer */
+	tovirt(r1,r1)	
+
+	/* Restore TB */
+	li	r3,0
+	mttbl	r3
+	lwz	r3,SL_TB(r1)
+	lwz	r4,SL_TB+4(r1)
+	mttbu	r3
+	mttbl	r4
+	
+	bl	do_swsusp2_resume_2
+	
+restore_stack:	
+	/* Restore the callee-saved registers and return */
+	lwz	r0,SL_CR(r1)
+	mtcr	r0
+	lwz	r2,SL_R2(r1)
+	lmw	r12,SL_R12(r1)
+	addi	r1,r1,SL_SIZE
+	lwz	r0,4(r1)
+	mtlr	r0
+	blr
+
+pm_turn_on_mmu:
+	mflr	r4
+	tovirt(r4,r4)
+	mtsrr0	r4
+	mtsrr1	r3
+	sync
+	isync
+	rfi
+
+pm_turn_off_mmu:	
+	mfmsr	r3
+	andi.	r0,r3,MSR_DR|MSR_IR		/* MMU enabled? */
+	beqlr
+	andc	r3,r3,r0
+	mtspr	SRR0,r4
+	mtspr	SRR1,r3
+	sync
+	rfi
+
+	.section	".data.nosave"
+origrange:
+	.long 0
+copyrange:
+	.long 0
+origoffset:
+	.long 0
+copyoffset:
+	.long 0
+origpage:
+	.long 0
+copypage:
+	.long 0
+loop:
+	.long 0
+state1:
+	.long 0
+state2:
+	.long 0
+state3:
+	.long 0
+c_loops_per_jiffy_ref:
+	.long 0
+cpu_khz_ref:
+	.long 0
+
+	.section .data
+	.balign L1_CACHE_LINE_SIZE
+pm_sleep_storage:
+	.long 0
+	.balign L1_CACHE_LINE_SIZE,0
+	
+	.text
Index: linux-2.6.1-suspend/arch/ppc/kernel/Makefile
===================================================================
--- linux-2.6.1-suspend/arch/ppc/kernel/Makefile	(revision 192)
+++ linux-2.6.1-suspend/arch/ppc/kernel/Makefile	(working copy)
@@ -34,3 +34,4 @@
 obj-$(CONFIG_8xx)		+= softemu8xx.o
 endif
 
+obj-$(CONFIG_SOFTWARE_SUSPEND2) += swsusp2-asm.o
Index: linux-2.6.1-suspend/arch/ppc/kernel/vmlinux.lds.S
===================================================================
--- linux-2.6.1-suspend/arch/ppc/kernel/vmlinux.lds.S	(revision 192)
+++ linux-2.6.1-suspend/arch/ppc/kernel/vmlinux.lds.S	(working copy)
@@ -72,6 +72,12 @@
     CONSTRUCTORS
   }
 
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
Index: linux-2.6.1-suspend/arch/ppc/kernel/signal.c
===================================================================
--- linux-2.6.1-suspend/arch/ppc/kernel/signal.c	(revision 192)
+++ linux-2.6.1-suspend/arch/ppc/kernel/signal.c	(working copy)
@@ -28,6 +28,7 @@
 #include <linux/elf.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
+#include <linux/suspend.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -552,6 +553,11 @@
 	unsigned long frame, newsp;
 	int signr, ret;
 
+	if (current->flags & PF_FREEZE) {
+		refrigerator(PF_FREEZE);
+		return 0;
+	}
+
 	if (!oldset)
 		oldset = &current->blocked;
 
Index: linux-2.6.1-suspend/arch/ppc/kernel/swsusp2.c
===================================================================
--- linux-2.6.1-suspend/arch/ppc/kernel/swsusp2.c	(revision 0)
+++ linux-2.6.1-suspend/arch/ppc/kernel/swsusp2.c	(revision 0)
@@ -0,0 +1,161 @@
+ /*
+  * Copyright 2003 Nigel Cunningham.
+  *
+  * This is the code that the code in swsusp2-asm.S for
+  * copying back the original kernel is based upon. It
+  * was based upon code that is...
+  * Copyright 2001-2002 Pavel Machek <pavel@suse.cz>
+  * Based on code
+  * Copyright 2001 Patrick Mochel <mochel@osdl.org>
+  * Copyright 2004 Hu Gang <hugang@soulinfo.com
+  *  port to PowerPC
+  */
+#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/irq.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/suspend-debug.h>
+#include <linux/suspend-common.h>
+#include <asm/uaccess.h>
+
+/* Local variables for do_swsusp2_suspend */
+volatile static int loop __nosavedata = 0;
+volatile static int state1 __nosavedata = 0;
+volatile static int state2 __nosavedata = 0;
+volatile static int state3 __nosavedata = 0;
+volatile static struct range *origrange __nosavedata;
+volatile static struct range *copyrange __nosavedata;
+volatile static int origoffset __nosavedata;
+volatile static int copyoffset __nosavedata;
+volatile static unsigned long * origpage __nosavedata;
+volatile static unsigned long * copypage __nosavedata;
+//volatile static int orig_min_free __nosavedata;
+#ifndef CONFIG_SMP
+//static unsigned long c_loops_per_jiffy_ref __nosavedata = 0;
+//static unsigned long cpu_khz_ref __nosavedata = 0;
+#endif
+
+extern void do_swsusp2_suspend_1(void);
+extern void do_swsusp2_suspend_2(void);
+extern void do_swsusp2_resume_1(void);
+extern void do_swsusp2_resume_2(void);
+extern struct pagedir __nosavedata pagedir_resume;
+
+/*
+ * FIXME: This function should really be written in assembly. Actually
+ * requirement is that it does not touch stack, because %esp will be
+ * wrong during resume before restore_processor_context(). Check
+ * assembly if you modify this.
+ */
+static inline void do_swsusp2_copyback(void)
+{
+#ifdef CONFIG_PREEMPT
+	/*
+	 * Preempt disabled in kernel we're about to restore.
+	 * Make sure we match state now.
+	 */
+	preempt_disable();
+	PRINTPREEMPTCOUNT("Prior to copying old kernel back.");
+#endif
+
+	state1 = swsusp_action;
+	state2 = swsusp_debug_state;
+	state3 = console_loglevel;
+
+#ifndef CONFIG_SMP
+	//c_loops_per_jiffy_ref = cpu_data->loops_per_jiffy;
+	//cpu_khz_ref = cpu_khz;
+#endif
+	
+	origrange = pagedir_resume.origranges.first;
+	copyrange = pagedir_resume.destranges.first;
+	origoffset = origrange->minimum;
+	copyoffset = copyrange->minimum;
+	origpage = (unsigned long *) (page_address(mem_map + origoffset));
+	copypage = (unsigned long *) (page_address(mem_map + copyoffset));
+	//orig_min_free = swsusp_min_free;
+
+	while (origrange) {
+		for (loop=0; loop < (PAGE_SIZE / sizeof(unsigned long)); loop++)
+			*(origpage + loop) = *(copypage + loop);
+		
+		if (origoffset < origrange->maximum) {
+			origoffset++;
+			origpage += (PAGE_SIZE / sizeof(unsigned long));
+		} else {
+			origrange = origrange->next;
+			if (origrange) {
+				origoffset = origrange->minimum;
+				origpage = (unsigned long *) (page_address(mem_map + origoffset));
+			}
+		}
+
+		if (copyoffset < copyrange->maximum) {
+			copyoffset++;
+			copypage += (PAGE_SIZE / sizeof(unsigned long));
+		} else {
+			copyrange = copyrange->next;
+			if (copyrange) {
+				copyoffset = copyrange->minimum;
+				copypage = (unsigned long *) (page_address(mem_map + copyoffset));
+			}
+		}
+	}
+	
+/* Ahah, we now run with our old stack, and with registers copied from
+   suspend time */
+
+#ifndef CONFIG_SMP
+	//cpu_data->loops_per_jiffy = c_loops_per_jiffy_ref;
+	//loops_per_jiffy = c_loops_per_jiffy_ref;
+	//cpu_khz = cpu_khz_ref;
+#endif
+	swsusp_action = state1;
+	swsusp_debug_state = state2;
+	console_loglevel = state3;
+	//swsusp_min_free = orig_min_free;
+}
+
+void do_swsusp_lowlevel(int resume)
+{
+	if (!resume) {
+		do_swsusp2_suspend_1();
+		/* call_processor_state() in x86 */
+		__asm__ __volatile__ (" bl save_processor_state");
+		/* saving stack */
+//		__asm__ __volatile__("sync");
+//		do_swsusp2_suspend_2();
+		return;
+	}
+
+	/* setup swapper_pg_dir in x86 */
+
+	do_swsusp2_resume_1();
+	do_swsusp2_copyback();
+	/* setup segment register */
+//	__asm__ __volatile__("sync");
+	restore_processor_state();
+	do_swsusp2_resume_2();
+}
+
+#if 0
+void flush_tlb_all(void)
+{
+	/* Flush all TLBs */
+	__asm__ __volatile__("lis 4, 0x1000");
+	__asm__ __volatile__("1: addic. 4,4,-0x1000");
+	__asm__ __volatile__("tlbie 4");
+	__asm__ __volatile__("blt 1b");
+	__asm__ __volatile__("sync");
+}
+#endif
Index: linux-2.6.1-suspend/include/asm-ppc/suspend.h
===================================================================
--- linux-2.6.1-suspend/include/asm-ppc/suspend.h	(revision 0)
+++ linux-2.6.1-suspend/include/asm-ppc/suspend.h	(revision 0)
@@ -0,0 +1,14 @@
+#ifndef _PPC_SUSPEND_H
+#define _PPC_SUSPEND_H
+
+static inline void flush_tlb_all(void)
+{
+	/* Flush all TLBs */
+	__asm__ __volatile__("lis 4, 0x1000");
+	__asm__ __volatile__("1: addic. 4,4,-0x1000");
+	__asm__ __volatile__("tlbie 4");
+	__asm__ __volatile__("blt 1b");
+	__asm__ __volatile__("sync");
+}
+
+#endif

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-22 13:17           ` Hugang
@ 2004-01-22 17:53             ` Nigel Cunningham
  2004-01-23  0:15               ` Hugang
  2004-01-23  7:12             ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-22 17:53 UTC (permalink / raw)
  To: Hugang; +Cc: Benjamin Herrenschmidt, Linux Kernel Mailing List, debian-powerpc

[-- Attachment #1: Type: text/plain, Size: 158 bytes --]

I know nothing about the PPC. Is it a uniprocessor?

Regards,

Nigel

-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-22 17:53             ` Nigel Cunningham
@ 2004-01-23  0:15               ` Hugang
  0 siblings, 0 replies; 80+ messages in thread
From: Hugang @ 2004-01-23  0:15 UTC (permalink / raw)
  To: ncunningham
  Cc: Benjamin Herrenschmidt, Linux Kernel Mailing List, debian-powerpc

On Fri, 23 Jan 2004 06:53:26 +1300
Nigel Cunningham <ncunningham@users.sourceforge.net> wrote:

> I know nothing about the PPC. Is it a uniprocessor?
> 
> Regards,
> 
> Nigel
There is a document abourt ppc, that can download from Moto, 
It help me to understand what is ppc, cool.

http://soulinfo.com/~hugang/tmp/MPCFPE_AD_R1.pdf

-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-22 13:17           ` Hugang
  2004-01-22 17:53             ` Nigel Cunningham
@ 2004-01-23  7:12             ` Benjamin Herrenschmidt
  2004-01-23 10:30               ` Hugang
  1 sibling, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-23  7:12 UTC (permalink / raw)
  To: Hugang
  Cc: Nigel Cunningham, ncunningham, Linux Kernel Mailing List, debian-powerpc


> Attached file is current version of port swsusp to ppc, STILL can not
> works, Benjamin, gave me some comments.
> 
> I has add one files swsusp2-asm.S. The save/restore processor state base
> on pmac_sleep.S. The copybackup is copy from gcc generate assmeble.
> 
> Now the suspend has no problem, resume can not works, strange.

There is at least one reason I think your code cannot work: When
resuming, you are basically blowing up the MMU hash table and kernel
page tables when copying the pages. I'm hacking on an implementation
of pmdisk at the moment that switches the MMU off during the page
copy to avoid that problem. This isn't the best way though.

I'll keep you informed of my progress

Ben.




^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Help port swsusp to ppc.
  2004-01-23  7:12             ` Benjamin Herrenschmidt
@ 2004-01-23 10:30               ` Hugang
  2004-01-24  2:54                 ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
  2004-01-24  4:39                 ` Benjamin Herrenschmidt
  0 siblings, 2 replies; 80+ messages in thread
From: Hugang @ 2004-01-23 10:30 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Nigel Cunningham, ncunningham, Linux Kernel Mailing List, debian-powerpc

[-- Attachment #1: Type: text/plain, Size: 1259 bytes --]

On Fri, 23 Jan 2004 18:12:53 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> There is at least one reason I think your code cannot work: When
> resuming, you are basically blowing up the MMU hash table and kernel
> page tables when copying the pages. I'm hacking on an implementation
> of pmdisk at the moment that switches the MMU off during the page
> copy to avoid that problem. This isn't the best way though.

I has hacking on swsusp2 to ppc for whole day. Here is the update
swsusp2-asm.S.

First I can true suspend is ok, the data and CPU context are full write
to disk. Then in resume, the copyback function works.

How I know it?
 I'm adding printk before do_swsusp2_lowleve finished, I has printf 
the r1, That is the pointer to cpu context, it must right on resume,
when resume it'll triger xmon, I d pm_sleep_storage, and check the 
pointer, I see that same things, So I true the copyback is ok, at least 
the cpu context memory has backed.

very tire day.

The current problem that is, In resume, It stop with all register
(r0-r32) is zero. I don't known where I am. :)

> I'll keep you informed of my progress
I'm too. :)

-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

[-- Attachment #2: swsusp2-asm.S --]
[-- Type: application/octet-stream, Size: 10178 bytes --]

#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/ppc_asm.h>
#include <asm/cputable.h>
#include <asm/cache.h>
#include <asm/thread_info.h>
#include <asm/offsets.h>

/*
 * Structure for storing CPU registers on the stack.
 */
#define SL_SP		0
#define SL_PC		(SL_SP + 0x4)
#define SL_MSR		(SL_SP + 0x8)
#define SL_SDR1		(SL_SP + 0xc)
#define SL_SPRG0	(SL_SP + 0x10)		/* 4 sprg's */
#define SL_DBAT0	(SL_SP + 0x20)
#define SL_IBAT0	(SL_SP + 0x28)
#define SL_DBAT1	(SL_SP + 0x30)
#define SL_IBAT1	(SL_SP + 0x38)
#define SL_DBAT2	(SL_SP + 0x40)
#define SL_IBAT2	(SL_SP + 0x48)
#define SL_DBAT3	(SL_SP + 0x50)
#define SL_IBAT3	(SL_SP + 0x58)
#define SL_TB		(SL_SP + 0x60)
#define SL_R2		(SL_SP + 0x68)
#define SL_CR		(SL_SP + 0x6c)
#define SL_R12		(SL_SP + 0x70)	/* r12 to r31 */
#define SL_SIZE		(SL_R12 + 80)

#if 0
	.section .rodata
ptr_debug:
	.string "ptr %x\n"
#endif

	.section .text
	.align 5
_GLOBAL(do_swsusp_lowlevel)
	mflr	r0					/* save return address into r0 */

	cmpwi	0,r3,0
	bc	4,2,.L3627

	bl	do_swsusp2_suspend_1

	stw		r0,SL_PC(r1)		/* save return address into r1 + 4 */
	stwu	r1,-SL_SIZE(r1) 	/* save r1 into r1 - SL_SIZE */

	mfcr	r0					/* condition register save */
	stw	r0,SL_CR(r1)
	stw	r2,SL_R2(r1)			/* r2 */
	stmw	r12,SL_R12(r1)		/* r12 */
	
	/* Save MSR & SDR1 */
	mfmsr	r4
	stw	r4,SL_MSR(r1)
	mfsdr1	r4
	stw	r4,SL_SDR1(r1)

	/* Get a stable timebase and save it */
1:	mftbu	r4
	stw	r4,SL_TB(r1)
	mftb	r5
	stw	r5,SL_TB+4(r1)
	mftbu	r3
	cmpw	r3,r4
	bne	1b

	/* Save SPRGs */
	mfsprg	r4,0
	stw	r4,SL_SPRG0(r1)
	mfsprg	r4,1
	stw	r4,SL_SPRG0+4(r1)
	mfsprg	r4,2
	stw	r4,SL_SPRG0+8(r1)
	mfsprg	r4,3
	stw	r4,SL_SPRG0+12(r1)

	/* Save BATs */
	mfdbatu	r4,0
	stw	r4,SL_DBAT0(r1)
	mfdbatl	r4,0
	stw	r4,SL_DBAT0+4(r1)
	mfdbatu	r4,1
	stw	r4,SL_DBAT1(r1)
	mfdbatl	r4,1
	stw	r4,SL_DBAT1+4(r1)
	mfdbatu	r4,2
	stw	r4,SL_DBAT2(r1)
	mfdbatl	r4,2
	stw	r4,SL_DBAT2+4(r1)
	mfdbatu	r4,3
	stw	r4,SL_DBAT3(r1)
	mfdbatl	r4,3
	stw	r4,SL_DBAT3+4(r1)
	mfibatu	r4,0
	stw	r4,SL_IBAT0(r1)
	mfibatl	r4,0
	stw	r4,SL_IBAT0+4(r1)
	mfibatu	r4,1
	stw	r4,SL_IBAT1(r1)
	mfibatl	r4,1
	stw	r4,SL_IBAT1+4(r1)
	mfibatu	r4,2
	stw	r4,SL_IBAT2(r1)
	mfibatl	r4,2
	stw	r4,SL_IBAT2+4(r1)
	mfibatu	r4,3
	stw	r4,SL_IBAT3(r1)
	mfibatl	r4,3
	stw	r4,SL_IBAT3+4(r1)

#if 0 /* TEST_CODE */
	lis		r4,0x1234
	ori		r4,r4,0x56
	stw		r4,-(SL_SIZE + 4)(r1)
#endif

	/* get r1 physical ptr */
	tophys(r5,r1)
	addi	r5,r5,SL_PC

	/* save storage ptr */	
	lis	r3,pm_sleep_storage@ha
	addi	r3,r3,pm_sleep_storage@l
	stw	r5,0(r3)

#if 0
	/* printf ptr */
	lis	r3,ptr_debug@ha
	la r3,ptr_debug@l(r3)
	bl	printk
#endif

	/* Backup various CPU configs stuffs */	
	bl	__save_cpu_setup

	bl	do_swsusp2_suspend_2

	b	restore_stack
		
.L3627:
	bl do_swsusp2_resume_1

	lis r9,swsusp_action@ha
	lwz r0,swsusp_action@l(r9)
	lis r11,swsusp_debug_state@ha
	lis r9,state1@ha
	stw r0,state1@l(r9)
	lwz r8,swsusp_debug_state@l(r11)
	lis r10,console_printk@ha
	lis r9,state2@ha
	lis r11,pagedir_resume@ha
	stw r8,state2@l(r9)
	la r11,pagedir_resume@l(r11)
	lwz r0,console_printk@l(r10)
	lwz r5,12(r11)
	lis r9,state3@ha
	stw r0,state3@l(r9)
	lwz r10,0(r5)
	lwz r4,56(r11)
	lis r9,origoffset@ha
	stw r10,origoffset@l(r9)
	lwz r0,0(r4)
	lis r11,copyoffset@ha
	stw r0,copyoffset@l(r11)
	lwz r10,origoffset@l(r9)
	lwz r8,copyoffset@l(r11)
	slwi r9,r10,r2
	slwi r11,r8,r2
	add r9,r9,r10
	add r11,r11,8
	lis r0,0xcccc
	ori r0,r0,52429
	slwi r9,r9,r3
	slwi r11,r11,r3
	mullw r11,r11,r0
	mullw r9,r9,r0
	slwi r11,r11,r9
	slwi r9,r9,r9
	cmpwi r0,r5,r0
	addis r9,r9,0xc000
	addis r11,r11,0xc000
	lis r7,origrange@ha
	lis r6,copyrange@ha
	lis r10,origpage@ha
	lis r8,copypage@ha
	lis r24,origrange@ha
	lis r25,copyrange@ha
	lis r12,origoffset@ha
	lis r3,copyoffset@ha
	stw r9,origpage@l(r10)
	stw r11,copypage@l(r8)
	stw r5,origrange@l(r7)
	stw r4,copyrange@l(r6)
	bc r12,r2,.L3646
	lis r4,0xcccc
	lis r28,loop@ha
	lis r26,origoffset@ha
	lis r29,origrange@ha
	lis r30,origpage@ha
	ori r4,r4,52429
	lis r27,copyoffset@ha
	lis r31,copypage@ha
.L3632:
	li r0,r0
	stw r0,loop@l(r28)
	lwz r9,loop@l(r28)
	cmplwi r0,r9,1023
	bc r12,r1,.L3637
	lis r7,loop@ha
	lis r5,origpage@ha
	lis r6,copypage@ha
.L3635:
	lwz r8,loop@l(r7)
	lwz r9,loop@l(r7)
	lwz r11,copypage@l(r6)
	slwi r9,r9,r2
	lwzx r0,r9,r11
	lwz r10,origpage@l(r5)
	slwi r8,r8,r2
	stwx r0,r8,r10
	lwz r9,loop@l(r7)
	addi r9,r9,r1
	stw r9,loop@l(r7)
	lwz r0,loop@l(r7)
	cmplwi r0,r0,1023
	bc r4,r1,.L3635
.L3637:
	lwz r11,origrange@l(r29)
	lwz r9,origoffset@l(r26)
	lwz r0,4(r11)
	cmplw r0,r9,r0
	bc r4,r0,.L3638
	lwz r9,origoffset@l(r12)
	lwz r11,origpage@l(r30)
	addi r9,r9,r1
	addi r11,r11,4096
	stw r9,origoffset@l(r12)
	stw r11,origpage@l(r30)
	b .L3639
.L3638:
	lwz r9,8(r11)
	cmpwi r0,r9,r0
	stw r9,origrange@l(r24)
	bc r12,r2,.L3639
	lwz r9,0(r9)
	stw r9,origoffset@l(r12)
	lwz r0,origoffset@l(r12)
	slwi r9,r0,r2
	add r9,r9,r0
	slwi r9,r9,r3
	mullw r9,r9,r4
	slwi r9,r9,r9
	addis r9,r9,0xc000
	stw r9,origpage@l(r30)
.L3639:
	lis r9,copyrange@ha
	lwz r9,copyrange@l(r9)
	lwz r11,copyoffset@l(r27)
	lwz r0,4(r9)
	cmplw r0,r11,r0
	bc r4,r0,.L3642
	lwz r9,copyoffset@l(r3)
	lwz r11,copypage@l(r31)
	addi r9,r9,r1
	addi r11,r11,4096
	stw r9,copyoffset@l(r3)
	stw r11,copypage@l(r31)
	b .L3630
.L3642:
	lwz r9,r8(r9)
	cmpwi r0,r9,r0
	stw r9,copyrange@l(r25)
	bc r12,r2,.L3630
	lwz r9,0(r9)
	stw r9,copyoffset@l(r3)
	lwz r0,copyoffset@l(r3)
	slwi r9,r0,r2
	add r9,r9,r0
	slwi r9,r9,r3
	mullw r9,r9,r4
	slwi r9,r9,r9
	addis r9,r9,0xc000
	stw 9,copypage@l(r31)
.L3630:
	lwz r0,origrange@l(r29)
	cmpwi r0,r0,r0
	bc r4,r2,.L3632
.L3646:
	lis r9,state1@ha
	lwz r7,state1@l(r9)
	lis r11,state2@ha
	lwz r8,state2@l(r11)
	lis r9,state3@ha
	lwz r0,state3@l(r9)
	lis r11,swsusp_action@ha
	lis r9,swsusp_debug_state@ha
	lis r10,console_printk@ha
	stw r7,swsusp_action@l(r11)
	stw r8,swsusp_debug_state@l(r9)
	stw r0,console_printk@l(r10)

#if 0
//	bl	pm_turn_off_mmu
//#else
//	mfmsr	r3
//	andi.	r0,r3,MSR_DR|MSR_IR		/* MMU enabled? */
	beqlr
	andc	r3,r3,r0
	mtspr	SRR0,r4
	mtspr	SRR1,r3
	sync
#endif

#if 0
	/* Turn off data relocation. */
	mfmsr	r3		/* Save MSR in r3 */
	rlwinm	r3,r3,0,28,26	/* Turn off DR bit */
	sync
	mtmsr	r3
	isync
#endif

#if 0	/* force supervisor */
	mfmsr   r4
	li  r3,MSR_PR   /* ensure supervisor! */
	ori r3,r3,MSR_IR|MSR_DR
	andc    r4,r4,r3
	mtmsr   r4
	isync
#endif

#if 0 /* MMU off */
	li  r3,0
	mtspr   IBAT0U,r3
	mtspr   IBAT0L,r3
	mtspr   IBAT1U,r3
	mtspr   IBAT1L,r3
	mtspr   IBAT2U,r3
	mtspr   IBAT2L,r3
	mtspr   IBAT3U,r3
	mtspr   IBAT3L,r3
	mtspr   DBAT0U,r3
	mtspr   DBAT0L,r3
	mtspr   DBAT1U,r3
	mtspr   DBAT1L,r3
	mtspr   DBAT2U,r3
	mtspr   DBAT2L,r3
	mtspr   DBAT3U,r3
	mtspr   DBAT3L,r3
#endif

#if 0
	/* Make sure HID0 no longer contains any sleep bit */
	mfspr	r3,HID0
	rlwinm	r3,r3,0,11,7		/* clear SLEEP, NAP, DOZE bits */
	mtspr	HID0,r3
	sync
	isync
#endif

#if 0
	/* Won't that cause problems on CPU that doesn't support it ? */
	lis	r3, 0
	mtspr	SPRN_MMCR0, r3
#endif

	/* sanitize MSR */
	mfmsr	r3
	ori	r3,r3,MSR_EE|MSR_IP
	xori	r3,r3,MSR_EE|MSR_IP
	sync
	isync
	mtmsr	r3
	sync
	isync

	/* Recover sleep storage */
	lis	r3,pm_sleep_storage@ha
	addi	r3,r3,pm_sleep_storage@l
	tophys(r3,r3)
	lwz	r1,0(r3)

	/* Invalidate & enable L1 cache, we don't care about
	 * whatever the ROM may have tried to write to memory
	 */
	bl	__inval_enable_L1

	/* Restore the kernel's segment registers before
	 * we do any r1 memory access as we are not sure they
	 * are in a sane state above the first 256Mb region
	 */
	li	r0,16		/* load up segment register values */
	mtctr	r0		/* for context 0 */
	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
	li	r4,0
3:	mtsrin	r3,r4
	addi	r3,r3,0x111	/* increment VSID */
	addis	r4,r4,0x1000	/* address of next segment */
	bdnz	3b
	sync
	isync

	subi	r1,r1,SL_PC
	
	/* Restore various CPU config stuffs */
	bl	__restore_cpu_setup
			
	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
	lwz	r4,SL_SDR1(r1)
	mtsdr1	r4
	lwz	r4,SL_SPRG0(r1)
	mtsprg	0,r4
	lwz	r4,SL_SPRG0+4(r1)
	mtsprg	1,r4
	lwz	r4,SL_SPRG0+8(r1)
	mtsprg	2,r4
	lwz	r4,SL_SPRG0+12(r1)
	mtsprg	3,r4

	lwz	r4,SL_DBAT0(r1)
	mtdbatu	0,r4
	lwz	r4,SL_DBAT0+4(r1)
	mtdbatl	0,r4
	lwz	r4,SL_DBAT1(r1)
	mtdbatu	1,r4
	lwz	r4,SL_DBAT1+4(r1)
	mtdbatl	1,r4
	lwz	r4,SL_DBAT2(r1)
	mtdbatu	2,r4
	lwz	r4,SL_DBAT2+4(r1)
	mtdbatl	2,r4
	lwz	r4,SL_DBAT3(r1)
	mtdbatu	3,r4
	lwz	r4,SL_DBAT3+4(r1)
	mtdbatl	3,r4
	lwz	r4,SL_IBAT0(r1)
	mtibatu	0,r4
	lwz	r4,SL_IBAT0+4(r1)
	mtibatl	0,r4
	lwz	r4,SL_IBAT1(r1)
	mtibatu	1,r4
	lwz	r4,SL_IBAT1+4(r1)
	mtibatl	1,r4
	lwz	r4,SL_IBAT2(r1)
	mtibatu	2,r4
	lwz	r4,SL_IBAT2+4(r1)
	mtibatl	2,r4
	lwz	r4,SL_IBAT3(r1)
	mtibatu	3,r4
	lwz	r4,SL_IBAT3+4(r1)
	mtibatl	3,r4

BEGIN_FTR_SECTION
	li	r4,0
	mtspr	SPRN_DBAT4U,r4
	mtspr	SPRN_DBAT4L,r4
	mtspr	SPRN_DBAT5U,r4
	mtspr	SPRN_DBAT5L,r4
	mtspr	SPRN_DBAT6U,r4
	mtspr	SPRN_DBAT6L,r4
	mtspr	SPRN_DBAT7U,r4
	mtspr	SPRN_DBAT7L,r4
	mtspr	SPRN_IBAT4U,r4
	mtspr	SPRN_IBAT4L,r4
	mtspr	SPRN_IBAT5U,r4
	mtspr	SPRN_IBAT5L,r4
	mtspr	SPRN_IBAT6U,r4
	mtspr	SPRN_IBAT6L,r4
	mtspr	SPRN_IBAT7U,r4
	mtspr	SPRN_IBAT7L,r4
END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)

	/* Flush all TLBs */
	lis	r4,0x1000
1:	addic.	r4,r4,-0x1000
	tlbie	r4
	blt	1b
	sync

	/* restore the MSR and turn on the MMU */
	lwz	r3,SL_MSR(r1)
	bl	pm_turn_on_mmu

	/* get back the stack pointer */
	tovirt(r1,r1)	

	/* Restore TB */
	li	r3,0
	mttbl	r3
	lwz	r3,SL_TB(r1)
	lwz	r4,SL_TB+4(r1)
	mttbu	r3
	mttbl	r4
	
	bl	do_swsusp2_resume_2
	
restore_stack:	
	/* Restore the callee-saved registers and return */
	lwz	r0,SL_CR(r1)
	mtcr	r0
	lwz	r2,SL_R2(r1)
	lmw	r12,SL_R12(r1)
	addi	r1,r1,SL_SIZE
	lwz	r0,4(r1)
	mtlr	r0
	blr

pm_turn_on_mmu:
	mflr	r4
	tovirt(r4,r4)
	mtsrr0	r4
	mtsrr1	r3
	sync
	isync
	rfi

pm_turn_off_mmu:
	mfmsr	r3
	andi.	r0,r3,MSR_DR|MSR_IR		/* MMU enabled? */
	beqlr
	andc	r3,r3,r0
	mtspr	SRR0,r4
	mtspr	SRR1,r3
	sync
	rfi

	.section	".data.nosave"
origrange:
	.long 0
copyrange:
	.long 0
origoffset:
	.long 0
copyoffset:
	.long 0
origpage:
	.long 0
copypage:
	.long 0
loop:
	.long 0
state1:
	.long 0
state2:
	.long 0
state3:
	.long 0
c_loops_per_jiffy_ref:
	.long 0
cpu_khz_ref:
	.long 0

	.section .data
	.balign L1_CACHE_LINE_SIZE
pm_sleep_storage:
	.long 0
	.balign L1_CACHE_LINE_SIZE,0
	
	.text

^ permalink raw reply	[flat|nested] 80+ messages in thread

* pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-23 10:30               ` Hugang
@ 2004-01-24  2:54                 ` Benjamin Herrenschmidt
  2004-01-24  5:40                   ` Hugang
                                     ` (3 more replies)
  2004-01-24  4:39                 ` Benjamin Herrenschmidt
  1 sibling, 4 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-24  2:54 UTC (permalink / raw)
  To: Hugang, Patrick Mochel
  Cc: Nigel Cunningham, ncunningham, Linux Kernel Mailing List,
	linuxppc-dev list

Ok, I hammered that for a day and got pmdisk (patrick's version) suspending
and resuming on a pismo G3 (with XFree etc.. running). Lots of rough edges
still (via-pmu sleep need to be improved, ADB need porting to the new driver
model to be properly suspended/resumed, a sysdev for RTC is needed too for
time, the asm code should be fixed for G5, etc...)

I had to fix some issues in the core pmdisk code though. One big one is that
lots of drivers expect suspend to disk to be state 4 while the current code
used state 3 for that (and suspend to RAM to be state 3 btw). I hacked that
in include/linux/suspend.h, but we shall probably just get rid of those
stupid numbers and properly define each constant indstead.

We should also use a different state for the suspend calls done before saving
the image, and the ones done before resuming the image, some driver may be
optimized for these cases.

The patch is against my tree currently, and the arch/ppc/kernel/pmdisk.S file
is appended as-is (not in patch form). I don't plan to release that right now,
I may hack a bit on it in the "background" (I want to get HIGHMEM working
some day). Feel free to improve, but then keep me informed please.

Ah, also: The "Freeing memory" phase takes forever. That should really be fixed.

Ben.

First the patch:

===== arch/ppc/Kconfig 1.60 vs edited =====
--- 1.60/arch/ppc/Kconfig	Wed Jan 21 11:29:19 2004
+++ edited/arch/ppc/Kconfig	Fri Jan 23 17:03:20 2004
@@ -913,6 +913,8 @@
 
 source "drivers/zorro/Kconfig"
 
+source kernel/power/Kconfig
+
 endmenu
 
 menu "Bus options"
===== arch/ppc/kernel/Makefile 1.61 vs edited =====
--- 1.61/arch/ppc/kernel/Makefile	Wed Jan 21 11:29:20 2004
+++ edited/arch/ppc/kernel/Makefile	Fri Jan 23 16:57:28 2004
@@ -15,6 +15,7 @@
 extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-$(CONFIG_6xx)		+= idle_6xx.o
 extra-$(CONFIG_POWER4)		+= idle_power4.o
+
 extra-y				+= vmlinux.lds.s
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
@@ -22,6 +23,7 @@
 					semaphore.o syscalls.o setup.o \
 					cputable.o ppc_htab.o
 obj-$(CONFIG_6xx)		+= l2cr.o cpu_setup_6xx.o
+obj-$(CONFIG_PM_DISK)		+= pmdisk.o
 obj-$(CONFIG_POWER4)		+= cpu_setup_power4.o
 obj-$(CONFIG_MODULES)		+= module.o ppc_ksyms.o
 obj-$(CONFIG_PCI)		+= pci.o
===== arch/ppc/kernel/signal.c 1.37 vs edited =====
--- 1.37/arch/ppc/kernel/signal.c	Fri Nov 28 12:13:45 2003
+++ edited/arch/ppc/kernel/signal.c	Fri Jan 23 18:47:07 2004
@@ -28,6 +28,7 @@
 #include <linux/elf.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
+#include <linux/suspend.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -563,6 +564,11 @@
 	struct k_sigaction *ka;
 	unsigned long frame, newsp;
 	int signr, ret;
+
+	if (current->flags & PF_FREEZE) {
+		refrigerator(0);
+		return 0;
+	}
 
 	if (!oldset)
 		oldset = &current->blocked;
===== arch/ppc/kernel/vmlinux.lds.S 1.39 vs edited =====
--- 1.39/arch/ppc/kernel/vmlinux.lds.S	Mon Nov 17 12:29:47 2003
+++ edited/arch/ppc/kernel/vmlinux.lds.S	Fri Jan 23 18:26:26 2004
@@ -72,6 +72,12 @@
     CONSTRUCTORS
   }
 
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
===== arch/ppc/platforms/pmac_setup.c 1.48 vs edited =====
--- 1.48/arch/ppc/platforms/pmac_setup.c	Sat Nov  1 12:36:52 2003
+++ edited/arch/ppc/platforms/pmac_setup.c	Fri Jan 23 18:08:18 2004
@@ -51,6 +51,7 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
+#include <linux/suspend.h>
 
 #include <asm/reg.h>
 #include <asm/sections.h>
@@ -70,6 +71,8 @@
 #include <asm/pmac_feature.h>
 #include <asm/time.h>
 #include <asm/of_device.h>
+#include <asm/mmu_context.h>
+
 #include "pmac_pic.h"
 #include "mem_pieces.h"
 
@@ -425,11 +428,65 @@
 #endif
 }
 
+/* TODO: Merge the suspend-to-ram with the common code !!!
+ * currently, this is a stub implementation for suspend-to-disk
+ * only
+ */
+
+#ifdef CONFIG_PM_DISK
+
+static int pmac_pm_prepare(u32 state)
+{
+	printk(KERN_DEBUG "pmac_pm_prepare(%d)\n", state);
+
+	return 0;
+}
+
+static int pmac_pm_enter(u32 state)
+{
+	printk(KERN_DEBUG "pmac_pm_enter(%d)\n", state);
+
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	return 0;
+}
+
+static int pmac_pm_finish(u32 state)
+{
+	printk(KERN_DEBUG "pmac_pm_finish(%d)\n", state);
+
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
+
+	return 0;
+}
+
+static struct pm_ops pmac_pm_ops = {
+	.pm_disk_mode	= PM_DISK_SHUTDOWN,
+	.prepare	= pmac_pm_prepare,
+	.enter		= pmac_pm_enter,
+	.finish		= pmac_pm_finish,
+};
+
+#endif /* CONFIG_PM_DISK */
+
 static int initializing = 1;
 
 static int pmac_late_init(void)
 {
 	initializing = 0;
+
+#ifdef CONFIG_PM_DISK
+	pm_set_ops(&pmac_pm_ops);
+#endif /* CONFIG_PM_DISK */
 	return 0;
 }
 
===== drivers/ide/ppc/pmac.c 1.47 vs edited =====
--- 1.47/drivers/ide/ppc/pmac.c	Mon Nov  3 09:30:01 2003
+++ edited/drivers/ide/ppc/pmac.c	Sat Jan 24 13:17:26 2004
@@ -1366,7 +1366,7 @@
 	ide_hwif_t	*hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
 	int		rc = 0;
 
-	if (state != mdev->ofdev.dev.power_state && state >= 2) {
+	if (state != mdev->ofdev.dev.power_state && state >= 2 && state != 4) {
 		rc = pmac_ide_do_suspend(hwif);
 		if (rc == 0)
 			mdev->ofdev.dev.power_state = state;
@@ -1469,7 +1469,7 @@
 	ide_hwif_t	*hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
 	int		rc = 0;
 	
-	if (state != pdev->dev.power_state && state >= 2) {
+	if (state != pdev->dev.power_state && state >= 2  && state != 4) {
 		rc = pmac_ide_do_suspend(hwif);
 		if (rc == 0)
 			pdev->dev.power_state = state;
===== drivers/macintosh/Kconfig 1.1 vs edited =====
--- 1.1/drivers/macintosh/Kconfig	Fri Jan  9 14:50:21 2004
+++ edited/drivers/macintosh/Kconfig	Fri Jan 23 17:03:41 2004
@@ -29,7 +29,7 @@
 
 config PMAC_PBOOK
 	bool "Power management support for PowerBooks"
-	depends on ADB_PMU
+	depends on PM && ADB_PMU
 	---help---
 	  This provides support for putting a PowerBook to sleep; it also
 	  enables media bay support.  Power management works on the
@@ -46,10 +46,10 @@
 	  have it autoloaded. The act of removing the module shuts down the
 	  sound hardware for more power savings.
 
-config PM
-	bool
-	depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK
-	default y
+#config PM
+#	bool
+#	depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK
+#	default y
 
 config PMAC_APM_EMU
 	tristate "APM emulation"
===== drivers/macintosh/mediabay.c 1.23 vs edited =====
--- 1.23/drivers/macintosh/mediabay.c	Sun Oct  5 09:22:51 2003
+++ edited/drivers/macintosh/mediabay.c	Sat Jan 24 12:49:53 2004
@@ -703,7 +703,7 @@
 {
 	struct media_bay_info	*bay = macio_get_drvdata(mdev);
 
-	if (state != mdev->ofdev.dev.power_state && state >= 2) {
+	if (state != mdev->ofdev.dev.power_state && state >= 2 && state != 4) {
 		down(&bay->lock);
 		bay->sleeping = 1;
 		set_mb_power(bay, 0);
===== drivers/macintosh/via-pmu.c 1.54 vs edited =====
--- 1.54/drivers/macintosh/via-pmu.c	Wed Nov  5 18:01:27 2003
+++ edited/drivers/macintosh/via-pmu.c	Fri Jan 23 18:17:17 2004
@@ -43,6 +43,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/sysdev.h>
 #include <linux/suspend.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
@@ -3074,6 +3075,88 @@
 	return 0;
 }
 #endif /* DEBUG_SLEEP */
+
+
+/* FIXME: This is a temporary set of callbacks to enable us
+ * to do suspend-to-disk.
+ */
+
+#ifdef CONFIG_PM
+
+static int pmu_sys_suspended = 0;
+
+static int pmu_sys_suspend(struct sys_device *sysdev, u32 state)
+{
+	if (state != PM_SUSPEND_DISK || pmu_sys_suspended)
+		return 0;
+
+	/* Suspend PMU event interrupts */
+	pmu_suspend();
+
+	pmu_sys_suspended = 1;
+	return 0;
+}
+
+static int pmu_sys_resume(struct sys_device *sysdev)
+{
+	struct adb_request req;
+
+	if (!pmu_sys_suspended)
+		return 0;
+
+	/* Tell PMU we are ready */
+	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+	pmu_wait_complete(&req);
+
+	/* Resume PMU event interrupts */
+	pmu_resume();
+
+	pmu_sys_suspended = 0;
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct sysdev_class pmu_sysclass = {
+	set_kset_name("pmu"),
+};
+
+static struct sys_device device_pmu = {
+	.id		= 0,
+	.cls		= &pmu_sysclass,
+};
+
+static struct sysdev_driver driver_pmu = {
+#ifdef CONFIG_PM
+	.suspend	= &pmu_sys_suspend,
+	.resume		= &pmu_sys_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init init_pmu_sysfs(void)
+{
+	int rc;
+
+	rc = sysdev_class_register(&pmu_sysclass);
+	if (rc) {
+		printk(KERN_ERR "Failed registering PMU sys class\n");
+		return -ENODEV;
+	}
+	rc = sys_device_register(&device_pmu);
+	if (rc) {
+		printk(KERN_ERR "Failed registering PMU sys device\n");
+		return -ENODEV;
+	}
+	rc = sysdev_driver_register(&pmu_sysclass, &driver_pmu);
+	if (rc) {
+		printk(KERN_ERR "Failed registering PMU sys driver\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+subsys_initcall(init_pmu_sysfs);
 
 EXPORT_SYMBOL(pmu_request);
 EXPORT_SYMBOL(pmu_poll);
===== drivers/video/aty/aty128fb.c 1.34 vs edited =====
--- 1.34/drivers/video/aty/aty128fb.c	Tue Oct 14 17:28:07 2003
+++ edited/drivers/video/aty/aty128fb.c	Sat Jan 24 12:49:28 2004
@@ -2251,13 +2251,16 @@
 	 * can properly take care of D3 ? Also, with swsusp, we
 	 * know we'll be rebooted, ...
 	 */
+	if (state != 2 && state != 3)
+		return 0;
+
 #ifdef CONFIG_PPC_PMAC
 	/* HACK ALERT ! Once I find a proper way to say to each driver
 	 * individually what will happen with it's PCI slot, I'll change
 	 * that. On laptops, the AGP slot is just unclocked, so D2 is
 	 * expected, while on desktops, the card is powered off
 	 */
-	if (state >= 3)
+	if (state == 3)
 		state = 2;
 #endif /* CONFIG_PPC_PMAC */
 	 
===== drivers/video/aty/radeon_pm.c 1.4 vs edited =====
--- 1.4/drivers/video/aty/radeon_pm.c	Wed Jan 21 17:00:06 2004
+++ edited/drivers/video/aty/radeon_pm.c	Fri Jan 23 18:55:16 2004
@@ -845,6 +845,8 @@
 	 */
 
 	printk(KERN_DEBUG "radeonfb: suspending to state: %d...\n", state);
+	if (state != 2 && state != 3)
+		return 0;
 	
 	acquire_console_sem();
 
===== include/linux/pm.h 1.9 vs edited =====
--- 1.9/include/linux/pm.h	Tue Aug 26 06:03:37 2003
+++ edited/include/linux/pm.h	Fri Jan 23 18:56:02 2004
@@ -195,10 +195,10 @@
 extern void (*pm_power_off)(void);
 
 enum {
-	PM_SUSPEND_ON,
-	PM_SUSPEND_STANDBY,
-	PM_SUSPEND_MEM,
-	PM_SUSPEND_DISK,
+	PM_SUSPEND_ON = 0,
+	PM_SUSPEND_STANDBY = 1,
+	PM_SUSPEND_MEM = 3,
+	PM_SUSPEND_DISK = 4,
 	PM_SUSPEND_MAX,
 };
 
===== include/linux/reboot.h 1.5 vs edited =====
--- 1.5/include/linux/reboot.h	Thu Aug  7 04:47:22 2003
+++ edited/include/linux/reboot.h	Sat Jan 24 12:31:11 2004
@@ -40,6 +40,8 @@
 extern int register_reboot_notifier(struct notifier_block *);
 extern int unregister_reboot_notifier(struct notifier_block *);
 
+/* For use by swsusp only */
+extern struct notifier_block *reboot_notifier_list;
 
 /*
  * Architecture-specific implementations of sys_reboot commands.
===== include/linux/suspend.h 1.22 vs edited =====
--- 1.22/include/linux/suspend.h	Tue Oct 14 17:28:08 2003
+++ edited/include/linux/suspend.h	Fri Jan 23 18:06:56 2004
@@ -1,9 +1,9 @@
 #ifndef _LINUX_SWSUSP_H
 #define _LINUX_SWSUSP_H
 
-#ifdef CONFIG_X86
+//#ifdef CONFIG_X86
 #include <asm/suspend.h>
-#endif
+//#endif
 #include <linux/swap.h>
 #include <linux/notifier.h>
 #include <linux/config.h>
===== kernel/sys.c 1.68 vs edited =====
--- 1.68/kernel/sys.c	Wed Jan 21 11:29:32 2004
+++ edited/kernel/sys.c	Sat Jan 24 12:30:31 2004
@@ -84,7 +84,7 @@
  *	and the like. 
  */
 
-static struct notifier_block *reboot_notifier_list;
+struct notifier_block *reboot_notifier_list;
 rwlock_t notifier_lock = RW_LOCK_UNLOCKED;
 
 /**
===== kernel/power/disk.c 1.6 vs edited =====
--- 1.6/kernel/power/disk.c	Thu Oct  2 04:52:48 2003
+++ edited/kernel/power/disk.c	Sat Jan 24 12:31:31 2004
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
+#include <linux/reboot.h>
 #include "power.h"
 
 
@@ -46,23 +47,26 @@
 	unsigned long flags;
 	int error = 0;
 
-	local_irq_save(flags);
-	device_power_down(PM_SUSPEND_DISK);
 	switch(mode) {
 	case PM_DISK_PLATFORM:
+		local_irq_save(flags);
 		error = pm_ops->enter(PM_SUSPEND_DISK);
+		local_irq_restore(flags);
 		break;
 	case PM_DISK_SHUTDOWN:
 		printk("Powering off system\n");
+		notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
+		device_shutdown();
 		machine_power_off();
 		break;
 	case PM_DISK_REBOOT:
+		printk("Rebooting system\n");
+		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+		device_shutdown();
 		machine_restart(NULL);
 		break;
 	}
 	machine_halt();
-	device_power_up();
-	local_irq_restore(flags);
 	return 0;
 }
 
@@ -163,8 +167,10 @@
 
 	pr_debug("PM: snapshotting memory.\n");
 	in_suspend = 1;
-	if ((error = pmdisk_save()))
+	if ((error = pmdisk_save())) {
+		pr_debug("PM: snapshot memory failed !\n");
 		goto Done;
+	}
 
 	if (in_suspend) {
 		pr_debug("PM: writing image.\n");
@@ -225,9 +231,6 @@
 	 * Do it with disabled interrupts for best effect. That way, if some
 	 * driver scheduled DMA, we have good chance for DMA to finish ;-).
 	 */
-	pr_debug("PM: Waiting for DMAs to settle down.\n");
-	mdelay(1000);
-
 	pr_debug("PM: Restoring saved image.\n");
 	pmdisk_restore();
 	pr_debug("PM: Restore failed, recovering.n");
===== kernel/power/main.c 1.16 vs edited =====
--- 1.16/kernel/power/main.c	Tue Sep  9 08:13:46 2003
+++ edited/kernel/power/main.c	Fri Jan 23 19:27:16 2004
@@ -120,6 +120,7 @@
 
 char * pm_states[] = {
 	[PM_SUSPEND_STANDBY]	= "standby",
+	[2]			= "",
 	[PM_SUSPEND_MEM]	= "mem",
 	[PM_SUSPEND_DISK]	= "disk",
 	NULL,
===== kernel/power/pmdisk.c 1.80 vs edited =====
--- 1.80/kernel/power/pmdisk.c	Thu Oct  2 04:52:48 2003
+++ edited/kernel/power/pmdisk.c	Sat Jan 24 13:52:30 2004
@@ -18,7 +18,7 @@
  *
  */
 
-#undef DEBUG
+#define DEBUG
 
 #include <linux/mm.h>
 #include <linux/bio.h>
@@ -28,6 +28,7 @@
 #include <linux/device.h>
 #include <linux/swapops.h>
 #include <linux/bootmem.h>
+#include <linux/utsname.h>
 
 #include <asm/mmu_context.h>
 
@@ -624,8 +625,10 @@
 {
 	int error = 0;
 
-	if ((error = read_swapfiles()))
+	if ((error = read_swapfiles())) {
+		printk("Can't read swapfiles\n");
 		return error;
+	}
 
 	drain_local_pages();
 
@@ -702,6 +705,7 @@
  * Magic happens here
  */
 
+#if 0
 int pmdisk_resume(void)
 {
 	BUG_ON (nr_copy_pages_check != pmdisk_pages);
@@ -711,6 +715,7 @@
 	__flush_tlb_global();
 	return 0;
 }
+#endif
 
 /* pmdisk_arch_suspend() is implemented in arch/?/power/pmdisk.S,
    and basically does:
@@ -1082,9 +1087,11 @@
 	if ((error = arch_prepare_suspend()))
 		return error;
 	local_irq_disable();
+	device_power_down(PM_SUSPEND_DISK);
 	save_processor_state();
 	error = pmdisk_arch_suspend(0);
 	restore_processor_state();
+	device_power_up();
 	local_irq_enable();
 	return error;
 }
@@ -1143,10 +1150,13 @@
 int __init pmdisk_restore(void)
 {
 	int error;
+
 	local_irq_disable();
+	device_power_down(PM_SUSPEND_DISK);
 	save_processor_state();
 	error = pmdisk_arch_suspend(1);
 	restore_processor_state();
+	device_power_up();
 	local_irq_enable();
 	return error;
 }

Then the arch/ppc/kernel/pmdisk.S file:

#include <linux/config.h>
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/offsets.h>


/*
 * Structure for storing CPU registers on the save area.
 */
#define SL_SP		0
#define SL_PC		4
#define SL_MSR		8
#define SL_SDR1		0xc
#define SL_SPRG0	0x10	/* 4 sprg's */
#define SL_DBAT0	0x20
#define SL_IBAT0	0x28
#define SL_DBAT1	0x30
#define SL_IBAT1	0x38
#define SL_DBAT2	0x40
#define SL_IBAT2	0x48
#define SL_DBAT3	0x50
#define SL_IBAT3	0x58
#define SL_TB		0x60
#define SL_R2		0x68
#define SL_CR		0x6c
#define SL_LR		0x70
#define SL_R12		0x74	/* r12 to r31 */
#define SL_SIZE		(SL_R12 + 80)

	.section .data
	.align	5

_GLOBAL(pmdisk_save_area)
	.space	SL_SIZE


	.section .text
	.align	5

_GLOBAL(pmdisk_arch_suspend)
	cmpi	0,r3,0
	bne	do_resume

	lis	r11,pmdisk_save_area@h
	ori	r11,r11,pmdisk_save_area@l

	mflr	r0
	stw	r0,SL_LR(r11)
	mfcr	r0
	stw	r0,SL_CR(r11)
	stw	r1,SL_SP(r11)
	stw	r2,SL_R2(r11)
	stmw	r12,SL_R12(r11)

	/* Save MSR & SDR1 */
	mfmsr	r4
	stw	r4,SL_MSR(r11)
	mfsdr1	r4
	stw	r4,SL_SDR1(r11)

	/* Get a stable timebase and save it */
1:	mftbu	r4
	stw	r4,SL_TB(r11)
	mftb	r5
	stw	r5,SL_TB+4(r11)
	mftbu	r3
	cmpw	r3,r4
	bne	1b

	/* Save SPRGs */
	mfsprg	r4,0
	stw	r4,SL_SPRG0(r11)
	mfsprg	r4,1
	stw	r4,SL_SPRG0+4(r11)
	mfsprg	r4,2
	stw	r4,SL_SPRG0+8(r11)
	mfsprg	r4,3
	stw	r4,SL_SPRG0+12(r11)

	/* Save BATs */
	mfdbatu	r4,0
	stw	r4,SL_DBAT0(r11)
	mfdbatl	r4,0
	stw	r4,SL_DBAT0+4(r11)
	mfdbatu	r4,1
	stw	r4,SL_DBAT1(r11)
	mfdbatl	r4,1
	stw	r4,SL_DBAT1+4(r11)
	mfdbatu	r4,2
	stw	r4,SL_DBAT2(r11)
	mfdbatl	r4,2
	stw	r4,SL_DBAT2+4(r11)
	mfdbatu	r4,3
	stw	r4,SL_DBAT3(r11)
	mfdbatl	r4,3
	stw	r4,SL_DBAT3+4(r11)
	mfibatu	r4,0
	stw	r4,SL_IBAT0(r11)
	mfibatl	r4,0
	stw	r4,SL_IBAT0+4(r11)
	mfibatu	r4,1
	stw	r4,SL_IBAT1(r11)
	mfibatl	r4,1
	stw	r4,SL_IBAT1+4(r11)
	mfibatu	r4,2
	stw	r4,SL_IBAT2(r11)
	mfibatl	r4,2
	stw	r4,SL_IBAT2+4(r11)
	mfibatu	r4,3
	stw	r4,SL_IBAT3(r11)
	mfibatl	r4,3
	stw	r4,SL_IBAT3+4(r11)

#if  0
	/* Backup various CPU config stuffs */
	bl	__save_cpu_setup
#endif
	/* Call the low level suspend stuff (we should probably have made
	 * a stackframe...
	 */
	bl	pmdisk_suspend
	
	/* Restore LR from the save area */
	lis	r11,pmdisk_save_area@h
	ori	r11,r11,pmdisk_save_area@l
	lwz	r0,SL_LR(r11)
	mtlr	r0

	blr


/* Resume code */	
do_resume:

	/* Stop pending alitvec streams and memory accesses */
BEGIN_FTR_SECTION
	DSSALL
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	sync

	/* Disable MSR:DR to make sure we don't take a TLB or
	 * hash miss during the copy, as our hash table will
	 * for a while be unuseable. For .text, we assume we are
	 * covered by a BAT. This works only for non-G5 at this
	 * point. G5 will need a better approach, possibly using
	 * a small temporary hash table filled with large mappings,
	 * disabling the MMU completely isn't a good option for
	 * performance reasons.
	 * (Note that 750's may have the same performance issue as
	 * the G5 in this case, we should investigate using moving
	 * BATs for these CPUs)
	 */
	mfmsr	r0
	sync
	rlwinm	r0,r0,0,28,26		/* clear MSR_DR */
	mtmsr	r0
	sync
	isync

	/* Load ptr the list of pages to copy in r3 */
	lis	r11,(pm_pagedir_nosave - KERNELBASE)@h
	ori	r11,r11,pm_pagedir_nosave@l
	lwz	r10,0(r11)
	tophys(r3,r10)

	/* Load the count of pages to copy in r4 */
	lis	r11,(pmdisk_pages - KERNELBASE)@h
	ori	r11,r11,pmdisk_pages@l
	lwz	r4,0(r11)
	

	/* Copy the pages. This is a very basic implementation, to
	 * be replaced by something more cache efficient */
1:
	li	r0,256
	mtctr	r0
	lwz	r11,0(r3)	/* source */
	tophys(r5,r11)
	lwz	r10,4(r3)	/* destination */
	tophys(r6,r10)
2:
	lwz	r8,0(r5)
	lwz	r9,4(r5)
	lwz	r10,8(r5)
	lwz	r11,12(r5)
	addi	r5,r5,16
	stw	r8,0(r6)
	stw	r9,4(r6)
	stw	r10,8(r6)
	stw	r11,12(r6)
	addi	r6,r6,16
	bdnz	2b
	addi	r3,r3,16
	subi	r4,r4,1
	cmpwi	0,r4,0
	bne	1b
	
	/* Do a very simple cache flush/inval of the L1 to ensure
	 * coherency of the icache
	 */
	lis	r3,0x0002
	mtctr	r3
	li	r3, 0
1:
	lwz	r0,0(r3)
	addi	r3,r3,0x0020
	bdnz	1b
	isync
	sync

	/* Now flush those cache lines */
	lis	r3,0x0002
	mtctr	r3
	li	r3, 0
1:
	dcbf	0,r3
	addi	r3,r3,0x0020
	bdnz	1b
	sync

	/* Ok, we are now running with the kernel data of the old
	 * kernel fully restored. We can get to the save area
	 * easily now. As for the rest of the code, it assumes the
	 * loader kernel and the booted one are exactly identical
	 */
	lis	r11,pmdisk_save_area@h
	ori	r11,r11,pmdisk_save_area@l
	tophys(r11,r11)
	
#if 0
	/* Restore various CPU config stuffs */
	bl	__restore_cpu_setup
#endif
	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. 
	 * This is a bit hairy as we are running out of those BATs,
	 * but first, our code is probably in the icache, and we are
	 * writing the same value to the BAT, so that should be fine,
	 * though a better solution will have to be found long-term
	 */
	lwz	r4,SL_SDR1(r11)
	mtsdr1	r4
	lwz	r4,SL_SPRG0(r11)
	mtsprg	0,r4
	lwz	r4,SL_SPRG0+4(r11)
	mtsprg	1,r4
	lwz	r4,SL_SPRG0+8(r11)
	mtsprg	2,r4
	lwz	r4,SL_SPRG0+12(r11)
	mtsprg	3,r4

#if 0
	lwz	r4,SL_DBAT0(r11)
	mtdbatu	0,r4
	lwz	r4,SL_DBAT0+4(r11)
	mtdbatl	0,r4
	lwz	r4,SL_DBAT1(r11)
	mtdbatu	1,r4
	lwz	r4,SL_DBAT1+4(r11)
	mtdbatl	1,r4
	lwz	r4,SL_DBAT2(r11)
	mtdbatu	2,r4
	lwz	r4,SL_DBAT2+4(r11)
	mtdbatl	2,r4
	lwz	r4,SL_DBAT3(r11)
	mtdbatu	3,r4
	lwz	r4,SL_DBAT3+4(r11)
	mtdbatl	3,r4
	lwz	r4,SL_IBAT0(r11)
	mtibatu	0,r4
	lwz	r4,SL_IBAT0+4(r11)
	mtibatl	0,r4
	lwz	r4,SL_IBAT1(r11)
	mtibatu	1,r4
	lwz	r4,SL_IBAT1+4(r11)
	mtibatl	1,r4
	lwz	r4,SL_IBAT2(r11)
	mtibatu	2,r4
	lwz	r4,SL_IBAT2+4(r11)
	mtibatl	2,r4
	lwz	r4,SL_IBAT3(r11)
	mtibatu	3,r4
	lwz	r4,SL_IBAT3+4(r11)
	mtibatl	3,r4
#endif

BEGIN_FTR_SECTION
	li	r4,0
	mtspr	SPRN_DBAT4U,r4
	mtspr	SPRN_DBAT4L,r4
	mtspr	SPRN_DBAT5U,r4
	mtspr	SPRN_DBAT5L,r4
	mtspr	SPRN_DBAT6U,r4
	mtspr	SPRN_DBAT6L,r4
	mtspr	SPRN_DBAT7U,r4
	mtspr	SPRN_DBAT7L,r4
	mtspr	SPRN_IBAT4U,r4
	mtspr	SPRN_IBAT4L,r4
	mtspr	SPRN_IBAT5U,r4
	mtspr	SPRN_IBAT5L,r4
	mtspr	SPRN_IBAT6U,r4
	mtspr	SPRN_IBAT6L,r4
	mtspr	SPRN_IBAT7U,r4
	mtspr	SPRN_IBAT7L,r4
END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)

	/* Flush all TLBs */
	lis	r4,0x1000
1:	addic.	r4,r4,-0x1000
	tlbie	r4
	blt	1b
	sync

	/* restore the MSR and turn on the MMU */
	lwz	r3,SL_MSR(r11)
	bl	turn_on_mmu
	tovirt(r11,r11)

	/* Restore TB */
	li	r3,0
	mttbl	r3
	lwz	r3,SL_TB(r11)
	lwz	r4,SL_TB+4(r11)
	mttbu	r3
	mttbl	r4

	/* Kick decrementer */
	li	r0,1
	mtdec	r0

	/* Restore the callee-saved registers and return */
	lwz	r0,SL_CR(r11)
	mtcr	r0
	lwz	r2,SL_R2(r11)
	lmw	r12,SL_R12(r11)
	lwz	r1,SL_SP(r11)
	lwz	r0,SL_LR(r11)
	mtlr	r0

	// XXX Note: we don't really need to call pmdisk_resume

	li	r3,0
	blr

/* FIXME:This construct is actually not useful since we don't shut
 * down the instruction MMU, we could just flip back MSR-DR on.
 */
turn_on_mmu:
	mflr	r4
	mtsrr0	r4
	mtsrr1	r3
	sync
	isync
	rfi



^ permalink raw reply	[flat|nested] 80+ messages in thread

* pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-23 10:30               ` Hugang
  2004-01-24  2:54                 ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
@ 2004-01-24  4:39                 ` Benjamin Herrenschmidt
  2004-01-24  7:20                   ` Pavel Machek
  1 sibling, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-24  4:39 UTC (permalink / raw)
  To: Patrick Mochel, Pavel Machek, Nigel Cunningham
  Cc: linuxppc-dev list, Linux Kernel list, Hugang

(RESENT, sorry if you got it already, something apparently went wrong
on the SMTP here)

Ok, I hammered that for a day and got pmdisk (patrick's version) suspending
and resuming on a pismo G3 (with XFree etc.. running). Lots of rough edges
still (via-pmu sleep need to be improved, ADB need porting to the new driver
model to be properly suspended/resumed, a sysdev for RTC is needed too for
time, the asm code should be fixed for G5, etc...)

I had to fix some issues in the core pmdisk code though. One big one is that
lots of drivers expect suspend to disk to be state 4 while the current code
used state 3 for that (and suspend to RAM to be state 3 btw). I hacked that
in include/linux/suspend.h, but we shall probably just get rid of those
stupid numbers and properly define each constant indstead.

We should also use a different state for the suspend calls done before saving
the image, and the ones done before resuming the image, some driver may be
optimized for these cases.

The patch is against my tree currently, and the arch/ppc/kernel/pmdisk.S file
is appended as-is (not in patch form). I don't plan to release that right now,
I may hack a bit on it in the "background" (I want to get HIGHMEM working
some day). Feel free to improve, but then keep me informed please.

Ah, also: The "Freeing memory" phase takes forever. That should really be fixed.

Ben.

First the patch:

===== arch/ppc/Kconfig 1.60 vs edited =====
--- 1.60/arch/ppc/Kconfig	Wed Jan 21 11:29:19 2004
+++ edited/arch/ppc/Kconfig	Fri Jan 23 17:03:20 2004
@@ -913,6 +913,8 @@
 
 source "drivers/zorro/Kconfig"
 
+source kernel/power/Kconfig
+
 endmenu
 
 menu "Bus options"
===== arch/ppc/kernel/Makefile 1.61 vs edited =====
--- 1.61/arch/ppc/kernel/Makefile	Wed Jan 21 11:29:20 2004
+++ edited/arch/ppc/kernel/Makefile	Fri Jan 23 16:57:28 2004
@@ -15,6 +15,7 @@
 extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-$(CONFIG_6xx)		+= idle_6xx.o
 extra-$(CONFIG_POWER4)		+= idle_power4.o
+
 extra-y				+= vmlinux.lds.s
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
@@ -22,6 +23,7 @@
 					semaphore.o syscalls.o setup.o \
 					cputable.o ppc_htab.o
 obj-$(CONFIG_6xx)		+= l2cr.o cpu_setup_6xx.o
+obj-$(CONFIG_PM_DISK)		+= pmdisk.o
 obj-$(CONFIG_POWER4)		+= cpu_setup_power4.o
 obj-$(CONFIG_MODULES)		+= module.o ppc_ksyms.o
 obj-$(CONFIG_PCI)		+= pci.o
===== arch/ppc/kernel/signal.c 1.37 vs edited =====
--- 1.37/arch/ppc/kernel/signal.c	Fri Nov 28 12:13:45 2003
+++ edited/arch/ppc/kernel/signal.c	Fri Jan 23 18:47:07 2004
@@ -28,6 +28,7 @@
 #include <linux/elf.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
+#include <linux/suspend.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -563,6 +564,11 @@
 	struct k_sigaction *ka;
 	unsigned long frame, newsp;
 	int signr, ret;
+
+	if (current->flags & PF_FREEZE) {
+		refrigerator(0);
+		return 0;
+	}
 
 	if (!oldset)
 		oldset = &current->blocked;
===== arch/ppc/kernel/vmlinux.lds.S 1.39 vs edited =====
--- 1.39/arch/ppc/kernel/vmlinux.lds.S	Mon Nov 17 12:29:47 2003
+++ edited/arch/ppc/kernel/vmlinux.lds.S	Fri Jan 23 18:26:26 2004
@@ -72,6 +72,12 @@
     CONSTRUCTORS
   }
 
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
===== arch/ppc/platforms/pmac_setup.c 1.48 vs edited =====
--- 1.48/arch/ppc/platforms/pmac_setup.c	Sat Nov  1 12:36:52 2003
+++ edited/arch/ppc/platforms/pmac_setup.c	Fri Jan 23 18:08:18 2004
@@ -51,6 +51,7 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
+#include <linux/suspend.h>
 
 #include <asm/reg.h>
 #include <asm/sections.h>
@@ -70,6 +71,8 @@
 #include <asm/pmac_feature.h>
 #include <asm/time.h>
 #include <asm/of_device.h>
+#include <asm/mmu_context.h>
+
 #include "pmac_pic.h"
 #include "mem_pieces.h"
 
@@ -425,11 +428,65 @@
 #endif
 }
 
+/* TODO: Merge the suspend-to-ram with the common code !!!
+ * currently, this is a stub implementation for suspend-to-disk
+ * only
+ */
+
+#ifdef CONFIG_PM_DISK
+
+static int pmac_pm_prepare(u32 state)
+{
+	printk(KERN_DEBUG "pmac_pm_prepare(%d)\n", state);
+
+	return 0;
+}
+
+static int pmac_pm_enter(u32 state)
+{
+	printk(KERN_DEBUG "pmac_pm_enter(%d)\n", state);
+
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	return 0;
+}
+
+static int pmac_pm_finish(u32 state)
+{
+	printk(KERN_DEBUG "pmac_pm_finish(%d)\n", state);
+
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
+
+	return 0;
+}
+
+static struct pm_ops pmac_pm_ops = {
+	.pm_disk_mode	= PM_DISK_SHUTDOWN,
+	.prepare	= pmac_pm_prepare,
+	.enter		= pmac_pm_enter,
+	.finish		= pmac_pm_finish,
+};
+
+#endif /* CONFIG_PM_DISK */
+
 static int initializing = 1;
 
 static int pmac_late_init(void)
 {
 	initializing = 0;
+
+#ifdef CONFIG_PM_DISK
+	pm_set_ops(&pmac_pm_ops);
+#endif /* CONFIG_PM_DISK */
 	return 0;
 }
 
===== drivers/ide/ppc/pmac.c 1.47 vs edited =====
--- 1.47/drivers/ide/ppc/pmac.c	Mon Nov  3 09:30:01 2003
+++ edited/drivers/ide/ppc/pmac.c	Sat Jan 24 13:17:26 2004
@@ -1366,7 +1366,7 @@
 	ide_hwif_t	*hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
 	int		rc = 0;
 
-	if (state != mdev->ofdev.dev.power_state && state >= 2) {
+	if (state != mdev->ofdev.dev.power_state && state >= 2 && state != 4) {
 		rc = pmac_ide_do_suspend(hwif);
 		if (rc == 0)
 			mdev->ofdev.dev.power_state = state;
@@ -1469,7 +1469,7 @@
 	ide_hwif_t	*hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
 	int		rc = 0;
 	
-	if (state != pdev->dev.power_state && state >= 2) {
+	if (state != pdev->dev.power_state && state >= 2  && state != 4) {
 		rc = pmac_ide_do_suspend(hwif);
 		if (rc == 0)
 			pdev->dev.power_state = state;
===== drivers/macintosh/Kconfig 1.1 vs edited =====
--- 1.1/drivers/macintosh/Kconfig	Fri Jan  9 14:50:21 2004
+++ edited/drivers/macintosh/Kconfig	Fri Jan 23 17:03:41 2004
@@ -29,7 +29,7 @@
 
 config PMAC_PBOOK
 	bool "Power management support for PowerBooks"
-	depends on ADB_PMU
+	depends on PM && ADB_PMU
 	---help---
 	  This provides support for putting a PowerBook to sleep; it also
 	  enables media bay support.  Power management works on the
@@ -46,10 +46,10 @@
 	  have it autoloaded. The act of removing the module shuts down the
 	  sound hardware for more power savings.
 
-config PM
-	bool
-	depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK
-	default y
+#config PM
+#	bool
+#	depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK
+#	default y
 
 config PMAC_APM_EMU
 	tristate "APM emulation"
===== drivers/macintosh/mediabay.c 1.23 vs edited =====
--- 1.23/drivers/macintosh/mediabay.c	Sun Oct  5 09:22:51 2003
+++ edited/drivers/macintosh/mediabay.c	Sat Jan 24 12:49:53 2004
@@ -703,7 +703,7 @@
 {
 	struct media_bay_info	*bay = macio_get_drvdata(mdev);
 
-	if (state != mdev->ofdev.dev.power_state && state >= 2) {
+	if (state != mdev->ofdev.dev.power_state && state >= 2 && state != 4) {
 		down(&bay->lock);
 		bay->sleeping = 1;
 		set_mb_power(bay, 0);
===== drivers/macintosh/via-pmu.c 1.54 vs edited =====
--- 1.54/drivers/macintosh/via-pmu.c	Wed Nov  5 18:01:27 2003
+++ edited/drivers/macintosh/via-pmu.c	Fri Jan 23 18:17:17 2004
@@ -43,6 +43,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/sysdev.h>
 #include <linux/suspend.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
@@ -3074,6 +3075,88 @@
 	return 0;
 }
 #endif /* DEBUG_SLEEP */
+
+
+/* FIXME: This is a temporary set of callbacks to enable us
+ * to do suspend-to-disk.
+ */
+
+#ifdef CONFIG_PM
+
+static int pmu_sys_suspended = 0;
+
+static int pmu_sys_suspend(struct sys_device *sysdev, u32 state)
+{
+	if (state != PM_SUSPEND_DISK || pmu_sys_suspended)
+		return 0;
+
+	/* Suspend PMU event interrupts */
+	pmu_suspend();
+
+	pmu_sys_suspended = 1;
+	return 0;
+}
+
+static int pmu_sys_resume(struct sys_device *sysdev)
+{
+	struct adb_request req;
+
+	if (!pmu_sys_suspended)
+		return 0;
+
+	/* Tell PMU we are ready */
+	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+	pmu_wait_complete(&req);
+
+	/* Resume PMU event interrupts */
+	pmu_resume();
+
+	pmu_sys_suspended = 0;
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct sysdev_class pmu_sysclass = {
+	set_kset_name("pmu"),
+};
+
+static struct sys_device device_pmu = {
+	.id		= 0,
+	.cls		= &pmu_sysclass,
+};
+
+static struct sysdev_driver driver_pmu = {
+#ifdef CONFIG_PM
+	.suspend	= &pmu_sys_suspend,
+	.resume		= &pmu_sys_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init init_pmu_sysfs(void)
+{
+	int rc;
+
+	rc = sysdev_class_register(&pmu_sysclass);
+	if (rc) {
+		printk(KERN_ERR "Failed registering PMU sys class\n");
+		return -ENODEV;
+	}
+	rc = sys_device_register(&device_pmu);
+	if (rc) {
+		printk(KERN_ERR "Failed registering PMU sys device\n");
+		return -ENODEV;
+	}
+	rc = sysdev_driver_register(&pmu_sysclass, &driver_pmu);
+	if (rc) {
+		printk(KERN_ERR "Failed registering PMU sys driver\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+subsys_initcall(init_pmu_sysfs);
 
 EXPORT_SYMBOL(pmu_request);
 EXPORT_SYMBOL(pmu_poll);
===== drivers/video/aty/aty128fb.c 1.34 vs edited =====
--- 1.34/drivers/video/aty/aty128fb.c	Tue Oct 14 17:28:07 2003
+++ edited/drivers/video/aty/aty128fb.c	Sat Jan 24 12:49:28 2004
@@ -2251,13 +2251,16 @@
 	 * can properly take care of D3 ? Also, with swsusp, we
 	 * know we'll be rebooted, ...
 	 */
+	if (state != 2 && state != 3)
+		return 0;
+
 #ifdef CONFIG_PPC_PMAC
 	/* HACK ALERT ! Once I find a proper way to say to each driver
 	 * individually what will happen with it's PCI slot, I'll change
 	 * that. On laptops, the AGP slot is just unclocked, so D2 is
 	 * expected, while on desktops, the card is powered off
 	 */
-	if (state >= 3)
+	if (state == 3)
 		state = 2;
 #endif /* CONFIG_PPC_PMAC */
 	 
===== drivers/video/aty/radeon_pm.c 1.4 vs edited =====
--- 1.4/drivers/video/aty/radeon_pm.c	Wed Jan 21 17:00:06 2004
+++ edited/drivers/video/aty/radeon_pm.c	Fri Jan 23 18:55:16 2004
@@ -845,6 +845,8 @@
 	 */
 
 	printk(KERN_DEBUG "radeonfb: suspending to state: %d...\n", state);
+	if (state != 2 && state != 3)
+		return 0;
 	
 	acquire_console_sem();
 
===== include/linux/pm.h 1.9 vs edited =====
--- 1.9/include/linux/pm.h	Tue Aug 26 06:03:37 2003
+++ edited/include/linux/pm.h	Fri Jan 23 18:56:02 2004
@@ -195,10 +195,10 @@
 extern void (*pm_power_off)(void);
 
 enum {
-	PM_SUSPEND_ON,
-	PM_SUSPEND_STANDBY,
-	PM_SUSPEND_MEM,
-	PM_SUSPEND_DISK,
+	PM_SUSPEND_ON = 0,
+	PM_SUSPEND_STANDBY = 1,
+	PM_SUSPEND_MEM = 3,
+	PM_SUSPEND_DISK = 4,
 	PM_SUSPEND_MAX,
 };
 
===== include/linux/reboot.h 1.5 vs edited =====
--- 1.5/include/linux/reboot.h	Thu Aug  7 04:47:22 2003
+++ edited/include/linux/reboot.h	Sat Jan 24 12:31:11 2004
@@ -40,6 +40,8 @@
 extern int register_reboot_notifier(struct notifier_block *);
 extern int unregister_reboot_notifier(struct notifier_block *);
 
+/* For use by swsusp only */
+extern struct notifier_block *reboot_notifier_list;
 
 /*
  * Architecture-specific implementations of sys_reboot commands.
===== include/linux/suspend.h 1.22 vs edited =====
--- 1.22/include/linux/suspend.h	Tue Oct 14 17:28:08 2003
+++ edited/include/linux/suspend.h	Fri Jan 23 18:06:56 2004
@@ -1,9 +1,9 @@
 #ifndef _LINUX_SWSUSP_H
 #define _LINUX_SWSUSP_H
 
-#ifdef CONFIG_X86
+//#ifdef CONFIG_X86
 #include <asm/suspend.h>
-#endif
+//#endif
 #include <linux/swap.h>
 #include <linux/notifier.h>
 #include <linux/config.h>
===== kernel/sys.c 1.68 vs edited =====
--- 1.68/kernel/sys.c	Wed Jan 21 11:29:32 2004
+++ edited/kernel/sys.c	Sat Jan 24 12:30:31 2004
@@ -84,7 +84,7 @@
  *	and the like. 
  */
 
-static struct notifier_block *reboot_notifier_list;
+struct notifier_block *reboot_notifier_list;
 rwlock_t notifier_lock = RW_LOCK_UNLOCKED;
 
 /**
===== kernel/power/disk.c 1.6 vs edited =====
--- 1.6/kernel/power/disk.c	Thu Oct  2 04:52:48 2003
+++ edited/kernel/power/disk.c	Sat Jan 24 12:31:31 2004
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
+#include <linux/reboot.h>
 #include "power.h"
 

@@ -46,23 +47,26 @@
 	unsigned long flags;
 	int error = 0;
 
-	local_irq_save(flags);
-	device_power_down(PM_SUSPEND_DISK);
 	switch(mode) {
 	case PM_DISK_PLATFORM:
+		local_irq_save(flags);
 		error = pm_ops->enter(PM_SUSPEND_DISK);
+		local_irq_restore(flags);
 		break;
 	case PM_DISK_SHUTDOWN:
 		printk("Powering off system\n");
+		notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
+		device_shutdown();
 		machine_power_off();
 		break;
 	case PM_DISK_REBOOT:
+		printk("Rebooting system\n");
+		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+		device_shutdown();
 		machine_restart(NULL);
 		break;
 	}
 	machine_halt();
-	device_power_up();
-	local_irq_restore(flags);
 	return 0;
 }
 
@@ -163,8 +167,10 @@
 
 	pr_debug("PM: snapshotting memory.\n");
 	in_suspend = 1;
-	if ((error = pmdisk_save()))
+	if ((error = pmdisk_save())) {
+		pr_debug("PM: snapshot memory failed !\n");
 		goto Done;
+	}
 
 	if (in_suspend) {
 		pr_debug("PM: writing image.\n");
@@ -225,9 +231,6 @@
 	 * Do it with disabled interrupts for best effect. That way, if some
 	 * driver scheduled DMA, we have good chance for DMA to finish ;-).
 	 */
-	pr_debug("PM: Waiting for DMAs to settle down.\n");
-	mdelay(1000);
-
 	pr_debug("PM: Restoring saved image.\n");
 	pmdisk_restore();
 	pr_debug("PM: Restore failed, recovering.n");
===== kernel/power/main.c 1.16 vs edited =====
--- 1.16/kernel/power/main.c	Tue Sep  9 08:13:46 2003
+++ edited/kernel/power/main.c	Fri Jan 23 19:27:16 2004
@@ -120,6 +120,7 @@
 
 char * pm_states[] = {
 	[PM_SUSPEND_STANDBY]	= "standby",
+	[2]			= "",
 	[PM_SUSPEND_MEM]	= "mem",
 	[PM_SUSPEND_DISK]	= "disk",
 	NULL,
===== kernel/power/pmdisk.c 1.80 vs edited =====
--- 1.80/kernel/power/pmdisk.c	Thu Oct  2 04:52:48 2003
+++ edited/kernel/power/pmdisk.c	Sat Jan 24 13:52:30 2004
@@ -18,7 +18,7 @@
  *
  */
 
-#undef DEBUG
+#define DEBUG
 
 #include <linux/mm.h>
 #include <linux/bio.h>
@@ -28,6 +28,7 @@
 #include <linux/device.h>
 #include <linux/swapops.h>
 #include <linux/bootmem.h>
+#include <linux/utsname.h>
 
 #include <asm/mmu_context.h>
 
@@ -624,8 +625,10 @@
 {
 	int error = 0;
 
-	if ((error = read_swapfiles()))
+	if ((error = read_swapfiles())) {
+		printk("Can't read swapfiles\n");
 		return error;
+	}
 
 	drain_local_pages();
 
@@ -702,6 +705,7 @@
  * Magic happens here
  */
 
+#if 0
 int pmdisk_resume(void)
 {
 	BUG_ON (nr_copy_pages_check != pmdisk_pages);
@@ -711,6 +715,7 @@
 	__flush_tlb_global();
 	return 0;
 }
+#endif
 
 /* pmdisk_arch_suspend() is implemented in arch/?/power/pmdisk.S,
    and basically does:
@@ -1082,9 +1087,11 @@
 	if ((error = arch_prepare_suspend()))
 		return error;
 	local_irq_disable();
+	device_power_down(PM_SUSPEND_DISK);
 	save_processor_state();
 	error = pmdisk_arch_suspend(0);
 	restore_processor_state();
+	device_power_up();
 	local_irq_enable();
 	return error;
 }
@@ -1143,10 +1150,13 @@
 int __init pmdisk_restore(void)
 {
 	int error;
+
 	local_irq_disable();
+	device_power_down(PM_SUSPEND_DISK);
 	save_processor_state();
 	error = pmdisk_arch_suspend(1);
 	restore_processor_state();
+	device_power_up();
 	local_irq_enable();
 	return error;
 }

Then the arch/ppc/kernel/pmdisk.S file:

#include <linux/config.h>
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/offsets.h>


/*
 * Structure for storing CPU registers on the save area.
 */
#define SL_SP		0
#define SL_PC		4
#define SL_MSR		8
#define SL_SDR1		0xc
#define SL_SPRG0	0x10	/* 4 sprg's */
#define SL_DBAT0	0x20
#define SL_IBAT0	0x28
#define SL_DBAT1	0x30
#define SL_IBAT1	0x38
#define SL_DBAT2	0x40
#define SL_IBAT2	0x48
#define SL_DBAT3	0x50
#define SL_IBAT3	0x58
#define SL_TB		0x60
#define SL_R2		0x68
#define SL_CR		0x6c
#define SL_LR		0x70
#define SL_R12		0x74	/* r12 to r31 */
#define SL_SIZE		(SL_R12 + 80)

	.section .data
	.align	5

_GLOBAL(pmdisk_save_area)
	.space	SL_SIZE


	.section .text
	.align	5

_GLOBAL(pmdisk_arch_suspend)
	cmpi	0,r3,0
	bne	do_resume

	lis	r11,pmdisk_save_area@h
	ori	r11,r11,pmdisk_save_area@l

	mflr	r0
	stw	r0,SL_LR(r11)
	mfcr	r0
	stw	r0,SL_CR(r11)
	stw	r1,SL_SP(r11)
	stw	r2,SL_R2(r11)
	stmw	r12,SL_R12(r11)

	/* Save MSR & SDR1 */
	mfmsr	r4
	stw	r4,SL_MSR(r11)
	mfsdr1	r4
	stw	r4,SL_SDR1(r11)

	/* Get a stable timebase and save it */
1:	mftbu	r4
	stw	r4,SL_TB(r11)
	mftb	r5
	stw	r5,SL_TB+4(r11)
	mftbu	r3
	cmpw	r3,r4
	bne	1b

	/* Save SPRGs */
	mfsprg	r4,0
	stw	r4,SL_SPRG0(r11)
	mfsprg	r4,1
	stw	r4,SL_SPRG0+4(r11)
	mfsprg	r4,2
	stw	r4,SL_SPRG0+8(r11)
	mfsprg	r4,3
	stw	r4,SL_SPRG0+12(r11)

	/* Save BATs */
	mfdbatu	r4,0
	stw	r4,SL_DBAT0(r11)
	mfdbatl	r4,0
	stw	r4,SL_DBAT0+4(r11)
	mfdbatu	r4,1
	stw	r4,SL_DBAT1(r11)
	mfdbatl	r4,1
	stw	r4,SL_DBAT1+4(r11)
	mfdbatu	r4,2
	stw	r4,SL_DBAT2(r11)
	mfdbatl	r4,2
	stw	r4,SL_DBAT2+4(r11)
	mfdbatu	r4,3
	stw	r4,SL_DBAT3(r11)
	mfdbatl	r4,3
	stw	r4,SL_DBAT3+4(r11)
	mfibatu	r4,0
	stw	r4,SL_IBAT0(r11)
	mfibatl	r4,0
	stw	r4,SL_IBAT0+4(r11)
	mfibatu	r4,1
	stw	r4,SL_IBAT1(r11)
	mfibatl	r4,1
	stw	r4,SL_IBAT1+4(r11)
	mfibatu	r4,2
	stw	r4,SL_IBAT2(r11)
	mfibatl	r4,2
	stw	r4,SL_IBAT2+4(r11)
	mfibatu	r4,3
	stw	r4,SL_IBAT3(r11)
	mfibatl	r4,3
	stw	r4,SL_IBAT3+4(r11)

#if  0
	/* Backup various CPU config stuffs */
	bl	__save_cpu_setup
#endif
	/* Call the low level suspend stuff (we should probably have made
	 * a stackframe...
	 */
	bl	pmdisk_suspend
	
	/* Restore LR from the save area */
	lis	r11,pmdisk_save_area@h
	ori	r11,r11,pmdisk_save_area@l
	lwz	r0,SL_LR(r11)
	mtlr	r0

	blr


/* Resume code */	
do_resume:

	/* Stop pending alitvec streams and memory accesses */
BEGIN_FTR_SECTION
	DSSALL
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	sync

	/* Disable MSR:DR to make sure we don't take a TLB or
	 * hash miss during the copy, as our hash table will
	 * for a while be unuseable. For .text, we assume we are
	 * covered by a BAT. This works only for non-G5 at this
	 * point. G5 will need a better approach, possibly using
	 * a small temporary hash table filled with large mappings,
	 * disabling the MMU completely isn't a good option for
	 * performance reasons.
	 * (Note that 750's may have the same performance issue as
	 * the G5 in this case, we should investigate using moving
	 * BATs for these CPUs)
	 */
	mfmsr	r0
	sync
	rlwinm	r0,r0,0,28,26		/* clear MSR_DR */
	mtmsr	r0
	sync
	isync

	/* Load ptr the list of pages to copy in r3 */
	lis	r11,(pm_pagedir_nosave - KERNELBASE)@h
	ori	r11,r11,pm_pagedir_nosave@l
	lwz	r10,0(r11)
	tophys(r3,r10)

	/* Load the count of pages to copy in r4 */
	lis	r11,(pmdisk_pages - KERNELBASE)@h
	ori	r11,r11,pmdisk_pages@l
	lwz	r4,0(r11)
	

	/* Copy the pages. This is a very basic implementation, to
	 * be replaced by something more cache efficient */
1:
	li	r0,256
	mtctr	r0
	lwz	r11,0(r3)	/* source */
	tophys(r5,r11)
	lwz	r10,4(r3)	/* destination */
	tophys(r6,r10)
2:
	lwz	r8,0(r5)
	lwz	r9,4(r5)
	lwz	r10,8(r5)
	lwz	r11,12(r5)
	addi	r5,r5,16
	stw	r8,0(r6)
	stw	r9,4(r6)
	stw	r10,8(r6)
	stw	r11,12(r6)
	addi	r6,r6,16
	bdnz	2b
	addi	r3,r3,16
	subi	r4,r4,1
	cmpwi	0,r4,0
	bne	1b
	
	/* Do a very simple cache flush/inval of the L1 to ensure
	 * coherency of the icache
	 */
	lis	r3,0x0002
	mtctr	r3
	li	r3, 0
1:
	lwz	r0,0(r3)
	addi	r3,r3,0x0020
	bdnz	1b
	isync
	sync

	/* Now flush those cache lines */
	lis	r3,0x0002
	mtctr	r3
	li	r3, 0
1:
	dcbf	0,r3
	addi	r3,r3,0x0020
	bdnz	1b
	sync

	/* Ok, we are now running with the kernel data of the old
	 * kernel fully restored. We can get to the save area
	 * easily now. As for the rest of the code, it assumes the
	 * loader kernel and the booted one are exactly identical
	 */
	lis	r11,pmdisk_save_area@h
	ori	r11,r11,pmdisk_save_area@l
	tophys(r11,r11)
	
#if 0
	/* Restore various CPU config stuffs */
	bl	__restore_cpu_setup
#endif
	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. 
	 * This is a bit hairy as we are running out of those BATs,
	 * but first, our code is probably in the icache, and we are
	 * writing the same value to the BAT, so that should be fine,
	 * though a better solution will have to be found long-term
	 */
	lwz	r4,SL_SDR1(r11)
	mtsdr1	r4
	lwz	r4,SL_SPRG0(r11)
	mtsprg	0,r4
	lwz	r4,SL_SPRG0+4(r11)
	mtsprg	1,r4
	lwz	r4,SL_SPRG0+8(r11)
	mtsprg	2,r4
	lwz	r4,SL_SPRG0+12(r11)
	mtsprg	3,r4

#if 0
	lwz	r4,SL_DBAT0(r11)
	mtdbatu	0,r4
	lwz	r4,SL_DBAT0+4(r11)
	mtdbatl	0,r4
	lwz	r4,SL_DBAT1(r11)
	mtdbatu	1,r4
	lwz	r4,SL_DBAT1+4(r11)
	mtdbatl	1,r4
	lwz	r4,SL_DBAT2(r11)
	mtdbatu	2,r4
	lwz	r4,SL_DBAT2+4(r11)
	mtdbatl	2,r4
	lwz	r4,SL_DBAT3(r11)
	mtdbatu	3,r4
	lwz	r4,SL_DBAT3+4(r11)
	mtdbatl	3,r4
	lwz	r4,SL_IBAT0(r11)
	mtibatu	0,r4
	lwz	r4,SL_IBAT0+4(r11)
	mtibatl	0,r4
	lwz	r4,SL_IBAT1(r11)
	mtibatu	1,r4
	lwz	r4,SL_IBAT1+4(r11)
	mtibatl	1,r4
	lwz	r4,SL_IBAT2(r11)
	mtibatu	2,r4
	lwz	r4,SL_IBAT2+4(r11)
	mtibatl	2,r4
	lwz	r4,SL_IBAT3(r11)
	mtibatu	3,r4
	lwz	r4,SL_IBAT3+4(r11)
	mtibatl	3,r4
#endif

BEGIN_FTR_SECTION
	li	r4,0
	mtspr	SPRN_DBAT4U,r4
	mtspr	SPRN_DBAT4L,r4
	mtspr	SPRN_DBAT5U,r4
	mtspr	SPRN_DBAT5L,r4
	mtspr	SPRN_DBAT6U,r4
	mtspr	SPRN_DBAT6L,r4
	mtspr	SPRN_DBAT7U,r4
	mtspr	SPRN_DBAT7L,r4
	mtspr	SPRN_IBAT4U,r4
	mtspr	SPRN_IBAT4L,r4
	mtspr	SPRN_IBAT5U,r4
	mtspr	SPRN_IBAT5L,r4
	mtspr	SPRN_IBAT6U,r4
	mtspr	SPRN_IBAT6L,r4
	mtspr	SPRN_IBAT7U,r4
	mtspr	SPRN_IBAT7L,r4
END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)

	/* Flush all TLBs */
	lis	r4,0x1000
1:	addic.	r4,r4,-0x1000
	tlbie	r4
	blt	1b
	sync

	/* restore the MSR and turn on the MMU */
	lwz	r3,SL_MSR(r11)
	bl	turn_on_mmu
	tovirt(r11,r11)

	/* Restore TB */
	li	r3,0
	mttbl	r3
	lwz	r3,SL_TB(r11)
	lwz	r4,SL_TB+4(r11)
	mttbu	r3
	mttbl	r4

	/* Kick decrementer */
	li	r0,1
	mtdec	r0

	/* Restore the callee-saved registers and return */
	lwz	r0,SL_CR(r11)
	mtcr	r0
	lwz	r2,SL_R2(r11)
	lmw	r12,SL_R12(r11)
	lwz	r1,SL_SP(r11)
	lwz	r0,SL_LR(r11)
	mtlr	r0

	// XXX Note: we don't really need to call pmdisk_resume

	li	r3,0
	blr

/* FIXME:This construct is actually not useful since we don't shut
 * down the instruction MMU, we could just flip back MSR-DR on.
 */
turn_on_mmu:
	mflr	r4
	mtsrr0	r4
	mtsrr1	r3
	sync
	isync
	rfi



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-24  2:54                 ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
@ 2004-01-24  5:40                   ` Hugang
  2004-01-24 16:28                   ` Colin Leroy
                                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 80+ messages in thread
From: Hugang @ 2004-01-24  5:40 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

On Sat, 24 Jan 2004 13:54:15 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> Ok, I hammered that for a day and got pmdisk (patrick's version)
> suspending and resuming on a pismo G3 (with XFree etc.. running). Lots
> of rough edges still (via-pmu sleep need to be improved, ADB need
> porting to the new driver model to be properly suspended/resumed, a
> sysdev for RTC is needed too for time, the asm code should be fixed
> for G5, etc...)

Yes, It works in my laptop too. Cool.

thanks for greate work.

-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-24  4:39                 ` Benjamin Herrenschmidt
@ 2004-01-24  7:20                   ` Pavel Machek
  2004-01-24  9:59                     ` pmdisk working on ppc Måns Rullgård
  0 siblings, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-24  7:20 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Patrick Mochel, Nigel Cunningham, linuxppc-dev list,
	Linux Kernel list, Hugang

Hi!

> (RESENT, sorry if you got it already, something apparently went wrong
> on the SMTP here)
> 
> Ok, I hammered that for a day and got pmdisk (patrick's version) suspending
> and resuming on a pismo G3 (with XFree etc.. running). Lots of rough
> edges

Congratulations!
								Pavel
[Now we'll have to do something with pmdisk vs. swsusp...]
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc
  2004-01-24  7:20                   ` Pavel Machek
@ 2004-01-24  9:59                     ` Måns Rullgård
  0 siblings, 0 replies; 80+ messages in thread
From: Måns Rullgård @ 2004-01-24  9:59 UTC (permalink / raw)
  To: linux-kernel

Pavel Machek <pavel@ucw.cz> writes:

> Hi!
>
>> (RESENT, sorry if you got it already, something apparently went wrong
>> on the SMTP here)
>>
>> Ok, I hammered that for a day and got pmdisk (patrick's version) suspending
>> and resuming on a pismo G3 (with XFree etc.. running). Lots of rough
>> edges
>
> Congratulations!
> 								Pavel
> [Now we'll have to do something with pmdisk vs. swsusp...]

pmdisk is the only one that ever was close to working on my laptop, do
don't kill that one.  Some driver is (was?) preventing it from
resuming properly.  Is there some list somewhere of drivers known to
be pmdisk safe?

-- 
Måns Rullgård
mru@kth.se


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-24  2:54                 ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
  2004-01-24  5:40                   ` Hugang
@ 2004-01-24 16:28                   ` Colin Leroy
  2004-01-24 23:46                     ` Benjamin Herrenschmidt
  2004-01-26 14:29                   ` Guido Guenther
       [not found]                   ` <20040126181004.GB315@elf.ucw.cz>
  3 siblings, 1 reply; 80+ messages in thread
From: Colin Leroy @ 2004-01-24 16:28 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

On 24 Jan 2004 at 13h01, Benjamin Herrenschmidt wrote:

Hi, 

> The patch is against my tree currently, and the arch/ppc/kernel/pmdisk.S file
> is appended as-is (not in patch form). 

Didn't you forget to include include/asm-ppc/suspend.h ? ;-)
-- 
Colin

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-24 16:28                   ` Colin Leroy
@ 2004-01-24 23:46                     ` Benjamin Herrenschmidt
  2004-01-25 18:08                       ` Colin Leroy
  0 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-24 23:46 UTC (permalink / raw)
  To: Colin Leroy
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

On Sun, 2004-01-25 at 03:28, Colin Leroy wrote:
> On 24 Jan 2004 at 13h01, Benjamin Herrenschmidt wrote:
> 
> Hi, 
> 
> > The patch is against my tree currently, and the arch/ppc/kernel/pmdisk.S file
> > is appended as-is (not in patch form). 
> 
> Didn't you forget to include include/asm-ppc/suspend.h ? ;-)

Yes, but you could have re-created it easily: 


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

static inline void save_processor_state(void)
{
}

static inline void restore_processor_state(void)
{
}




^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-24 23:46                     ` Benjamin Herrenschmidt
@ 2004-01-25 18:08                       ` Colin Leroy
  2004-01-26  0:08                         ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 80+ messages in thread
From: Colin Leroy @ 2004-01-25 18:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

On 25 Jan 2004 at 10h01, Benjamin Herrenschmidt wrote:

Hi, 

> > Didn't you forget to include include/asm-ppc/suspend.h ? ;-)
> 
> Yes, but you could have re-created it easily: 

Thanks - I wasn't sure about it.
The kernel now builds. However, after doing
	echo disk > /sys/power/state
or "hda14" or "/dev/hda14" (which is my swap partition) instead of "disk", 
nothing happens (and nothing gets logged). 
The only things different from your patch is that I added PMAC_MB_CAN_SLEEP 
to my iBook's entry in pmac_feature.c, and added 
	return -EBUSY; 
after your 
        if (state != 2 && state != 3)
                return 0;
in radeon_pm.c (to avoid pmud putting the iBook to sleep by mistake).

relevant .config part:
# CONFIG_SOFTWARE_SUSPEND is not set
CONFIG_PM_DISK=y
CONFIG_PM_DISK_PARTITION="/dev/hda14"

Any pointer ? (did I miss something obvious?)

Thanks,
-- 
Colin

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-25 18:08                       ` Colin Leroy
@ 2004-01-26  0:08                         ` Benjamin Herrenschmidt
  2004-01-26 18:21                           ` Colin Leroy
  0 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-26  0:08 UTC (permalink / raw)
  To: Colin Leroy
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list


> Thanks - I wasn't sure about it.
> The kernel now builds. However, after doing
> 	echo disk > /sys/power/state
> or "hda14" or "/dev/hda14" (which is my swap partition) instead of "disk",
> nothing happens (and nothing gets logged).

Hrm... It tends to do that when it's not happy with something,
but I did get it working... Ah yes, do

echo -n "disk" instead :) It doesn't like the trailing \n

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-24  2:54                 ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
  2004-01-24  5:40                   ` Hugang
  2004-01-24 16:28                   ` Colin Leroy
@ 2004-01-26 14:29                   ` Guido Guenther
       [not found]                   ` <20040126181004.GB315@elf.ucw.cz>
  3 siblings, 0 replies; 80+ messages in thread
From: Guido Guenther @ 2004-01-26 14:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

On Sat, Jan 24, 2004 at 01:54:15PM +1100, Benjamin Herrenschmidt wrote:
> Ok, I hammered that for a day and got pmdisk (patrick's version) suspending
> and resuming on a pismo G3 (with XFree etc.. running). Lots of rough edges
> still (via-pmu sleep need to be improved, ADB need porting to the new driver
> model to be properly suspended/resumed, a sysdev for RTC is needed too for
> time, the asm code should be fixed for G5, etc...)
Works fine on a 

processor       : 0
cpu             : 7455, altivec supported
clock           : 867MHz
revision        : 3.3 (pvr 8001 0303)
bogomips        : 863.00
machine         : PowerBook6,1
motherboard     : PowerBook6,1 MacRISC3 Power Macintosh
board revision  : 00000001
detected as     : 287 (PowerBook G4 12")
pmac flags      : 0000000b
L2 cache        : 256K unified
memory          : 256MB
pmac-generation : NewWorld

Cheers,
 -- Guido

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-26  0:08                         ` Benjamin Herrenschmidt
@ 2004-01-26 18:21                           ` Colin Leroy
  2004-01-26 21:58                             ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 80+ messages in thread
From: Colin Leroy @ 2004-01-26 18:21 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

On 26 Jan 2004 at 11h01, Benjamin Herrenschmidt wrote:

Hi, 

> Hrm... It tends to do that when it's not happy with something,
> but I did get it working... Ah yes, do
> 
> echo -n "disk" instead :) It doesn't like the trailing \n

Thanks, worked better. Got an oops with ohci-hcd or ehci-hcd, though. 
shutdown worked after rmmoding these.
However resume did not - got:

dn: cn= pmdisk: CPUs: 544501616
 pmdisk: Image: 168453230 Pages
 pmdisk: Pagedir: 975201134 Pages
pmdisk: Resume mismatch: kernel version
pmdisk: Error -1 resuming
PM: Resume from disk failed.

of course, this was the same kernel. Don't really know what to try next,
but it doesn't matter that much to me, don't lose your time with it if 
you lack time :)

-- 
Colin

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-26 18:21                           ` Colin Leroy
@ 2004-01-26 21:58                             ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-26 21:58 UTC (permalink / raw)
  To: Colin Leroy
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

On Tue, 2004-01-27 at 05:21, Colin Leroy wrote:
> On 26 Jan 2004 at 11h01, Benjamin Herrenschmidt wrote:
> 
> Hi, 
> 
> > Hrm... It tends to do that when it's not happy with something,
> > but I did get it working... Ah yes, do
> > 
> > echo -n "disk" instead :) It doesn't like the trailing \n
> 
> Thanks, worked better. Got an oops with ohci-hcd or ehci-hcd, though. 
> shutdown worked after rmmoding these.
> However resume did not - got:

pmdisk will save to the first (or the last, I'm not sure) installed
swap partition, not what your say on the command line. It will _resume_
from what you say on the command line.

ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
       [not found]                   ` <20040126181004.GB315@elf.ucw.cz>
@ 2004-01-26 22:00                     ` Benjamin Herrenschmidt
  2004-01-26 22:31                       ` Nigel Cunningham
                                         ` (2 more replies)
  0 siblings, 3 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-26 22:00 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

On Tue, 2004-01-27 at 05:10, Pavel Machek wrote:
> Hi!
> 
> > Ah, also: The "Freeing memory" phase takes forever. That should
> > really be fixed.
> 
> Well, it does the trick for me, but it takes 50% or so of suspend
> time. Some memory managment guru making "freeing memory" faster would
> certainly be welcome.
> 								Pavel
> PS: But I'd like to keep it simple...

Haven't looked at it yet. Several crash reports so far, mostly
lockups right after printing the number of pages to save. I wonder
if we have something broken in there. It dies for me once too at
this point.

Also, at least on pmac laptops, the HD is usually so fast, that
I suspect spending 10 seconds freeing things is less efficient than
spending this 10 seconds writing 200Mb of data to disk :) Also, one
wakup, it's quite painful to see everything be swapped in again. It
may make sense to be less agressive on the memory freeing, though
finding a good balance isn't easy.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-26 22:00                     ` Benjamin Herrenschmidt
@ 2004-01-26 22:31                       ` Nigel Cunningham
  2004-01-28 12:22                         ` Hugang
  2004-01-26 23:21                       ` Pavel Machek
  2004-01-27 10:34                       ` Michael Schmitz
  2 siblings, 1 reply; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-26 22:31 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Pavel Machek, Hugang, Patrick Mochel, Linux Kernel Mailing List,
	linuxppc-dev list

[-- Attachment #1: Type: text/plain, Size: 692 bytes --]

Hi.

On Tue, 2004-01-27 at 11:00, Benjamin Herrenschmidt wrote:
> Also, at least on pmac laptops, the HD is usually so fast, that
> I suspect spending 10 seconds freeing things is less efficient than
> spending this 10 seconds writing 200Mb of data to disk :) Also, one
> wakup, it's quite painful to see everything be swapped in again. It
> may make sense to be less agressive on the memory freeing, though
> finding a good balance isn't easy.

Yes. That's why suspend2 doesn't free any memory at all by default, but
gives the user the option of setting a maximum image size.

Regards,

Nigel
-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-26 22:00                     ` Benjamin Herrenschmidt
  2004-01-26 22:31                       ` Nigel Cunningham
@ 2004-01-26 23:21                       ` Pavel Machek
  2004-01-27  0:12                         ` Nigel Cunningham
  2004-01-27 10:34                       ` Michael Schmitz
  2 siblings, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-26 23:21 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Hugang, Patrick Mochel, Nigel Cunningham, ncunningham,
	Linux Kernel Mailing List, linuxppc-dev list

Hi!

> > > Ah, also: The "Freeing memory" phase takes forever. That should
> > > really be fixed.
> > 
> > Well, it does the trick for me, but it takes 50% or so of suspend
> > time. Some memory managment guru making "freeing memory" faster would
> > certainly be welcome.
> > 								Pavel
> > PS: But I'd like to keep it simple...
> 
> Haven't looked at it yet. Several crash reports so far, mostly
> lockups right after printing the number of pages to save. I wonder
> if we have something broken in there. It dies for me once too at
> this point.
> 
> Also, at least on pmac laptops, the HD is usually so fast, that
> I suspect spending 10 seconds freeing things is less efficient than
> spending this 10 seconds writing 200Mb of data to disk :) Also, one
> wakup, it's quite painful to see everything be swapped in again. It
> may make sense to be less agressive on the memory freeing, though
> finding a good balance isn't easy.

Notice that swsusp needs half of physical memory free by design. That
means that we need _some_ freeing. Nigel's swsusp2 works around that
at cost of more complicated implementation.
								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-26 23:21                       ` Pavel Machek
@ 2004-01-27  0:12                         ` Nigel Cunningham
  2004-01-27  7:53                           ` Pavel Machek
  0 siblings, 1 reply; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-27  0:12 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Benjamin Herrenschmidt, Hugang, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

[-- Attachment #1: Type: text/plain, Size: 585 bytes --]

On Tue, 2004-01-27 at 12:21, Pavel Machek wrote:
> Notice that swsusp needs half of physical memory free by design. That
> means that we need _some_ freeing. Nigel's swsusp2 works around that
> at cost of more complicated implementation.

Yes, my method is a bit more complicated.

Yours doesn't always need some freeing though - you only need to free
memory until that 1/2 limitation is met. Last time I looked at it, it
freed memory until it could free no more. Is that still true?

Nigel
-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-27  0:12                         ` Nigel Cunningham
@ 2004-01-27  7:53                           ` Pavel Machek
  0 siblings, 0 replies; 80+ messages in thread
From: Pavel Machek @ 2004-01-27  7:53 UTC (permalink / raw)
  To: Nigel Cunningham
  Cc: Benjamin Herrenschmidt, Hugang, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

Hi!

> > Notice that swsusp needs half of physical memory free by design. That
> > means that we need _some_ freeing. Nigel's swsusp2 works around that
> > at cost of more complicated implementation.
> 
> Yes, my method is a bit more complicated.
> 
> Yours doesn't always need some freeing though - you only need to free
> memory until that 1/2 limitation is met. Last time I looked at it, it
> freed memory until it could free no more. Is that still true?

Yes. [It could be changed, but at that point I'd have to figure out
how much memory I really do need for write buffers, bio allocation,
etc.]

								Pavel
-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-26 22:00                     ` Benjamin Herrenschmidt
  2004-01-26 22:31                       ` Nigel Cunningham
  2004-01-26 23:21                       ` Pavel Machek
@ 2004-01-27 10:34                       ` Michael Schmitz
  2004-01-27 10:37                         ` Benjamin Herrenschmidt
  2004-01-27 10:47                         ` Pavel Machek
  2 siblings, 2 replies; 80+ messages in thread
From: Michael Schmitz @ 2004-01-27 10:34 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Pavel Machek, Hugang, Patrick Mochel, Nigel Cunningham,
	ncunningham, linuxppc-dev list


> > > Ah, also: The "Freeing memory" phase takes forever. That should
> > > really be fixed.
> >
> > Well, it does the trick for me, but it takes 50% or so of suspend
> > time. Some memory managment guru making "freeing memory" faster would
> > certainly be welcome.
> > 								Pavel
> > PS: But I'd like to keep it simple...
>
> Haven't looked at it yet. Several crash reports so far, mostly
> lockups right after printing the number of pages to save. I wonder
> if we have something broken in there. It dies for me once too at
> this point.

The PMU locking up with interrupts disabled, for me (Lombard, 400 MHz).
Seems to happen more often on slow machines.
Otherwise, it works (saving to the last swap partition if you try to
specify which one to use; patch sent to Ben FWIW).

> Also, at least on pmac laptops, the HD is usually so fast, that
> I suspect spending 10 seconds freeing things is less efficient than
> spending this 10 seconds writing 200Mb of data to disk :) Also, one
> wakup, it's quite painful to see everything be swapped in again. It
> may make sense to be less agressive on the memory freeing, though
> finding a good balance isn't easy.

I don't mind the wait for memory being freed. Copying more pages with
interrupts disabled would mean a higher chance for PMU lockup, won't it?

	Michael


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-27 10:34                       ` Michael Schmitz
@ 2004-01-27 10:37                         ` Benjamin Herrenschmidt
  2004-01-27 14:32                           ` Michael Schmitz
  2004-01-27 10:47                         ` Pavel Machek
  1 sibling, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-27 10:37 UTC (permalink / raw)
  To: Michael Schmitz
  Cc: Pavel Machek, Hugang, Patrick Mochel, Nigel Cunningham,
	ncunningham, linuxppc-dev list


> I don't mind the wait for memory being freed. Copying more pages with
> interrupts disabled would mean a higher chance for PMU lockup, won't it?

It's also possible that there is a bug and it just crashes :)

Also, I do suspend devices before the page copy, and I quickly hacked a
PMU sysdev that should suspend ADB interrupts (at least) so that should
be fine, except if you have a brightness request in flight maybe ?

The whole PMU suspend thing must be reworked I suppose. (And the battery
monitoring thing "paused" as well, we must wait for async PMU requests,
that is at least battery requests and backlight ones to stop)

Ben.


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-27 10:34                       ` Michael Schmitz
  2004-01-27 10:37                         ` Benjamin Herrenschmidt
@ 2004-01-27 10:47                         ` Pavel Machek
  2004-01-27 10:56                           ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-27 10:47 UTC (permalink / raw)
  To: Michael Schmitz
  Cc: Benjamin Herrenschmidt, Hugang, Patrick Mochel, Nigel Cunningham,
	ncunningham, linuxppc-dev list


Hi!

> > > > Ah, also: The "Freeing memory" phase takes forever. That should
> > > > really be fixed.
> > >
> > > Well, it does the trick for me, but it takes 50% or so of suspend
> > > time. Some memory managment guru making "freeing memory" faster would
> > > certainly be welcome.
> > > 								Pavel
> > > PS: But I'd like to keep it simple...
> >
> > Haven't looked at it yet. Several crash reports so far, mostly
> > lockups right after printing the number of pages to save. I wonder
> > if we have something broken in there. It dies for me once too at
> > this point.
>
> The PMU locking up with interrupts disabled, for me (Lombard, 400 MHz).
> Seems to happen more often on slow machines.
> Otherwise, it works (saving to the last swap partition if you try to
> specify which one to use; patch sent to Ben FWIW).

What is "PMU locking"? Is there some part of powermac harware that
kills machine if you sleep too long with interrupts disabled?

								Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-27 10:47                         ` Pavel Machek
@ 2004-01-27 10:56                           ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-27 10:56 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Michael Schmitz, Hugang, Patrick Mochel, Nigel Cunningham,
	ncunningham, linuxppc-dev list


> What is "PMU locking"? Is there some part of powermac harware that
> kills machine if you sleep too long with interrupts disabled?

The PMU is the "Power Management Unit". It's a microcontroller
that does a bunch of things, some PM related, but also the ADB
emulation for the keyboard & trackpad on laptops, the real time
clock, battery management, etc...

We communicate with it via an SPI, it's asynchronous (interrupt
driven) protocol (banging things to a shit register basically).

The kernel is continuously talking to the PMU. If for some reason
communication stops in the middle of a message exchange, the PMU
can time out and shuts the box down.

"PMU suspend" is a hook I added to the driver that completes
pending requests and stops answering to "event" interrupts (those
interrupts are sent by the PMU when we need to read it's incoming
event messages, like keystrokes, environement events, etc...).

When we get such an interrupt, we send a command to read the
event and get the data in the reply. The PMU can timeout in the
middle of that exchange, but won't timeout if we don't ask for
the data at all...

On suspend-to-RAM, since the PMU driver drives the whole suspend
process, there is no real problem, it does things the right way.

But with suspend-to-disk, it's just yet-another device, and so we
need to make sure we properly stop pending communication. The quick
hack I did (added a sysdev with suspend/resume hooks for it) may not
be perfect yet :)

Ben.


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-27 10:37                         ` Benjamin Herrenschmidt
@ 2004-01-27 14:32                           ` Michael Schmitz
  2004-01-27 21:40                             ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 80+ messages in thread
From: Michael Schmitz @ 2004-01-27 14:32 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Michael Schmitz, Pavel Machek, Hugang, Patrick Mochel,
	Nigel Cunningham, ncunningham, linuxppc-dev list


> > I don't mind the wait for memory being freed. Copying more pages with
> > interrupts disabled would mean a higher chance for PMU lockup, won't it?
>
> It's also possible that there is a bug and it just crashes :)
>
> Also, I do suspend devices before the page copy, and I quickly hacked a
> PMU sysdev that should suspend ADB interrupts (at least) so that should
> be fine, except if you have a brightness request in flight maybe ?

I haven't. I've added another pmu_suspend/pmu_resume around the bulk of
pmdisk_save, that seems to have improved things (but not completely). It's
executed outside your sysdev calls, so it shouldn't really improve things.

> The whole PMU suspend thing must be reworked I suppose. (And the battery
> monitoring thing "paused" as well, we must wait for async PMU requests,
> that is at least battery requests and backlight ones to stop)

Battery requests might have been underway; pmud is running. If I read
pmu_suspend() right, pending battery requests should result in pmu_suspend
waiting for them to finish?

	Michael


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-27 14:32                           ` Michael Schmitz
@ 2004-01-27 21:40                             ` Benjamin Herrenschmidt
  2004-01-28 16:09                               ` Michael Schmitz
  0 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-27 21:40 UTC (permalink / raw)
  To: Michael Schmitz
  Cc: Michael Schmitz, Pavel Machek, Hugang, Patrick Mochel,
	Nigel Cunningham, ncunningham, linuxppc-dev list


> Battery requests might have been underway; pmud is running. If I read
> pmu_suspend() right, pending battery requests should result in pmu_suspend
> waiting for them to finish?

Normally yes... pmud isn't running at this point (all processes are frozen)

Ben.


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-26 22:31                       ` Nigel Cunningham
@ 2004-01-28 12:22                         ` Hugang
  2004-01-28 13:23                           ` pmdisk working on ppc (WAS: Help port swsusp to ppc), swsusp2 works Hugang
  2004-01-29  0:34                           ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
  0 siblings, 2 replies; 80+ messages in thread
From: Hugang @ 2004-01-28 12:22 UTC (permalink / raw)
  To: ncunningham
  Cc: Benjamin Herrenschmidt, Pavel Machek, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

[-- Attachment #1: Type: text/plain, Size: 1172 bytes --]

On Tue, 27 Jan 2004 11:31:50 +1300
Nigel Cunningham <ncunningham@users.sourceforge.net> wrote:

> Yes. That's why suspend2 doesn't free any memory at all by default,
> but gives the user the option of setting a maximum image size.

HaHa, Here is swsusp2 patch for ppc. Now it WORKS fine.

The code base for testing, any comments and testing are welcome.

-: Howto let it work.
 1: download clean 2.6.1 kernel.
 2: apply swusp2 2.6.1 patch.
 3: apply swsusp2 core patch.
 4: apply ppc_swsusp2_1.diff
 5: do make menuconfig
CONFIG_SOFTWARE_SUSPEND2=y
CONFIG_SOFTWARE_SUSPEND_DEBUG=y
CONFIG_SOFTWARE_SUSPEND_GZIP_COMPRESSION=y
CONFIG_SOFTWARE_SUSPEND_LZF_COMPRESSION=y
CONFIG_SOFTWARE_SUSPEND_SWAPWRITER=y
 6:add "resume2=swap:/dev/hda10" into yaboot.conf.
  "/dev/hda10" is your swap partition.
 7:do suspend.
  I using a sciprt to do it. or use suspend script from swsusp2.sf.net .
 8:you system will backed.

-: Plans. 
   I has created arch/ppc/power directory like i386 arch, and put power
    manger code in it.
 1: clean code.
 2: merge pmac sleep into.

thanks.

-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

[-- Attachment #2: ppc_swsusp2_1.diff --]
[-- Type: text/plain, Size: 21636 bytes --]

Index: linux-2.6.1-suspend/kernel/power/swsusp2.c
===================================================================
--- linux-2.6.1-suspend/kernel/power/swsusp2.c	(revision 192)
+++ linux-2.6.1-suspend/kernel/power/swsusp2.c	(working copy)
@@ -54,7 +54,9 @@
 
 #include <linux/suspend-common.h>
 #include <linux/suspend-version-specific.h>
+#ifdef  CONFIG_X86
 #include <asm/i387.h> /* for kernel_fpu_end */
+#endif
 #ifdef	CONFIG_KDB
 #include <linux/kdb.h>
 #endif	/* CONFIG_KDB */
@@ -327,7 +329,9 @@
 	preempt_enable();
 #endif
 
+#ifdef CONFIG_X86
 	kernel_fpu_end();
+#endif
 
 	PRINTPREEMPTCOUNT("Prior to resuming drivers.");
 
@@ -486,10 +490,10 @@
 #endif
 
 	PRINTPREEMPTCOUNT("In resume_2 after copy back.");
-
+#ifdef CONFIG_X86
 	kernel_fpu_end();
-
 	PRINTPREEMPTCOUNT("In resume_2 after fpu end.");
+#endif
 	
 #ifdef CONFIG_PREEMPT
 	preempt_enable();
Index: linux-2.6.1-suspend/include/asm-ppc/suspend.h
===================================================================
--- linux-2.6.1-suspend/include/asm-ppc/suspend.h	(revision 0)
+++ linux-2.6.1-suspend/include/asm-ppc/suspend.h	(revision 0)
@@ -0,0 +1,14 @@
+#ifndef _PPC_SUSPEND_H
+#define _PPC_SUSPEND_H
+
+static inline void flush_tlb_all(void)
+{
+	/* Flush all TLBs */
+	__asm__ __volatile__("lis 4, 0x1000");
+	__asm__ __volatile__("1: addic. 4,4,-0x1000");
+	__asm__ __volatile__("tlbie 4");
+	__asm__ __volatile__("blt 1b");
+	__asm__ __volatile__("sync");
+}
+
+#endif
Index: linux-2.6.1-suspend/arch/ppc/kernel/vmlinux.lds.S
===================================================================
--- linux-2.6.1-suspend/arch/ppc/kernel/vmlinux.lds.S	(revision 192)
+++ linux-2.6.1-suspend/arch/ppc/kernel/vmlinux.lds.S	(working copy)
@@ -72,6 +72,12 @@
     CONSTRUCTORS
   }
 
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
Index: linux-2.6.1-suspend/arch/ppc/kernel/signal.c
===================================================================
--- linux-2.6.1-suspend/arch/ppc/kernel/signal.c	(revision 192)
+++ linux-2.6.1-suspend/arch/ppc/kernel/signal.c	(working copy)
@@ -28,6 +28,7 @@
 #include <linux/elf.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
+#include <linux/suspend.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -552,6 +553,11 @@
 	unsigned long frame, newsp;
 	int signr, ret;
 
+	if (current->flags & PF_FREEZE) {
+		refrigerator(PF_FREEZE);
+		return 0;
+	}
+
 	if (!oldset)
 		oldset = &current->blocked;
 
Index: linux-2.6.1-suspend/arch/ppc/Kconfig
===================================================================
--- linux-2.6.1-suspend/arch/ppc/Kconfig	(revision 192)
+++ linux-2.6.1-suspend/arch/ppc/Kconfig	(working copy)
@@ -193,6 +193,8 @@
 
 	  If in doubt, say Y here.
 
+source kernel/power/Kconfig
+
 source arch/ppc/platforms/4xx/Kconfig
 
 config PPC64BRIDGE
Index: linux-2.6.1-suspend/arch/ppc/power/swsusp2-copyback.S
===================================================================
--- linux-2.6.1-suspend/arch/ppc/power/swsusp2-copyback.S	(revision 0)
+++ linux-2.6.1-suspend/arch/ppc/power/swsusp2-copyback.S	(revision 0)
@@ -0,0 +1,73 @@
+#define PAGE_TO_POINTER(in, out, p)	\
+	lwz out,0(in)					  ; \
+	slwi r9,out,2					  ; \
+	add r9,r9,out					  ; \
+	slwi r9,r9,3					  ; \
+	mullw r9,r9,r4					  ; \
+	slwi r9,r9,9					  ; \
+	addis p,r9,0xc000				  ; \
+	tophys(p,p)
+
+	.section ".text"
+swsusp2_copyback:
+	lis r20,pagedir_resume@ha	/* can't ture this is right FIXME */
+	addi r20,r20,pagedir_resume@l
+	tophys(r20,r20)
+#if 0
+	lwz	r4,4(r20)
+	twi	31,r0,0	/* triger trap */
+#endif	
+	lis r4,0xcccc /* FIXME */
+	ori r4,r4,52429
+
+	lwz r6,12(r20)		/* r6 is origranges.first */
+	cmpwi r6,0
+	beq- swsusp2_end_copyback
+		
+	tophys(r6,r6)
+	PAGE_TO_POINTER(r6,r8,r10)				  
+
+	lwz r5,56(r20)		/* r5 is copyranges.first */
+	tophys(r5,r5)
+	PAGE_TO_POINTER(r5,r7,r11) 
+	
+swsusp2_copy_one_page:
+	li r0,1024		/* r9 is loop */
+	mtctr r0		/* prepare for branch */
+	li r9,0
+swsusp2_copy_data:
+	lwzx r0,r9,r11
+	stwx r0,r9,r10
+	addi r9,r9,4
+
+	bdnz swsusp2_copy_data
+
+	lwz r0,4(r6)					  /* r0 is maximum */
+	cmplw r8,r0
+	bge- next_orig
+	addi r8,r8,1
+	addi r10,r10,4096
+	b end_orig
+next_orig:
+	lwz r6,8(r6)	/* r6 origrange */
+	cmpwi r6,0
+	beq- end_orig
+	tophys(r6,r6)
+	PAGE_TO_POINTER(r6,r8,r10)
+end_orig:
+	lwz r0,4(r5)					  /* r0 is maximum */
+	cmplw r7,r0
+	bge- next_copy
+	addi r7,r7,1
+	addi r11,r11,4096
+	b end_copy
+next_copy:
+	lwz r5,8(r5)	/* r5 is copypage */
+	cmpwi r5,0
+	beq- end_copy
+	tophys(r5,r5)
+	PAGE_TO_POINTER(r5,r7,r11)
+end_copy:
+	cmpwi 0,r6,0
+	bc r4,r2,swsusp2_copy_one_page
+swsusp2_end_copyback:
Index: linux-2.6.1-suspend/arch/ppc/power/swsusp2-asm.S
===================================================================
--- linux-2.6.1-suspend/arch/ppc/power/swsusp2-asm.S	(revision 0)
+++ linux-2.6.1-suspend/arch/ppc/power/swsusp2-asm.S	(revision 0)
@@ -0,0 +1,51 @@
+/*
+ * This code base on pmdisk.S by Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ * changed for swsusp2 by Hu Gang <hugang@soulinfo.com>
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
+#include "cpu_reg.S"
+
+	CPU_REG_MEM_DEFINE
+
+	.section .text
+	.align 5
+_GLOBAL(do_swsusp_lowlevel)
+	CPU_REG_STACK_SAVE
+	cmpwi	0,r3,0
+	bne	do_resume
+	bl	save_processor_state
+	bl	do_swsusp2_suspend_1
+	CPU_REG_MEM_SAVE
+	bl	do_swsusp2_suspend_2
+	CPU_REG_MEM_RESTORE_END
+	CPU_REG_STACK_RESTORE
+	
+do_resume:
+	bl save_processor_state
+	bl do_swsusp2_resume_1
+
+	/* Stop pending alitvec streams and memory accesses */
+BEGIN_FTR_SECTION
+	DSSALL
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ 	sync
+
+	CPU_REG_MEM_DISABLE_MMU 
+#include "swsusp2-copyback.S"
+	CPU_REG_MEM_FLUSH_CACHE
+	
+	CPU_REG_MEM_RESTORE
+	bl	do_swsusp2_resume_2
+	bl	restore_processor_state
+	CPU_REG_MEM_RESTORE_END
+	CPU_REG_STACK_RESTORE
+
+	CPU_REG_TURN_ON_MMU
\ No newline at end of file
Index: linux-2.6.1-suspend/arch/ppc/power/cpu_reg.S
===================================================================
--- linux-2.6.1-suspend/arch/ppc/power/cpu_reg.S	(revision 0)
+++ linux-2.6.1-suspend/arch/ppc/power/cpu_reg.S	(revision 0)
@@ -0,0 +1,325 @@
+/*
+ * This code base on pmdisk.S by Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ * changed for swsusp2 by Hu Gang <hugang@soulinfo.com>
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#define SL_SP		0
+#define SL_PC		4
+#define SL_MSR		8
+#define SL_SDR1		0xc
+#define SL_SPRG0	0x10	/* 4 sprg's */
+#define SL_DBAT0	0x20
+#define SL_IBAT0	0x28
+#define SL_DBAT1	0x30
+#define SL_IBAT1	0x38
+#define SL_DBAT2	0x40
+#define SL_IBAT2	0x48
+#define SL_DBAT3	0x50
+#define SL_IBAT3	0x58
+#define SL_TB		0x60
+#define SL_R2		0x68
+#define SL_CR		0x6c
+#define SL_LR		0x70
+#define SL_R12		0x74	/* r12 to r31 */
+#define SL_SIZE		(SL_R12 + 80)
+
+#define CPU_REG_MEM_DEFINE \
+	.section .data					  ; \
+	.align	5					  ; \
+\
+_GLOBAL(cpu_reg_save_area)				  ; \
+	.space	SL_SIZE	
+	
+#define CPU_REG_MEM_SAVE \
+	lis	r11,cpu_reg_save_area@h;\
+	ori	r11,r11,cpu_reg_save_area@l;\
+;\
+	mflr	r0					  ; \
+	stw	r0,SL_LR(r11);\
+	mfcr	r0;\
+	stw	r0,SL_CR(r11);\
+	stw	r1,SL_SP(r11);\
+	stw	r2,SL_R2(r11);\
+	stmw	r12,SL_R12(r11);\
+;\
+	/* Save MSR & SDR1 */;\
+	mfmsr	r4;\
+	stw	r4,SL_MSR(r11);\
+	mfsdr1	r4;\
+	stw	r4,SL_SDR1(r11);\
+;\
+	/* Get a stable timebase and save it */;\
+1:	mftbu	r4;\
+	stw	r4,SL_TB(r11);\
+	mftb	r5;\
+	stw	r5,SL_TB+4(r11);\
+	mftbu	r3;\
+	cmpw	r3,r4;\
+	bne	1b;\
+;\
+	/* Save SPRGs */;\
+	mfsprg	r4,0;\
+	stw	r4,SL_SPRG0(r11);\
+	mfsprg	r4,1;\
+	stw	r4,SL_SPRG0+4(r11);\
+	mfsprg	r4,2;\
+	stw	r4,SL_SPRG0+8(r11);\
+	mfsprg	r4,3;\
+	stw	r4,SL_SPRG0+12(r11);\
+;\
+	/* Save BATs */;\
+	mfdbatu	r4,0;\
+	stw	r4,SL_DBAT0(r11);\
+	mfdbatl	r4,0;\
+	stw	r4,SL_DBAT0+4(r11);\
+	mfdbatu	r4,1;\
+	stw	r4,SL_DBAT1(r11);\
+	mfdbatl	r4,1;\
+	stw	r4,SL_DBAT1+4(r11);\
+	mfdbatu	r4,2;\
+	stw	r4,SL_DBAT2(r11);\
+	mfdbatl	r4,2;\
+	stw	r4,SL_DBAT2+4(r11);\
+	mfdbatu	r4,3;\
+	stw	r4,SL_DBAT3(r11);\
+	mfdbatl	r4,3;\
+	stw	r4,SL_DBAT3+4(r11);\
+	mfibatu	r4,0;\
+	stw	r4,SL_IBAT0(r11);\
+	mfibatl	r4,0;\
+	stw	r4,SL_IBAT0+4(r11);\
+	mfibatu	r4,1;\
+	stw	r4,SL_IBAT1(r11);\
+	mfibatl	r4,1;\
+	stw	r4,SL_IBAT1+4(r11);\
+	mfibatu	r4,2;\
+	stw	r4,SL_IBAT2(r11);\
+	mfibatl	r4,2;\
+	stw	r4,SL_IBAT2+4(r11);\
+	mfibatu	r4,3;\
+	stw	r4,SL_IBAT3(r11);\
+	mfibatl	r4,3;\
+	stw	r4,SL_IBAT3+4(r11);\
+	/* Backup various CPU config stuffs */;\
+	/* bl	__save_cpu_setup; */
+
+#define CPU_REG_MEM_DISABLE_MMU \
+	/* Disable MSR:DR to make sure we don't take a TLB or	;\
+	 * hash miss during the copy, as our hash table will	;\
+	 * for a while be unuseable. For .text, we assume we are;\
+	 * covered by a BAT. This works only for non-G5 at this	;\
+	 * point. G5 will need a better approach, possibly using;\
+	 * a small temporary hash table filled with large mappings,;\
+	 * disabling the MMU completely isn't a good option for	;\
+	 * performance reasons.	;\
+	 * (Note that 750's may have the same performance issue as;\
+	 * the G5 in this case, we should investigate using moving;\
+	 * BATs for these CPUs);\
+	 */;\
+	mfmsr	r0	;\
+	sync	;\
+	rlwinm	r0,r0,0,28,26		/* clear MSR_DR */ ;\
+	mtmsr	r0 ;\
+	sync ;\
+	isync
+
+#define CPU_REG_MEM_FLUSH_CACHE \
+	/* Do a very simple cache flush/inval of the L1 to ensure \
+	 * coherency of the icache \
+	 */ \
+	lis	r3,0x0002 ;\
+	mtctr	r3 ;\
+	li	r3, 0 ;\
+1: ;\
+	lwz	r0,0(r3) ;\
+	addi	r3,r3,0x0020 ;\
+	bdnz	1b ;\
+	isync ;\
+	sync ;\
+;\
+	/* Now flush those cache lines */ ;\
+	lis	r3,0x0002 ;\
+	mtctr	r3 ;\
+	li	r3, 0 ;\
+1:;\
+	dcbf	0,r3 ;\
+	addi	r3,r3,0x0020 ;\
+	bdnz	1b
+
+#define CPU_REG_MEM_RESTORE \
+/* Ok, we are now running with the kernel data of the old;\
+	 * kernel fully restored. We can get to the save area;\
+	 * easily now. As for the rest of the code, it assumes the;\
+	 * loader kernel and the booted one are exactly identical;\
+	 */;\
+	lis	r11,cpu_reg_save_area@h;\
+	ori	r11,r11,cpu_reg_save_area@l;\
+	tophys(r11,r11);\
+	/* Restore various CPU config stuffs */;\
+	/* bl	__restore_cpu_setup; */\
+	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. ;\
+	 * This is a bit hairy as we are running out of those BATs,;\
+	 * but first, our code is probably in the icache, and we are;\
+	 * writing the same value to the BAT, so that should be fine,;\
+	 * though a better solution will have to be found long-term;\
+	 */;\
+	lwz	r4,SL_SDR1(r11);\
+	mtsdr1	r4;\
+	lwz	r4,SL_SPRG0(r11);\
+	mtsprg	0,r4;\
+	lwz	r4,SL_SPRG0+4(r11);\
+	mtsprg	1,r4;\
+	lwz	r4,SL_SPRG0+8(r11);\
+	mtsprg	2,r4;\
+	lwz	r4,SL_SPRG0+12(r11);\
+	mtsprg	3,r4;\
+;\
+/*	lwz	r4,SL_DBAT0(r11);\
+	mtdbatu	0,r4;\
+	lwz	r4,SL_DBAT0+4(r11);\
+	mtdbatl	0,r4;\
+	lwz	r4,SL_DBAT1(r11);\
+	mtdbatu	1,r4;\
+	lwz	r4,SL_DBAT1+4(r11);\
+	mtdbatl	1,r4;\
+	lwz	r4,SL_DBAT2(r11);\
+	mtdbatu	2,r4;\
+	lwz	r4,SL_DBAT2+4(r11);\
+	mtdbatl	2,r4;\
+	lwz	r4,SL_DBAT3(r11);\
+	mtdbatu	3,r4;\
+	lwz	r4,SL_DBAT3+4(r11);\
+	mtdbatl	3,r4;\
+	lwz	r4,SL_IBAT0(r11);\
+	mtibatu	0,r4;\
+	lwz	r4,SL_IBAT0+4(r11);\
+	mtibatl	0,r4;\
+	lwz	r4,SL_IBAT1(r11);\
+	mtibatu	1,r4;\
+	lwz	r4,SL_IBAT1+4(r11);\
+	mtibatl	1,r4;\
+	lwz	r4,SL_IBAT2(r11);\
+	mtibatu	2,r4;\
+	lwz	r4,SL_IBAT2+4(r11);\
+	mtibatl	2,r4;\
+	lwz	r4,SL_IBAT3(r11);\
+	mtibatu	3,r4;\
+	lwz	r4,SL_IBAT3+4(r11);\
+	mtibatl	3,r4;\
+; */ \
+BEGIN_FTR_SECTION;\
+	li	r4,0;\
+	mtspr	SPRN_DBAT4U,r4;\
+	mtspr	SPRN_DBAT4L,r4;\
+	mtspr	SPRN_DBAT5U,r4;\
+	mtspr	SPRN_DBAT5L,r4;\
+	mtspr	SPRN_DBAT6U,r4;\
+	mtspr	SPRN_DBAT6L,r4;\
+	mtspr	SPRN_DBAT7U,r4;\
+	mtspr	SPRN_DBAT7L,r4;\
+	mtspr	SPRN_IBAT4U,r4;\
+	mtspr	SPRN_IBAT4L,r4;\
+	mtspr	SPRN_IBAT5U,r4;\
+	mtspr	SPRN_IBAT5L,r4;\
+	mtspr	SPRN_IBAT6U,r4;\
+	mtspr	SPRN_IBAT6L,r4;\
+	mtspr	SPRN_IBAT7U,r4;\
+	mtspr	SPRN_IBAT7L,r4;\
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS);\
+;\
+	/* Flush all TLBs */;\
+	lis	r4,0x1000;\
+1:	addic.	r4,r4,-0x1000;\
+	tlbie	r4;\
+	blt	1b;\
+	sync;\
+;\
+	/* restore the MSR and turn on the MMU */;\
+	lwz	r3,SL_MSR(r11);\
+	bl	turn_on_mmu;\
+	tovirt(r11,r11);\
+;\
+	/* Restore TB */;\
+	li	r3,0;\
+	mttbl	r3;\
+	lwz	r3,SL_TB(r11);\
+	lwz	r4,SL_TB+4(r11);\
+	mttbu	r3;\
+	mttbl	r4;\
+; \
+	lwz	r0,SL_CR(r11);\
+	mtcr	r0;\
+	lwz	r2,SL_R2(r11);\
+	lmw	r12,SL_R12(r11);\
+	lwz	r1,SL_SP(r11);\
+	lwz	r4,SL_LR(r11)
+
+#define CPU_REG_MEM_RESTORE_END \
+	/* Restore LR from the save area */		  ; \
+	lis	r11,cpu_reg_save_area@h			  ; \
+	ori	r11,r11,cpu_reg_save_area@l		  ; \
+	lwz	r0,SL_CR(r11)				  ; \
+	mtcr r0					  ; \
+	lwz	r2,SL_R2(r11)				  ; \
+	lmw	r12,SL_R12(r11)				  ; \
+	lwz	r1,SL_SP(r11)
+
+#define CPU_REG_TURN_ON_MMU \
+/* FIXME:This construct is actually not useful since we don't shut ; \
+ * down the instruction MMU, we could just flip back MSR-DR on.	; \
+ */							  ; \
+turn_on_mmu:						  ; \
+	mflr	r4					  ; \
+	mtsrr0	r4					  ; \
+	mtsrr1	r3					  ; \
+	sync						  ; \
+	isync						  ; \
+	rfi
+
+#define CPU_REG_STACK_SAVE \
+	mflr	r0					  ; \
+	stw	r0,4(r1)				  ; \
+	stwu	r1,-SL_SIZE(r1)				  ; \
+	mfcr	r0					  ; \
+	stw	r0,SL_CR(r1)				  ; \
+	stw	r2,SL_R2(r1)				  ; \
+	stmw	r12,SL_R12(r1)				  ; \
+	/* Save SPRGs */				  ; \
+	mfsprg	r4,0					  ; \
+	stw	r4,SL_SPRG0(r1)				  ; \
+	mfsprg	r4,1					  ; \
+	stw	r4,SL_SPRG0+4(r1)			  ; \
+	mfsprg	r4,2					  ; \
+	stw	r4,SL_SPRG0+8(r1)			  ; \
+	mfsprg	r4,3					  ; \
+	stw	r4,SL_SPRG0+12(r1)	
+
+#define CPU_REG_STACK_RESTORE \
+	lwz	r4,SL_SPRG0(r1)				  ; \
+	mtsprg	0,r4					  ; \
+	lwz	r4,SL_SPRG0+4(r1)			  ; \
+	mtsprg	1,r4					  ; \
+	lwz	r4,SL_SPRG0+8(r1)			  ; \
+	mtsprg	2,r4					  ; \
+	lwz	r4,SL_SPRG0+12(r1)			  ; \
+	mtsprg	3,r4					  ; \
+	lwz	r0,SL_CR(r1)				  ; \
+	mtcr	r0					  ; \
+	lwz	r2,SL_R2(r1)				  ; \
+	lmw	r12,SL_R12(r1)				  ; \
+	addi	r1,r1,SL_SIZE				  ; \
+	lwz	r0,4(r1)				  ; \
+	mtlr	r0					  ; \
+	blr
Index: linux-2.6.1-suspend/arch/ppc/power/swsusp2.c
===================================================================
--- linux-2.6.1-suspend/arch/ppc/power/swsusp2.c	(revision 0)
+++ linux-2.6.1-suspend/arch/ppc/power/swsusp2.c	(revision 0)
@@ -0,0 +1,170 @@
+ /*
+  * Copyright 2003 Nigel Cunningham.
+  *
+  * This is the code that the code in swsusp2-asm.S for
+  * copying back the original kernel is based upon. It
+  * was based upon code that is...
+  * Copyright 2001-2002 Pavel Machek <pavel@suse.cz>
+  * Based on code
+  * Copyright 2001 Patrick Mochel <mochel@osdl.org>
+  * Copyright 2004 Hu Gang <hugang@soulinfo.com
+  *  port to PowerPC
+  */
+#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/irq.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/suspend-debug.h>
+#include <linux/suspend-common.h>
+#include <asm/uaccess.h>
+#if 0
+/* Local variables for do_swsusp2_suspend */
+volatile static int state1 __nosavedata = 0;
+volatile static int state2 __nosavedata = 0;
+volatile static int state3 __nosavedata = 0;
+volatile static int loop __nosavedata = 0;
+volatile static struct range *origrange __nosavedata;
+volatile static struct range *copyrange __nosavedata;
+volatile static int origoffset __nosavedata;
+volatile static int copyoffset __nosavedata;
+volatile static unsigned long * origpage __nosavedata;
+volatile static unsigned long * copypage __nosavedata;
+#endif
+
+//volatile static int orig_min_free __nosavedata;
+#ifndef CONFIG_SMP
+//static unsigned long c_loops_per_jiffy_ref __nosavedata = 0;
+//static unsigned long cpu_khz_ref __nosavedata = 0;
+#endif
+
+extern void do_swsusp2_suspend_1(void);
+extern void do_swsusp2_suspend_2(void);
+extern void do_swsusp2_resume_1(void);
+extern void do_swsusp2_resume_2(void);
+extern struct pagedir __nosavedata pagedir_resume;
+
+/*
+ * FIXME: This function should really be written in assembly. Actually
+ * requirement is that it does not touch stack, because %esp will be
+ * wrong during resume before restore_processor_context(). Check
+ * assembly if you modify this.
+ */
+#if 0
+static inline void pre_copyback(void)
+{
+#ifdef CONFIG_PREEMPT
+	/*
+	 * Preempt disabled in kernel we're about to restore.
+	 * Make sure we match state now.
+	 */
+	preempt_disable();
+	PRINTPREEMPTCOUNT("Prior to copying old kernel back.");
+#endif
+
+	state1 = swsusp_action;
+	state2 = swsusp_debug_state;
+	state3 = console_loglevel;
+
+#ifndef CONFIG_SMP
+	//c_loops_per_jiffy_ref = cpu_data->loops_per_jiffy;
+	//cpu_khz_ref = cpu_khz;
+#endif
+}
+static inline void post_copyback(void)
+{
+#ifndef CONFIG_SMP
+	//cpu_data->loops_per_jiffy = c_loops_per_jiffy_ref;
+	//loops_per_jiffy = c_loops_per_jiffy_ref;
+	//cpu_khz = cpu_khz_ref;
+#endif
+	swsusp_action = state1;
+	swsusp_debug_state = state2;
+	console_loglevel = state3;
+	//swsusp_min_free = orig_min_free;
+
+}
+#endif
+static inline void do_swsusp2_copyback(void)
+{
+	/* PowerPC has a lots register, use local register is possible */
+	register int origoffset, copyoffset;
+	register unsigned long * origpage, * copypage;
+	register struct range *origrange, *copyrange;
+//	register int pagesize;
+
+//	pre_copyback();
+
+	origrange = pagedir_resume.origranges.first;
+//	pagesize = pagedir_resume.pageset_size;
+//	printk("%d\n", pagesize);
+	origoffset = origrange->minimum;
+	origpage = (unsigned long *) (page_address(mem_map + origoffset));
+	
+	copyrange = pagedir_resume.destranges.first;
+	copyoffset = copyrange->minimum;
+	copypage = (unsigned long *) (page_address(mem_map + copyoffset));
+	//orig_min_free = swsusp_min_free;
+
+	while (origrange) {
+		register int loop;
+		for (loop = 0; loop < (PAGE_SIZE / sizeof(unsigned long)); loop++)
+			*(origpage + loop) = *(copypage + loop);
+		
+		if (origoffset < origrange->maximum) {
+			origoffset++;
+			origpage += (PAGE_SIZE / sizeof(unsigned long));
+		} else {
+			origrange = origrange->next;
+			if (origrange) {
+				origoffset = origrange->minimum;
+				origpage = (unsigned long *) (page_address(mem_map + origoffset));
+			}
+		}
+
+		if (copyoffset < copyrange->maximum) {
+			copyoffset++;
+			copypage += (PAGE_SIZE / sizeof(unsigned long));
+		} else {
+			copyrange = copyrange->next;
+			if (copyrange) {
+				copyoffset = copyrange->minimum;
+				copypage = (unsigned long *) (page_address(mem_map + copyoffset));
+			}
+		}
+	}
+	
+/* Ahah, we now run with our old stack, and with registers copied from
+   suspend time */
+
+//	post_copyback();
+}
+
+void do_swsusp_lowlevel(int resume)
+{
+	if (!resume) {
+		do_swsusp2_suspend_1();
+		save_processor_state();
+		/* saving stack */
+		
+		do_swsusp2_suspend_2();
+		return;
+	}
+
+	/* setup swapper_pg_dir in x86 */
+
+	do_swsusp2_resume_1();
+	do_swsusp2_copyback();
+	/* setup segment register */
+	restore_processor_state();
+	do_swsusp2_resume_2();
+}
Index: linux-2.6.1-suspend/arch/ppc/power/cpu.c
===================================================================
--- linux-2.6.1-suspend/arch/ppc/power/cpu.c	(revision 0)
+++ linux-2.6.1-suspend/arch/ppc/power/cpu.c	(revision 0)
@@ -0,0 +1,72 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <linux/irq.h>
+#include <linux/root_dev.h>
+#include <linux/suspend.h>
+#include <linux/delay.h>
+
+#include <asm/mmu_context.h>
+
+extern void enable_kernel_altivec(void);
+
+static inline void do_pmu_suspend(void)
+{
+	printk("suspend pmu\n");	
+	pmu_suspend();
+	printk(".\n");
+}
+
+static inline void do_pmu_resume(void)
+{
+	struct adb_request req;
+	printk("resume pmu\n");	
+	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+	pmu_wait_complete(&req);
+	
+	/* Resume PMU event interrupts */
+	pmu_resume();	
+	printk(".\n");
+}
+
+void save_processor_state(void)
+{
+	printk("save processor state\n");
+	pmu_suspend();
+	printk(".\n");
+	printk("current is 0x%x\n", current);
+	mdelay(1000);
+}
+
+void restore_processor_state(void)
+{
+	printk("current is 0x%x\n", current);
+	mdelay(1000);
+	printk("seting context\n");
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
+
+	printk("do pmu resume\n");
+	do_pmu_resume();
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif
+	printk("enable kernel fp\n");
+	enable_kernel_fp();
+	printk(".\n");
+}
+
+EXPORT_SYMBOL(save_processor_state);
+EXPORT_SYMBOL(restore_processor_state);
Index: linux-2.6.1-suspend/arch/ppc/power/Makefile
===================================================================
--- linux-2.6.1-suspend/arch/ppc/power/Makefile	(revision 0)
+++ linux-2.6.1-suspend/arch/ppc/power/Makefile	(revision 0)
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PM) += cpu.o
+obj-$(CONFIG_SOFTWARE_SUSPEND2) += swsusp2-asm.o

[-- Attachment #3: suspend --]
[-- Type: application/octet-stream, Size: 657 bytes --]

#!/bin/sh

chvt 1
swapon -a
sync
sync
#hwclock --systohc
/etc/init.d/cfsd stop
/etc/init.d/aumix stop
/etc/init.d/networking stop

for i in `lsmod | awk '{print $1}'`
do
	rmmod $i
done
for i in `lsmod | awk '{print $1}'`
do
	rmmod $i
done

mount -t proc none /proc
mount /sys

echo -n "disk" > /sys/power/state
echo -n "6" > /proc/swsusp/default_console_level
echo -n "1" > /proc/swsusp/slow
echo -n "1" > /proc/swsusp/reboot
echo -n "1" > /proc/swsusp/debug_sections
echo -n "1" > /proc/swsusp/activate

for i in `grep -v ^# /etc/modules`
do
	modprobe $i
done

/etc/init.d/networking start
/etc/init.d/cfsd start
/etc/init.d/aumix start
#hwclock --hctosys

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc), swsusp2 works.
  2004-01-28 12:22                         ` Hugang
@ 2004-01-28 13:23                           ` Hugang
       [not found]                             ` <20040129012720.1385c41a@localhost>
  2004-01-29  0:34                           ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
  1 sibling, 1 reply; 80+ messages in thread
From: Hugang @ 2004-01-28 13:23 UTC (permalink / raw)
  To: Hugang
  Cc: ncunningham, Benjamin Herrenschmidt, Pavel Machek,
	Patrick Mochel, Linux Kernel Mailing List, linuxppc-dev list

[-- Attachment #1: Type: text/plain, Size: 1959 bytes --]

On Wed, 28 Jan 2004 20:22:17 +0800
Hugang <hugang@soulinfo.com> wrote:

> HaHa, Here is swsusp2 patch for ppc. Now it WORKS fine.
> 
> The code base for testing, any comments and testing are welcome.
previous patch, I has forgot a file, here is it.
Index: arch/ppc/Makefile
===================================================================
--- arch/ppc/Makefile   (revision 192)
+++ arch/ppc/Makefile   (working copy)
@@ -44,6 +44,7 @@
 drivers-$(CONFIG_4xx)      += arch/ppc/4xx_io/
 drivers-$(CONFIG_8260)     += arch/ppc/8260_io/
 drivers-$(CONFIG_OCP)      += arch/ppc/ocp/
+drivers-$(CONFIG_PM)       += arch/ppc/power/

 BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm

Attached file that is diff for the lastest swsusp2.
 for clean 2.6.1 + 2.6.1-swsusp2-rc3 + swsusp2-core-rc5

swsusp2 for ppc like very stable, I has been do 5 times, has no
problems.

Nice day.

- SWSUSP core    : 2.0-rc4
- Kernel Version : 2.6.1
- Version spec.  : 2.0.0
- Compiler vers. : 2.95
ide_cd cdrom nfs lockd sunrpc af_packet ohci_hcd snd_pcm_oss
snd_mixer_oss i2c_keywest snd_powermac snd_pcm snd_page_alloc snd_timer
snd soundcore i2c_core ohci1394 ieee1394 hid sungem sungem_phy reiserfs
dm_mod uninorth_agp agpgart usbcore - Attempt number : 5
- Pageset sizes  : 7201 and 56927 (56927 low).
- Parameters     : 0 1 1 0 0 32
- Calculations   : Image size: 2. Ram to suspend: 631.
- Limits         : 65536 pages RAM. Initial boot: 63232.
- Overall expected compression percentage: 2.
- Swapwriter active.
  Attempting to automatically swapon: .
  Swap available for image: 110002.
- GZIP compressor enabled.
  Compressed 129732608 bytes into 103573980.
  Image compressed by 20 percent.
- LZF Compressor enabled.
  Compressed 262668288 bytes into 129727869.
  Image compressed by 50 percent.
- Debugging compiled in.
- Max ranges used: 11352
-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

[-- Attachment #2: ppc_swsusp2_2.diff --]
[-- Type: text/plain, Size: 21206 bytes --]

Index: kernel/power/swsusp2.c
===================================================================
--- kernel/power/swsusp2.c	(revision 193)
+++ kernel/power/swsusp2.c	(working copy)
@@ -54,7 +54,9 @@
 
 #include <linux/suspend-common.h>
 #include <linux/suspend-version-specific.h>
+#ifdef  CONFIG_X86
 #include <asm/i387.h> /* for kernel_fpu_end */
+#endif
 #ifdef	CONFIG_KDB
 #include <linux/kdb.h>
 #endif	/* CONFIG_KDB */
@@ -343,7 +345,9 @@
 	preempt_enable();
 #endif
 
+#ifdef CONFIG_X86
 	kernel_fpu_end();
+#endif
 
 	PRINTPREEMPTCOUNT("Prior to resuming drivers.");
 
Index: include/asm-ppc/suspend.h
===================================================================
--- include/asm-ppc/suspend.h	(revision 193)
+++ include/asm-ppc/suspend.h	(working copy)
@@ -0,0 +1,14 @@
+#ifndef _PPC_SUSPEND_H
+#define _PPC_SUSPEND_H
+
+static inline void flush_tlb_all(void)
+{
+	/* Flush all TLBs */
+	__asm__ __volatile__("lis 4, 0x1000");
+	__asm__ __volatile__("1: addic. 4,4,-0x1000");
+	__asm__ __volatile__("tlbie 4");
+	__asm__ __volatile__("blt 1b");
+	__asm__ __volatile__("sync");
+}
+
+#endif
Index: arch/ppc/Kconfig
===================================================================
--- arch/ppc/Kconfig	(revision 193)
+++ arch/ppc/Kconfig	(working copy)
@@ -193,6 +193,8 @@
 
 	  If in doubt, say Y here.
 
+source kernel/power/Kconfig
+
 source arch/ppc/platforms/4xx/Kconfig
 
 config PPC64BRIDGE
Index: arch/ppc/kernel/vmlinux.lds.S
===================================================================
--- arch/ppc/kernel/vmlinux.lds.S	(revision 192)
+++ arch/ppc/kernel/vmlinux.lds.S	(working copy)
@@ -72,6 +72,12 @@
     CONSTRUCTORS
   }
 
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
   . = ALIGN(32);
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
Index: arch/ppc/kernel/signal.c
===================================================================
--- arch/ppc/kernel/signal.c	(revision 192)
+++ arch/ppc/kernel/signal.c	(working copy)
@@ -28,6 +28,7 @@
 #include <linux/elf.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
+#include <linux/suspend.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -552,6 +553,11 @@
 	unsigned long frame, newsp;
 	int signr, ret;
 
+	if (current->flags & PF_FREEZE) {
+		refrigerator(PF_FREEZE);
+		return 0;
+	}
+
 	if (!oldset)
 		oldset = &current->blocked;
 
Index: arch/ppc/power/swsusp2-copyback.S
===================================================================
--- arch/ppc/power/swsusp2-copyback.S	(revision 193)
+++ arch/ppc/power/swsusp2-copyback.S	(working copy)
@@ -0,0 +1,73 @@
+#define PAGE_TO_POINTER(in, out, p)	\
+	lwz out,0(in)					  ; \
+	slwi r9,out,2					  ; \
+	add r9,r9,out					  ; \
+	slwi r9,r9,3					  ; \
+	mullw r9,r9,r4					  ; \
+	slwi r9,r9,9					  ; \
+	addis p,r9,0xc000				  ; \
+	tophys(p,p)
+
+	.section ".text"
+swsusp2_copyback:
+	lis r20,pagedir_resume@ha	/* can't ture this is right FIXME */
+	addi r20,r20,pagedir_resume@l
+	tophys(r20,r20)
+#if 0
+	lwz	r4,4(r20)
+	twi	31,r0,0	/* triger trap */
+#endif	
+	lis r4,0xcccc /* FIXME */
+	ori r4,r4,52429
+
+	lwz r6,12(r20)		/* r6 is origranges.first */
+	cmpwi r6,0
+	beq- swsusp2_end_copyback
+		
+	tophys(r6,r6)
+	PAGE_TO_POINTER(r6,r8,r10)				  
+
+	lwz r5,56(r20)		/* r5 is copyranges.first */
+	tophys(r5,r5)
+	PAGE_TO_POINTER(r5,r7,r11) 
+	
+swsusp2_copy_one_page:
+	li r0,1024		/* r9 is loop */
+	mtctr r0		/* prepare for branch */
+	li r9,0
+swsusp2_copy_data:
+	lwzx r0,r9,r11
+	stwx r0,r9,r10
+	addi r9,r9,4
+
+	bdnz swsusp2_copy_data
+
+	lwz r0,4(r6)					  /* r0 is maximum */
+	cmplw r8,r0
+	bge- next_orig
+	addi r8,r8,1
+	addi r10,r10,4096
+	b end_orig
+next_orig:
+	lwz r6,8(r6)	/* r6 origrange */
+	cmpwi r6,0
+	beq- end_orig
+	tophys(r6,r6)
+	PAGE_TO_POINTER(r6,r8,r10)
+end_orig:
+	lwz r0,4(r5)					  /* r0 is maximum */
+	cmplw r7,r0
+	bge- next_copy
+	addi r7,r7,1
+	addi r11,r11,4096
+	b end_copy
+next_copy:
+	lwz r5,8(r5)	/* r5 is copypage */
+	cmpwi r5,0
+	beq- end_copy
+	tophys(r5,r5)
+	PAGE_TO_POINTER(r5,r7,r11)
+end_copy:
+	cmpwi 0,r6,0
+	bc r4,r2,swsusp2_copy_one_page
+swsusp2_end_copyback:
Index: arch/ppc/power/swsusp2-asm.S
===================================================================
--- arch/ppc/power/swsusp2-asm.S	(revision 193)
+++ arch/ppc/power/swsusp2-asm.S	(working copy)
@@ -0,0 +1,51 @@
+/*
+ * This code base on pmdisk.S by Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ * changed for swsusp2 by Hu Gang <hugang@soulinfo.com>
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
+#include "cpu_reg.S"
+
+	CPU_REG_MEM_DEFINE
+
+	.section .text
+	.align 5
+_GLOBAL(do_swsusp_lowlevel)
+	CPU_REG_STACK_SAVE
+	cmpwi	0,r3,0
+	bne	do_resume
+	bl	save_processor_state
+	bl	do_swsusp2_suspend_1
+	CPU_REG_MEM_SAVE
+	bl	do_swsusp2_suspend_2
+	CPU_REG_MEM_RESTORE_END
+	CPU_REG_STACK_RESTORE
+	
+do_resume:
+	bl save_processor_state
+	bl do_swsusp2_resume_1
+
+	/* Stop pending alitvec streams and memory accesses */
+BEGIN_FTR_SECTION
+	DSSALL
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ 	sync
+
+	CPU_REG_MEM_DISABLE_MMU 
+#include "swsusp2-copyback.S"
+	CPU_REG_MEM_FLUSH_CACHE
+	
+	CPU_REG_MEM_RESTORE
+	bl	do_swsusp2_resume_2
+	bl	restore_processor_state
+	CPU_REG_MEM_RESTORE_END
+	CPU_REG_STACK_RESTORE
+
+	CPU_REG_TURN_ON_MMU
\ No newline at end of file
Index: arch/ppc/power/cpu_reg.S
===================================================================
--- arch/ppc/power/cpu_reg.S	(revision 193)
+++ arch/ppc/power/cpu_reg.S	(working copy)
@@ -0,0 +1,325 @@
+/*
+ * This code base on pmdisk.S by Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ * changed for swsusp2 by Hu Gang <hugang@soulinfo.com>
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#define SL_SP		0
+#define SL_PC		4
+#define SL_MSR		8
+#define SL_SDR1		0xc
+#define SL_SPRG0	0x10	/* 4 sprg's */
+#define SL_DBAT0	0x20
+#define SL_IBAT0	0x28
+#define SL_DBAT1	0x30
+#define SL_IBAT1	0x38
+#define SL_DBAT2	0x40
+#define SL_IBAT2	0x48
+#define SL_DBAT3	0x50
+#define SL_IBAT3	0x58
+#define SL_TB		0x60
+#define SL_R2		0x68
+#define SL_CR		0x6c
+#define SL_LR		0x70
+#define SL_R12		0x74	/* r12 to r31 */
+#define SL_SIZE		(SL_R12 + 80)
+
+#define CPU_REG_MEM_DEFINE \
+	.section .data					  ; \
+	.align	5					  ; \
+\
+_GLOBAL(cpu_reg_save_area)				  ; \
+	.space	SL_SIZE	
+	
+#define CPU_REG_MEM_SAVE \
+	lis	r11,cpu_reg_save_area@h;\
+	ori	r11,r11,cpu_reg_save_area@l;\
+;\
+	mflr	r0					  ; \
+	stw	r0,SL_LR(r11);\
+	mfcr	r0;\
+	stw	r0,SL_CR(r11);\
+	stw	r1,SL_SP(r11);\
+	stw	r2,SL_R2(r11);\
+	stmw	r12,SL_R12(r11);\
+;\
+	/* Save MSR & SDR1 */;\
+	mfmsr	r4;\
+	stw	r4,SL_MSR(r11);\
+	mfsdr1	r4;\
+	stw	r4,SL_SDR1(r11);\
+;\
+	/* Get a stable timebase and save it */;\
+1:	mftbu	r4;\
+	stw	r4,SL_TB(r11);\
+	mftb	r5;\
+	stw	r5,SL_TB+4(r11);\
+	mftbu	r3;\
+	cmpw	r3,r4;\
+	bne	1b;\
+;\
+	/* Save SPRGs */;\
+	mfsprg	r4,0;\
+	stw	r4,SL_SPRG0(r11);\
+	mfsprg	r4,1;\
+	stw	r4,SL_SPRG0+4(r11);\
+	mfsprg	r4,2;\
+	stw	r4,SL_SPRG0+8(r11);\
+	mfsprg	r4,3;\
+	stw	r4,SL_SPRG0+12(r11);\
+;\
+	/* Save BATs */;\
+	mfdbatu	r4,0;\
+	stw	r4,SL_DBAT0(r11);\
+	mfdbatl	r4,0;\
+	stw	r4,SL_DBAT0+4(r11);\
+	mfdbatu	r4,1;\
+	stw	r4,SL_DBAT1(r11);\
+	mfdbatl	r4,1;\
+	stw	r4,SL_DBAT1+4(r11);\
+	mfdbatu	r4,2;\
+	stw	r4,SL_DBAT2(r11);\
+	mfdbatl	r4,2;\
+	stw	r4,SL_DBAT2+4(r11);\
+	mfdbatu	r4,3;\
+	stw	r4,SL_DBAT3(r11);\
+	mfdbatl	r4,3;\
+	stw	r4,SL_DBAT3+4(r11);\
+	mfibatu	r4,0;\
+	stw	r4,SL_IBAT0(r11);\
+	mfibatl	r4,0;\
+	stw	r4,SL_IBAT0+4(r11);\
+	mfibatu	r4,1;\
+	stw	r4,SL_IBAT1(r11);\
+	mfibatl	r4,1;\
+	stw	r4,SL_IBAT1+4(r11);\
+	mfibatu	r4,2;\
+	stw	r4,SL_IBAT2(r11);\
+	mfibatl	r4,2;\
+	stw	r4,SL_IBAT2+4(r11);\
+	mfibatu	r4,3;\
+	stw	r4,SL_IBAT3(r11);\
+	mfibatl	r4,3;\
+	stw	r4,SL_IBAT3+4(r11);\
+	/* Backup various CPU config stuffs */;\
+	/* bl	__save_cpu_setup; */
+
+#define CPU_REG_MEM_DISABLE_MMU \
+	/* Disable MSR:DR to make sure we don't take a TLB or	;\
+	 * hash miss during the copy, as our hash table will	;\
+	 * for a while be unuseable. For .text, we assume we are;\
+	 * covered by a BAT. This works only for non-G5 at this	;\
+	 * point. G5 will need a better approach, possibly using;\
+	 * a small temporary hash table filled with large mappings,;\
+	 * disabling the MMU completely isn't a good option for	;\
+	 * performance reasons.	;\
+	 * (Note that 750's may have the same performance issue as;\
+	 * the G5 in this case, we should investigate using moving;\
+	 * BATs for these CPUs);\
+	 */;\
+	mfmsr	r0	;\
+	sync	;\
+	rlwinm	r0,r0,0,28,26		/* clear MSR_DR */ ;\
+	mtmsr	r0 ;\
+	sync ;\
+	isync
+
+#define CPU_REG_MEM_FLUSH_CACHE \
+	/* Do a very simple cache flush/inval of the L1 to ensure \
+	 * coherency of the icache \
+	 */ \
+	lis	r3,0x0002 ;\
+	mtctr	r3 ;\
+	li	r3, 0 ;\
+1: ;\
+	lwz	r0,0(r3) ;\
+	addi	r3,r3,0x0020 ;\
+	bdnz	1b ;\
+	isync ;\
+	sync ;\
+;\
+	/* Now flush those cache lines */ ;\
+	lis	r3,0x0002 ;\
+	mtctr	r3 ;\
+	li	r3, 0 ;\
+1:;\
+	dcbf	0,r3 ;\
+	addi	r3,r3,0x0020 ;\
+	bdnz	1b
+
+#define CPU_REG_MEM_RESTORE \
+/* Ok, we are now running with the kernel data of the old;\
+	 * kernel fully restored. We can get to the save area;\
+	 * easily now. As for the rest of the code, it assumes the;\
+	 * loader kernel and the booted one are exactly identical;\
+	 */;\
+	lis	r11,cpu_reg_save_area@h;\
+	ori	r11,r11,cpu_reg_save_area@l;\
+	tophys(r11,r11);\
+	/* Restore various CPU config stuffs */;\
+	/* bl	__restore_cpu_setup; */\
+	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. ;\
+	 * This is a bit hairy as we are running out of those BATs,;\
+	 * but first, our code is probably in the icache, and we are;\
+	 * writing the same value to the BAT, so that should be fine,;\
+	 * though a better solution will have to be found long-term;\
+	 */;\
+	lwz	r4,SL_SDR1(r11);\
+	mtsdr1	r4;\
+	lwz	r4,SL_SPRG0(r11);\
+	mtsprg	0,r4;\
+	lwz	r4,SL_SPRG0+4(r11);\
+	mtsprg	1,r4;\
+	lwz	r4,SL_SPRG0+8(r11);\
+	mtsprg	2,r4;\
+	lwz	r4,SL_SPRG0+12(r11);\
+	mtsprg	3,r4;\
+;\
+/*	lwz	r4,SL_DBAT0(r11);\
+	mtdbatu	0,r4;\
+	lwz	r4,SL_DBAT0+4(r11);\
+	mtdbatl	0,r4;\
+	lwz	r4,SL_DBAT1(r11);\
+	mtdbatu	1,r4;\
+	lwz	r4,SL_DBAT1+4(r11);\
+	mtdbatl	1,r4;\
+	lwz	r4,SL_DBAT2(r11);\
+	mtdbatu	2,r4;\
+	lwz	r4,SL_DBAT2+4(r11);\
+	mtdbatl	2,r4;\
+	lwz	r4,SL_DBAT3(r11);\
+	mtdbatu	3,r4;\
+	lwz	r4,SL_DBAT3+4(r11);\
+	mtdbatl	3,r4;\
+	lwz	r4,SL_IBAT0(r11);\
+	mtibatu	0,r4;\
+	lwz	r4,SL_IBAT0+4(r11);\
+	mtibatl	0,r4;\
+	lwz	r4,SL_IBAT1(r11);\
+	mtibatu	1,r4;\
+	lwz	r4,SL_IBAT1+4(r11);\
+	mtibatl	1,r4;\
+	lwz	r4,SL_IBAT2(r11);\
+	mtibatu	2,r4;\
+	lwz	r4,SL_IBAT2+4(r11);\
+	mtibatl	2,r4;\
+	lwz	r4,SL_IBAT3(r11);\
+	mtibatu	3,r4;\
+	lwz	r4,SL_IBAT3+4(r11);\
+	mtibatl	3,r4;\
+; */ \
+BEGIN_FTR_SECTION;\
+	li	r4,0;\
+	mtspr	SPRN_DBAT4U,r4;\
+	mtspr	SPRN_DBAT4L,r4;\
+	mtspr	SPRN_DBAT5U,r4;\
+	mtspr	SPRN_DBAT5L,r4;\
+	mtspr	SPRN_DBAT6U,r4;\
+	mtspr	SPRN_DBAT6L,r4;\
+	mtspr	SPRN_DBAT7U,r4;\
+	mtspr	SPRN_DBAT7L,r4;\
+	mtspr	SPRN_IBAT4U,r4;\
+	mtspr	SPRN_IBAT4L,r4;\
+	mtspr	SPRN_IBAT5U,r4;\
+	mtspr	SPRN_IBAT5L,r4;\
+	mtspr	SPRN_IBAT6U,r4;\
+	mtspr	SPRN_IBAT6L,r4;\
+	mtspr	SPRN_IBAT7U,r4;\
+	mtspr	SPRN_IBAT7L,r4;\
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS);\
+;\
+	/* Flush all TLBs */;\
+	lis	r4,0x1000;\
+1:	addic.	r4,r4,-0x1000;\
+	tlbie	r4;\
+	blt	1b;\
+	sync;\
+;\
+	/* restore the MSR and turn on the MMU */;\
+	lwz	r3,SL_MSR(r11);\
+	bl	turn_on_mmu;\
+	tovirt(r11,r11);\
+;\
+	/* Restore TB */;\
+	li	r3,0;\
+	mttbl	r3;\
+	lwz	r3,SL_TB(r11);\
+	lwz	r4,SL_TB+4(r11);\
+	mttbu	r3;\
+	mttbl	r4;\
+; \
+	lwz	r0,SL_CR(r11);\
+	mtcr	r0;\
+	lwz	r2,SL_R2(r11);\
+	lmw	r12,SL_R12(r11);\
+	lwz	r1,SL_SP(r11);\
+	lwz	r4,SL_LR(r11)
+
+#define CPU_REG_MEM_RESTORE_END \
+	/* Restore LR from the save area */		  ; \
+	lis	r11,cpu_reg_save_area@h			  ; \
+	ori	r11,r11,cpu_reg_save_area@l		  ; \
+	lwz	r0,SL_CR(r11)				  ; \
+	mtcr r0					  ; \
+	lwz	r2,SL_R2(r11)				  ; \
+	lmw	r12,SL_R12(r11)				  ; \
+	lwz	r1,SL_SP(r11)
+
+#define CPU_REG_TURN_ON_MMU \
+/* FIXME:This construct is actually not useful since we don't shut ; \
+ * down the instruction MMU, we could just flip back MSR-DR on.	; \
+ */							  ; \
+turn_on_mmu:						  ; \
+	mflr	r4					  ; \
+	mtsrr0	r4					  ; \
+	mtsrr1	r3					  ; \
+	sync						  ; \
+	isync						  ; \
+	rfi
+
+#define CPU_REG_STACK_SAVE \
+	mflr	r0					  ; \
+	stw	r0,4(r1)				  ; \
+	stwu	r1,-SL_SIZE(r1)				  ; \
+	mfcr	r0					  ; \
+	stw	r0,SL_CR(r1)				  ; \
+	stw	r2,SL_R2(r1)				  ; \
+	stmw	r12,SL_R12(r1)				  ; \
+	/* Save SPRGs */				  ; \
+	mfsprg	r4,0					  ; \
+	stw	r4,SL_SPRG0(r1)				  ; \
+	mfsprg	r4,1					  ; \
+	stw	r4,SL_SPRG0+4(r1)			  ; \
+	mfsprg	r4,2					  ; \
+	stw	r4,SL_SPRG0+8(r1)			  ; \
+	mfsprg	r4,3					  ; \
+	stw	r4,SL_SPRG0+12(r1)	
+
+#define CPU_REG_STACK_RESTORE \
+	lwz	r4,SL_SPRG0(r1)				  ; \
+	mtsprg	0,r4					  ; \
+	lwz	r4,SL_SPRG0+4(r1)			  ; \
+	mtsprg	1,r4					  ; \
+	lwz	r4,SL_SPRG0+8(r1)			  ; \
+	mtsprg	2,r4					  ; \
+	lwz	r4,SL_SPRG0+12(r1)			  ; \
+	mtsprg	3,r4					  ; \
+	lwz	r0,SL_CR(r1)				  ; \
+	mtcr	r0					  ; \
+	lwz	r2,SL_R2(r1)				  ; \
+	lmw	r12,SL_R12(r1)				  ; \
+	addi	r1,r1,SL_SIZE				  ; \
+	lwz	r0,4(r1)				  ; \
+	mtlr	r0					  ; \
+	blr
Index: arch/ppc/power/swsusp2.c
===================================================================
--- arch/ppc/power/swsusp2.c	(revision 193)
+++ arch/ppc/power/swsusp2.c	(working copy)
@@ -0,0 +1,170 @@
+ /*
+  * Copyright 2003 Nigel Cunningham.
+  *
+  * This is the code that the code in swsusp2-asm.S for
+  * copying back the original kernel is based upon. It
+  * was based upon code that is...
+  * Copyright 2001-2002 Pavel Machek <pavel@suse.cz>
+  * Based on code
+  * Copyright 2001 Patrick Mochel <mochel@osdl.org>
+  * Copyright 2004 Hu Gang <hugang@soulinfo.com
+  *  port to PowerPC
+  */
+#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/irq.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/suspend-debug.h>
+#include <linux/suspend-common.h>
+#include <asm/uaccess.h>
+#if 0
+/* Local variables for do_swsusp2_suspend */
+volatile static int state1 __nosavedata = 0;
+volatile static int state2 __nosavedata = 0;
+volatile static int state3 __nosavedata = 0;
+volatile static int loop __nosavedata = 0;
+volatile static struct range *origrange __nosavedata;
+volatile static struct range *copyrange __nosavedata;
+volatile static int origoffset __nosavedata;
+volatile static int copyoffset __nosavedata;
+volatile static unsigned long * origpage __nosavedata;
+volatile static unsigned long * copypage __nosavedata;
+#endif
+
+//volatile static int orig_min_free __nosavedata;
+#ifndef CONFIG_SMP
+//static unsigned long c_loops_per_jiffy_ref __nosavedata = 0;
+//static unsigned long cpu_khz_ref __nosavedata = 0;
+#endif
+
+extern void do_swsusp2_suspend_1(void);
+extern void do_swsusp2_suspend_2(void);
+extern void do_swsusp2_resume_1(void);
+extern void do_swsusp2_resume_2(void);
+extern struct pagedir __nosavedata pagedir_resume;
+
+/*
+ * FIXME: This function should really be written in assembly. Actually
+ * requirement is that it does not touch stack, because %esp will be
+ * wrong during resume before restore_processor_context(). Check
+ * assembly if you modify this.
+ */
+#if 0
+static inline void pre_copyback(void)
+{
+#ifdef CONFIG_PREEMPT
+	/*
+	 * Preempt disabled in kernel we're about to restore.
+	 * Make sure we match state now.
+	 */
+	preempt_disable();
+	PRINTPREEMPTCOUNT("Prior to copying old kernel back.");
+#endif
+
+	state1 = swsusp_action;
+	state2 = swsusp_debug_state;
+	state3 = console_loglevel;
+
+#ifndef CONFIG_SMP
+	//c_loops_per_jiffy_ref = cpu_data->loops_per_jiffy;
+	//cpu_khz_ref = cpu_khz;
+#endif
+}
+static inline void post_copyback(void)
+{
+#ifndef CONFIG_SMP
+	//cpu_data->loops_per_jiffy = c_loops_per_jiffy_ref;
+	//loops_per_jiffy = c_loops_per_jiffy_ref;
+	//cpu_khz = cpu_khz_ref;
+#endif
+	swsusp_action = state1;
+	swsusp_debug_state = state2;
+	console_loglevel = state3;
+	//swsusp_min_free = orig_min_free;
+
+}
+#endif
+static inline void do_swsusp2_copyback(void)
+{
+	/* PowerPC has a lots register, use local register is possible */
+	register int origoffset, copyoffset;
+	register unsigned long * origpage, * copypage;
+	register struct range *origrange, *copyrange;
+//	register int pagesize;
+
+//	pre_copyback();
+
+	origrange = pagedir_resume.origranges.first;
+//	pagesize = pagedir_resume.pageset_size;
+//	printk("%d\n", pagesize);
+	origoffset = origrange->minimum;
+	origpage = (unsigned long *) (page_address(mem_map + origoffset));
+	
+	copyrange = pagedir_resume.destranges.first;
+	copyoffset = copyrange->minimum;
+	copypage = (unsigned long *) (page_address(mem_map + copyoffset));
+	//orig_min_free = swsusp_min_free;
+
+	while (origrange) {
+		register int loop;
+		for (loop = 0; loop < (PAGE_SIZE / sizeof(unsigned long)); loop++)
+			*(origpage + loop) = *(copypage + loop);
+		
+		if (origoffset < origrange->maximum) {
+			origoffset++;
+			origpage += (PAGE_SIZE / sizeof(unsigned long));
+		} else {
+			origrange = origrange->next;
+			if (origrange) {
+				origoffset = origrange->minimum;
+				origpage = (unsigned long *) (page_address(mem_map + origoffset));
+			}
+		}
+
+		if (copyoffset < copyrange->maximum) {
+			copyoffset++;
+			copypage += (PAGE_SIZE / sizeof(unsigned long));
+		} else {
+			copyrange = copyrange->next;
+			if (copyrange) {
+				copyoffset = copyrange->minimum;
+				copypage = (unsigned long *) (page_address(mem_map + copyoffset));
+			}
+		}
+	}
+	
+/* Ahah, we now run with our old stack, and with registers copied from
+   suspend time */
+
+//	post_copyback();
+}
+
+void do_swsusp_lowlevel(int resume)
+{
+	if (!resume) {
+		do_swsusp2_suspend_1();
+		save_processor_state();
+		/* saving stack */
+		
+		do_swsusp2_suspend_2();
+		return;
+	}
+
+	/* setup swapper_pg_dir in x86 */
+
+	do_swsusp2_resume_1();
+	do_swsusp2_copyback();
+	/* setup segment register */
+	restore_processor_state();
+	do_swsusp2_resume_2();
+}
Index: arch/ppc/power/cpu.c
===================================================================
--- arch/ppc/power/cpu.c	(revision 193)
+++ arch/ppc/power/cpu.c	(working copy)
@@ -0,0 +1,72 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <linux/irq.h>
+#include <linux/root_dev.h>
+#include <linux/suspend.h>
+#include <linux/delay.h>
+
+#include <asm/mmu_context.h>
+
+extern void enable_kernel_altivec(void);
+
+static inline void do_pmu_suspend(void)
+{
+	printk("suspend pmu\n");	
+	pmu_suspend();
+	printk(".\n");
+}
+
+static inline void do_pmu_resume(void)
+{
+	struct adb_request req;
+	printk("resume pmu\n");	
+	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+	pmu_wait_complete(&req);
+	
+	/* Resume PMU event interrupts */
+	pmu_resume();	
+	printk(".\n");
+}
+
+void save_processor_state(void)
+{
+	printk("save processor state\n");
+	pmu_suspend();
+	printk(".\n");
+	printk("current is 0x%x\n", current);
+	mdelay(1000);
+}
+
+void restore_processor_state(void)
+{
+	printk("current is 0x%x\n", current);
+	mdelay(1000);
+	printk("seting context\n");
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
+
+	printk("do pmu resume\n");
+	do_pmu_resume();
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif
+	printk("enable kernel fp\n");
+	enable_kernel_fp();
+	printk(".\n");
+}
+
+EXPORT_SYMBOL(save_processor_state);
+EXPORT_SYMBOL(restore_processor_state);
Index: arch/ppc/power/Makefile
===================================================================
--- arch/ppc/power/Makefile	(revision 193)
+++ arch/ppc/power/Makefile	(working copy)
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PM) += cpu.o
+obj-$(CONFIG_SOFTWARE_SUSPEND2) += swsusp2-asm.o
Index: arch/ppc/Makefile
===================================================================
--- arch/ppc/Makefile	(revision 192)
+++ arch/ppc/Makefile	(working copy)
@@ -44,6 +44,7 @@
 drivers-$(CONFIG_4xx)		+= arch/ppc/4xx_io/
 drivers-$(CONFIG_8260)		+= arch/ppc/8260_io/
 drivers-$(CONFIG_OCP)		+= arch/ppc/ocp/
+drivers-$(CONFIG_PM)		+= arch/ppc/power/
 
 BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-27 21:40                             ` Benjamin Herrenschmidt
@ 2004-01-28 16:09                               ` Michael Schmitz
  2004-01-28 17:02                                 ` Hugang
                                                   ` (2 more replies)
  0 siblings, 3 replies; 80+ messages in thread
From: Michael Schmitz @ 2004-01-28 16:09 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Michael Schmitz, Michael Schmitz, Pavel Machek, Hugang,
	Patrick Mochel, Nigel Cunningham, ncunningham, linuxppc-dev list


> > Battery requests might have been underway; pmud is running. If I read
> > pmu_suspend() right, pending battery requests should result in pmu_suspend
> > waiting for them to finish?
>
> Normally yes... pmud isn't running at this point (all processes are frozen)

OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
note: if you are saving a large system and have multiple swap files, play
with swap priorities to make sure the pages are swapped out to the file
_not_ used for suspend.

	Michael


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 16:09                               ` Michael Schmitz
@ 2004-01-28 17:02                                 ` Hugang
  2004-01-28 17:03                                   ` Colin Leroy
                                                     ` (2 more replies)
  2004-01-28 21:55                                 ` Benjamin Herrenschmidt
  2004-01-28 21:55                                 ` Benjamin Herrenschmidt
  2 siblings, 3 replies; 80+ messages in thread
From: Hugang @ 2004-01-28 17:02 UTC (permalink / raw)
  To: Michael Schmitz
  Cc: Benjamin Herrenschmidt, Michael Schmitz, Michael Schmitz,
	Pavel Machek, Patrick Mochel, Nigel Cunningham, ncunningham,
	linuxppc-dev list


On Wed, 28 Jan 2004 17:09:36 +0100 (CET)
Michael Schmitz <schmitz@opal.biophys.uni-duesseldorf.de> wrote:

> OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> note: if you are saving a large system and have multiple swap files,
> play with swap priorities to make sure the pages are swapped out to
> the file_not_ used for suspend.

Can you try with swsusp2 ppc port, if you have time.

:)

--
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 17:02                                 ` Hugang
@ 2004-01-28 17:03                                   ` Colin Leroy
  2004-01-29  9:17                                     ` Michael Schmitz
  2004-01-28 18:00                                   ` Michael Schmitz
  2004-01-28 21:56                                   ` Benjamin Herrenschmidt
  2 siblings, 1 reply; 80+ messages in thread
From: Colin Leroy @ 2004-01-28 17:03 UTC (permalink / raw)
  To: Hugang; +Cc: linuxppc-dev list


> Can you try with swsusp2 ppc port, if you have time.

It would be really nice if you could provide a unique diff, would be
easier to test ;-)

--
Colin, lazy


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 17:02                                 ` Hugang
  2004-01-28 17:03                                   ` Colin Leroy
@ 2004-01-28 18:00                                   ` Michael Schmitz
  2004-01-28 21:56                                   ` Benjamin Herrenschmidt
  2 siblings, 0 replies; 80+ messages in thread
From: Michael Schmitz @ 2004-01-28 18:00 UTC (permalink / raw)
  To: Hugang
  Cc: Michael Schmitz, Benjamin Herrenschmidt, Michael Schmitz,
	Pavel Machek, Patrick Mochel, Nigel Cunningham, ncunningham,
	linuxppc-dev list


> > OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> > pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> > note: if you are saving a large system and have multiple swap files,
> > play with swap priorities to make sure the pages are swapped out to
> > the file_not_ used for suspend.
>
> Can you try with swsusp2 ppc port, if you have time.

I'll have a look at it. Unless you take care of PMU timeouts some way,
I'd dare predict it won't work, though.

	Michael


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc), swsusp2 works.
       [not found]                             ` <20040129012720.1385c41a@localhost>
@ 2004-01-28 19:05                               ` Nigel Cunningham
  2004-01-28 19:10                                 ` Hugang
  0 siblings, 1 reply; 80+ messages in thread
From: Nigel Cunningham @ 2004-01-28 19:05 UTC (permalink / raw)
  To: Hugang
  Cc: Benjamin Herrenschmidt, Pavel Machek, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

Congratulations on getting it going!

I'll add it to the patch, but mark it as experimental for the moment.

Regards,

Nigel 
-- 
My work on Software Suspend is graciously brought to you by
LinuxFund.org.


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc), swsusp2 works.
  2004-01-28 19:05                               ` Nigel Cunningham
@ 2004-01-28 19:10                                 ` Hugang
  0 siblings, 0 replies; 80+ messages in thread
From: Hugang @ 2004-01-28 19:10 UTC (permalink / raw)
  To: ncunningham
  Cc: Benjamin Herrenschmidt, Pavel Machek, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

On Thu, 29 Jan 2004 08:05:49 +1300
Nigel Cunningham <ncunningham@users.sourceforge.net> wrote:

> Congratulations on getting it going!
Not easy for me. But do it improve my kernel understand.

> 
> I'll add it to the patch, but mark it as experimental for the moment.
thanks.

-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 16:09                               ` Michael Schmitz
  2004-01-28 17:02                                 ` Hugang
@ 2004-01-28 21:55                                 ` Benjamin Herrenschmidt
  2004-01-29  9:30                                   ` Michael Schmitz
  2004-01-28 21:55                                 ` Benjamin Herrenschmidt
  2 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-28 21:55 UTC (permalink / raw)
  To: Michael Schmitz
  Cc: Michael Schmitz, Pavel Machek, Hugang, Patrick Mochel,
	Nigel Cunningham, ncunningham, linuxppc-dev list


On Thu, 2004-01-29 at 03:09, Michael Schmitz wrote:
> > > Battery requests might have been underway; pmud is running. If I read
> > > pmu_suspend() right, pending battery requests should result in pmu_suspend
> > > waiting for them to finish?
> >
> > Normally yes... pmud isn't running at this point (all processes are frozen)
>
> OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> note: if you are saving a large system and have multiple swap files, play
> with swap priorities to make sure the pages are swapped out to the file
> _not_ used for suspend.

Hrm... Remove the PMU_SYSTEM_READY, it's a bug to call it on a 101...
And it's not needed anyway.

Ben.


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 16:09                               ` Michael Schmitz
  2004-01-28 17:02                                 ` Hugang
  2004-01-28 21:55                                 ` Benjamin Herrenschmidt
@ 2004-01-28 21:55                                 ` Benjamin Herrenschmidt
  2004-01-28 23:35                                   ` Pavel Machek
  2004-01-29  8:11                                   ` Michael Schmitz
  2 siblings, 2 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-28 21:55 UTC (permalink / raw)
  To: Michael Schmitz
  Cc: Michael Schmitz, Pavel Machek, Hugang, Patrick Mochel,
	Nigel Cunningham, ncunningham, linuxppc-dev list


On Thu, 2004-01-29 at 03:09, Michael Schmitz wrote:
> > > Battery requests might have been underway; pmud is running. If I read
> > > pmu_suspend() right, pending battery requests should result in pmu_suspend
> > > waiting for them to finish?
> >
> > Normally yes... pmud isn't running at this point (all processes are frozen)
>
> OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> note: if you are saving a large system and have multiple swap files, play
> with swap priorities to make sure the pages are swapped out to the file
> _not_ used for suspend.

Ah ? What's up ? suspend trashes the swap ? That's very bad...

Ben.


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 17:02                                 ` Hugang
  2004-01-28 17:03                                   ` Colin Leroy
  2004-01-28 18:00                                   ` Michael Schmitz
@ 2004-01-28 21:56                                   ` Benjamin Herrenschmidt
  2 siblings, 0 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-28 21:56 UTC (permalink / raw)
  To: Hugang
  Cc: Michael Schmitz, Michael Schmitz, Pavel Machek, Patrick Mochel,
	Nigel Cunningham, ncunningham, linuxppc-dev list


On Thu, 2004-01-29 at 04:02, Hugang wrote:
> On Wed, 28 Jan 2004 17:09:36 +0100 (CET)
> Michael Schmitz <schmitz@opal.biophys.uni-duesseldorf.de> wrote:
>
> > OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> > pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> > note: if you are saving a large system and have multiple swap files,
> > play with swap priorities to make sure the pages are swapped out to
> > the file_not_ used for suspend.
>
> Can you try with swsusp2 ppc port, if you have time.

Well, I though you would do it :) The basis is the same, only the
page copy routine in the assembly has to change afaik...

Ben.


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 21:55                                 ` Benjamin Herrenschmidt
@ 2004-01-28 23:35                                   ` Pavel Machek
  2004-01-29  8:11                                   ` Michael Schmitz
  1 sibling, 0 replies; 80+ messages in thread
From: Pavel Machek @ 2004-01-28 23:35 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Michael Schmitz, Michael Schmitz, Hugang, Patrick Mochel,
	Nigel Cunningham, ncunningham, linuxppc-dev list


Hi!

> > > > Battery requests might have been underway; pmud is running. If I read
> > > > pmu_suspend() right, pending battery requests should result in pmu_suspend
> > > > waiting for them to finish?
> > >
> > > Normally yes... pmud isn't running at this point (all processes are frozen)
> >
> > OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> > pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> > note: if you are saving a large system and have multiple swap files, play
> > with swap priorities to make sure the pages are swapped out to the file
> > _not_ used for suspend.
>
> Ah ? What's up ? suspend trashes the swap ? That's very bad...

No, it does not.

But swap space is shared between suspend and swap. And if that place
is full (unlikely), you've got a problem.
								Pavel
--
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 12:22                         ` Hugang
  2004-01-28 13:23                           ` pmdisk working on ppc (WAS: Help port swsusp to ppc), swsusp2 works Hugang
@ 2004-01-29  0:34                           ` Benjamin Herrenschmidt
  2004-01-29  2:05                             ` Hugang
  1 sibling, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-29  0:34 UTC (permalink / raw)
  To: Hugang
  Cc: Nigel Cunningham, Pavel Machek, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

On Wed, 2004-01-28 at 23:22, Hugang wrote:
> On Tue, 27 Jan 2004 11:31:50 +1300
> Nigel Cunningham <ncunningham@users.sourceforge.net> wrote:
> 
> > Yes. That's why suspend2 doesn't free any memory at all by default,
> > but gives the user the option of setting a maximum image size.
> 
> HaHa, Here is swsusp2 patch for ppc. Now it WORKS fine.
> 
> The code base for testing, any comments and testing are welcome.

Ok, had a quick look. I  _HATE_ those horrible macros you did. Why
not just call asm functions or just inline the code ?

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-29  0:34                           ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
@ 2004-01-29  2:05                             ` Hugang
  2004-01-29  4:23                               ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 80+ messages in thread
From: Hugang @ 2004-01-29  2:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Nigel Cunningham, Pavel Machek, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

On Thu, 29 Jan 2004 11:34:53 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> Ok, had a quick look. I  _HATE_ those horrible macros you did. Why
> not just call asm functions or just inline the code ?

Good idea, But will try inline first. I can't sure change to call asm
function can works. But I'll try.

Thanks for look.

-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-29  2:05                             ` Hugang
@ 2004-01-29  4:23                               ` Benjamin Herrenschmidt
       [not found]                                 ` <20040129165119.553403f1@localhost>
  0 siblings, 1 reply; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-29  4:23 UTC (permalink / raw)
  To: Hugang
  Cc: Nigel Cunningham, Pavel Machek, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

On Thu, 2004-01-29 at 13:05, Hugang wrote:
> On Thu, 29 Jan 2004 11:34:53 +1100
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> 
> > Ok, had a quick look. I  _HATE_ those horrible macros you did. Why
> > not just call asm functions or just inline the code ?
> 
> Good idea, But will try inline first. I can't sure change to call asm
> function can works. But I'll try.

As long as you make sure you save the LR in case you need it, you
can call asm functions. macros are _evil_ :)

Also, you can remove the code playing with BATs for now, they don't
really need to be saved. If the boot kernel sets them up any differently
than the saved kernel, we are in trouble anyway. And the G5 has no BATs.

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 21:55                                 ` Benjamin Herrenschmidt
  2004-01-28 23:35                                   ` Pavel Machek
@ 2004-01-29  8:11                                   ` Michael Schmitz
  1 sibling, 0 replies; 80+ messages in thread
From: Michael Schmitz @ 2004-01-29  8:11 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Michael Schmitz, Pavel Machek, Hugang, Patrick Mochel,
	Nigel Cunningham, ncunningham, linuxppc-dev list


> > OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> > pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> > note: if you are saving a large system and have multiple swap files, play
> > with swap priorities to make sure the pages are swapped out to the file
> > _not_ used for suspend.
>
> Ah ? What's up ? suspend trashes the swap ? That's very bad...

Nope; freeing memory puts everything in the highest priority swap (happens
to be the first one), and suspend doesn't find enough room in that swap
area. The calculation of free swap done by pmdisk is bogus, it calculates
total free swap, not free swap in the area that pmdisk is going to use for
the snapshot.

	Michael


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 17:03                                   ` Colin Leroy
@ 2004-01-29  9:17                                     ` Michael Schmitz
  0 siblings, 0 replies; 80+ messages in thread
From: Michael Schmitz @ 2004-01-29  9:17 UTC (permalink / raw)
  To: Colin Leroy; +Cc: Hugang, linuxppc-dev list


> > Can you try with swsusp2 ppc port, if you have time.
>
> It would be really nice if you could provide a unique diff, would be
> easier to test ;-)

Seconded. And I'd like to have it all in one single diff - I started
losing track of what patch to apply on top of the first one already.

	Michael


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-28 21:55                                 ` Benjamin Herrenschmidt
@ 2004-01-29  9:30                                   ` Michael Schmitz
  2004-01-29 12:10                                     ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 80+ messages in thread
From: Michael Schmitz @ 2004-01-29  9:30 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Michael Schmitz, Michael Schmitz, Pavel Machek, Hugang,
	Patrick Mochel, Nigel Cunningham, ncunningham, linuxppc-dev list


> > OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> > pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> > note: if you are saving a large system and have multiple swap files, play
> > with swap priorities to make sure the pages are swapped out to the file
> > _not_ used for suspend.
>
> Hrm... Remove the PMU_SYSTEM_READY, it's a bug to call it on a 101...
> And it's not needed anyway.

I'm trying a if (pmu_kind != 3) around that call - should it rather be <= 3 ?

	Michael


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
       [not found]                                 ` <20040129165119.553403f1@localhost>
@ 2004-01-29 10:29                                   ` Pavel Machek
  2004-01-29 10:50                                     ` Hugang
  2004-01-29 12:12                                   ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 80+ messages in thread
From: Pavel Machek @ 2004-01-29 10:29 UTC (permalink / raw)
  To: Hugang
  Cc: Benjamin Herrenschmidt, Nigel Cunningham, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

Hi!

> > As long as you make sure you save the LR in case you need it, you
> > can call asm functions. macros are _evil_ :)
> > 
> > Also, you can remove the code playing with BATs for now, they don't
> > really need to be saved. If the boot kernel sets them up any
> > differently than the saved kernel, we are in trouble anyway. And the
> > G5 has no BATs.
> 
> Thanks, I hate macros too, I'll change code to function as soon as
> possible.
> 
> First I would tell you current swusp(2) signal ppc part has a problem.
> I has add follow code into do_signal to let process to FREEZE before 
> suspend.
> ppc/
>     int signr, ret;
> 
> +    if (current->flags & PF_FREEZE) {
> +        refrigerator(PF_FREEZE);
> +        return 0;
> +    }
> 
>     if (!oldset)
>         oldset = &current->blocked;
> 
> i386/
>     if (current->flags & PF_FREEZE) {
>         refrigerator(PF_FREEZE);
>         if (!signal_pending(current))
>             goto no_signal;
>     }


You may want to try this one.. Maybe it helps?
								Pavel
Index: linux/kernel/power/process.c
===================================================================
--- linux.orig/kernel/power/process.c	2004-01-13 22:52:40.000000000 +0100
+++ linux/kernel/power/process.c	2004-01-09 20:33:05.000000000 +0100
@@ -49,10 +49,11 @@
 	pr_debug("%s entered refrigerator\n", current->comm);
 	printk("=");
 	current->flags &= ~PF_FREEZE;
-	if (flag)
-		flush_signals(current); /* We have signaled a kernel thread, which isn't normal behaviour
-					   and that may lead to 100%CPU sucking because those threads
-					   just don't manage signals. */
+
+	spin_lock_irq(&current->sighand->siglock);
+	recalc_sigpending(); /* We sent fake signal, clean it up */
+	spin_unlock_irq(&current->sighand->siglock);
+
 	current->flags |= PF_FROZEN;
 	while (current->flags & PF_FROZEN)
 		schedule();


-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-29 10:29                                   ` Pavel Machek
@ 2004-01-29 10:50                                     ` Hugang
  0 siblings, 0 replies; 80+ messages in thread
From: Hugang @ 2004-01-29 10:50 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Benjamin Herrenschmidt, Nigel Cunningham, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list

On Thu, 29 Jan 2004 11:29:48 +0100
Pavel Machek <pavel@ucw.cz> wrote:
> 
> You may want to try this one.. Maybe it helps?
> 							
I has check the kernel, I using swsusp2 patch, the process freeze like
this, but still need the patch I lastest send.

           if (flag) {
                swsusp_spin_lock_irqsave(PROCESS_SIG_MASK(current),
flags);                RECALC_SIGPENDING;
                swsusp_spin_unlock_irqrestore(PROCESS_SIG_MASK(current),
flags);            }


-- 
Hu Gang / Steve
Linux Registered User 204016
GPG Public Key: http://soulinfo.com/~hugang/HuGang.asc

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
  2004-01-29  9:30                                   ` Michael Schmitz
@ 2004-01-29 12:10                                     ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-29 12:10 UTC (permalink / raw)
  To: Michael Schmitz
  Cc: Michael Schmitz, Pavel Machek, Hugang, Patrick Mochel,
	Nigel Cunningham, ncunningham, linuxppc-dev list


On Thu, 2004-01-29 at 20:30, Michael Schmitz wrote:
> > > OK. I put a mdelay(100) between the PMU_SYSTEM_READY request and the
> > > pmu_suspend() call in pmu_sys_resume and it seems to work so far. Side
> > > note: if you are saving a large system and have multiple swap files, play
> > > with swap priorities to make sure the pages are swapped out to the file
> > > _not_ used for suspend.
> >
> > Hrm... Remove the PMU_SYSTEM_READY, it's a bug to call it on a 101...
> > And it's not needed anyway.
>
> I'm trying a if (pmu_kind != 3) around that call - should it rather be <= 3 ?

Just remove it for you tests. Only KEYLARGO based PMUs have this call

Ben.


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: pmdisk working on ppc (WAS: Help port swsusp to ppc)
       [not found]                                 ` <20040129165119.553403f1@localhost>
  2004-01-29 10:29                                   ` Pavel Machek
@ 2004-01-29 12:12                                   ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 80+ messages in thread
From: Benjamin Herrenschmidt @ 2004-01-29 12:12 UTC (permalink / raw)
  To: Hugang
  Cc: Nigel Cunningham, Pavel Machek, Patrick Mochel,
	Linux Kernel Mailing List, linuxppc-dev list


> The ppc part I has lost something, They are has a step to show bug.
> switch to vt console, login as normal use, run "screen", do suspend.
> after resume, screen will say unknown error 514.
> 
> attached file should fix it. but look very very ulgy.

I'll have a look tomorrow, that code was a quick hack indeed.

Ben.



^ permalink raw reply	[flat|nested] 80+ messages in thread

end of thread, other threads:[~2004-01-29 12:13 UTC | newest]

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-01-19  2:52 Help port swsusp to ppc Hugang
2004-01-19  3:04 ` Nigel Cunningham
2004-01-19  3:35 ` Benjamin Herrenschmidt
2004-01-19  5:20   ` Nigel Cunningham
2004-01-19 11:39     ` Benjamin Herrenschmidt
2004-01-19 17:56       ` Nigel Cunningham
2004-01-19 22:03         ` Benjamin Herrenschmidt
2004-01-20 20:44           ` Pavel Machek
2004-01-20 21:54             ` Benjamin Herrenschmidt
2004-01-20 22:07               ` Nigel Cunningham
2004-01-20 22:42               ` Pavel Machek
2004-01-22 13:17           ` Hugang
2004-01-22 17:53             ` Nigel Cunningham
2004-01-23  0:15               ` Hugang
2004-01-23  7:12             ` Benjamin Herrenschmidt
2004-01-23 10:30               ` Hugang
2004-01-24  2:54                 ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
2004-01-24  5:40                   ` Hugang
2004-01-24 16:28                   ` Colin Leroy
2004-01-24 23:46                     ` Benjamin Herrenschmidt
2004-01-25 18:08                       ` Colin Leroy
2004-01-26  0:08                         ` Benjamin Herrenschmidt
2004-01-26 18:21                           ` Colin Leroy
2004-01-26 21:58                             ` Benjamin Herrenschmidt
2004-01-26 14:29                   ` Guido Guenther
     [not found]                   ` <20040126181004.GB315@elf.ucw.cz>
2004-01-26 22:00                     ` Benjamin Herrenschmidt
2004-01-26 22:31                       ` Nigel Cunningham
2004-01-28 12:22                         ` Hugang
2004-01-28 13:23                           ` pmdisk working on ppc (WAS: Help port swsusp to ppc), swsusp2 works Hugang
     [not found]                             ` <20040129012720.1385c41a@localhost>
2004-01-28 19:05                               ` Nigel Cunningham
2004-01-28 19:10                                 ` Hugang
2004-01-29  0:34                           ` pmdisk working on ppc (WAS: Help port swsusp to ppc) Benjamin Herrenschmidt
2004-01-29  2:05                             ` Hugang
2004-01-29  4:23                               ` Benjamin Herrenschmidt
     [not found]                                 ` <20040129165119.553403f1@localhost>
2004-01-29 10:29                                   ` Pavel Machek
2004-01-29 10:50                                     ` Hugang
2004-01-29 12:12                                   ` Benjamin Herrenschmidt
2004-01-26 23:21                       ` Pavel Machek
2004-01-27  0:12                         ` Nigel Cunningham
2004-01-27  7:53                           ` Pavel Machek
2004-01-27 10:34                       ` Michael Schmitz
2004-01-27 10:37                         ` Benjamin Herrenschmidt
2004-01-27 14:32                           ` Michael Schmitz
2004-01-27 21:40                             ` Benjamin Herrenschmidt
2004-01-28 16:09                               ` Michael Schmitz
2004-01-28 17:02                                 ` Hugang
2004-01-28 17:03                                   ` Colin Leroy
2004-01-29  9:17                                     ` Michael Schmitz
2004-01-28 18:00                                   ` Michael Schmitz
2004-01-28 21:56                                   ` Benjamin Herrenschmidt
2004-01-28 21:55                                 ` Benjamin Herrenschmidt
2004-01-29  9:30                                   ` Michael Schmitz
2004-01-29 12:10                                     ` Benjamin Herrenschmidt
2004-01-28 21:55                                 ` Benjamin Herrenschmidt
2004-01-28 23:35                                   ` Pavel Machek
2004-01-29  8:11                                   ` Michael Schmitz
2004-01-27 10:47                         ` Pavel Machek
2004-01-27 10:56                           ` Benjamin Herrenschmidt
2004-01-24  4:39                 ` Benjamin Herrenschmidt
2004-01-24  7:20                   ` Pavel Machek
2004-01-24  9:59                     ` pmdisk working on ppc Måns Rullgård
2004-01-19 20:45       ` Help port swsusp to ppc Pavel Machek
2004-01-19 23:38         ` Benjamin Herrenschmidt
2004-01-20  0:04           ` Pavel Machek
2004-01-20  1:06             ` Benjamin Herrenschmidt
2004-01-20 10:02               ` Pavel Machek
2004-01-20 11:25                 ` Benjamin Herrenschmidt
2004-01-20 11:44                   ` Pavel Machek
2004-01-20  9:53           ` Geert Uytterhoeven
2004-01-20 10:04             ` Pavel Machek
2004-01-20 11:26               ` Benjamin Herrenschmidt
2004-01-20 11:36                 ` Pavel Machek
2004-01-20 11:44                   ` Benjamin Herrenschmidt
2004-01-20 11:57                     ` Pavel Machek
2004-01-20 18:30                     ` Nigel Cunningham
2004-01-20 21:43                       ` Benjamin Herrenschmidt
2004-01-20 11:22             ` Benjamin Herrenschmidt
2004-01-19 20:40     ` Pavel Machek
2004-01-19 23:40       ` Benjamin Herrenschmidt
2004-01-19 23:59         ` Pavel Machek

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.