On Wed, Oct 31, 2007 at 04:12:36AM +0900, Hyon Lim wrote:
> Hello. I need a help for my implementation work on MIPS software suspend.
> From 3month ago, I've been coding software suspend(swsusp) on MIPS arch.
> I'm developing with MIPS32 4KEc embedded processor for digital appliance.
>
> Swsusp has two procedure. the one is suspending procedure and other one is
> resume procedure.
> Yesterday, I confirmed suspending procedure working.
> This is a porting guide of swsusp (
> http://tree.celinuxforum.org/CelfPubWiki/SwSuspendPortingNotes)
> I refered this article.
The article is a bit dated and lacking alot of details.
> The problem I faced is assembly language for MIPS.
> Of course, there are many manuals for this work but, I need a help from MIPS
> expert.
>
> This pseudo code should be implemented by MIPS asm.
>
> for (j = nr_copy_pages; j>0; j--) {
> src = pagedir_nosave[j].src;
> dst = pagedir_nosave[j].dst;
> for (i=0;i<1024;i++) {
> *dst++ = *src++;
> }
> }
>
> nr_copy_pages is unsigned long variable.
The page is refering to some old code which no longer seems to exist in
this form. The array pagedir_nosave has now become a chained list. I
attach a patch for illustration purposes. It illustrates how things work
on recent kernels; I didn't have a 2.6.10 kernel at hand.
If you have further questions on MIPS assembler then I suggest you get a
copy of Dominik Sweetman's excellent "See MIPS Run Linux" book.
> and pagedir_nosave is a
> suspend_pagedir_t<http://lxr.linux.no/source/kernel/power/ident?v=2.6.10;i=suspend_pagedir_t>type
> structure array(pointer). (you can refer following url. Line 101. :
> http://lxr.linux.no/source/kernel/power/swsusp.c?v=2.6.10)
> code skeleton or useful material will be welcomed. (whatever you have.)
>
> The second problem is
> " which register should be prevented? "
>
> I saved $v0-v1. $a0-$a3. $t0-t7. $s0-s7. $t8-t9. $gp,sp,fp,ra.
That sounds about right but I'd need to dive deeper into swsusp to give
you a definitive answer.
Cheers,
Ralf
[MIPS] Skeleton swsusp implementation.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 3196509..38adf9e 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -75,6 +75,8 @@ obj-$(CONFIG_PCSPEAKER) += pcspeaker.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
+
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o
/dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index ca13629..f3038dc 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
+#include <linux/suspend.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
@@ -337,3 +338,13 @@ void output_irq_cpustat_t_defines(void)
size("#define IC_IRQ_CPUSTAT_T ", irq_cpustat_t);
linefeed;
}
+
+void output_pbe_defines(void)
+{
+ text("/* Linux struct pbe offsets. */");
+ offset("#define PBE_ADDRESS ", struct pbe, address);
+ offset("#define PBE_ORIG_ADDRESS ", struct pbe, orig_address);
+ offset("#define PBE_NEXT ", struct pbe, next);
+ size("#define PBE_SIZE ", struct pbe);
+ linefeed;
+}
diff --git a/arch/mips/kernel/suspend.S b/arch/mips/kernel/suspend.S
new file mode 100644
index 0000000..32b3ec0
--- /dev/null
+++ b/arch/mips/kernel/suspend.S
@@ -0,0 +1,20 @@
+#include <asm/asm-offsets.h>
+#include <asm/regdef.h>
+#include <asm/asm.h>
+
+LEAF(swsusp_arch_suspend)
+ END(swsusp_arch_suspend)
+
+LEAF(swsusp_arch_resume)
+ PTR_LA t0, restore_pblist
+0: PTR_L t1, PBE_ADDRESS(t1)
+ PTR_L t2, PBE_ORIG_ADDRESS(t1)
+ PTR_ADDIU t3, t1, _PAGE_SIZE
+1: REG_L t4, (t1)
+ REG_S t4, (t1)
+ PTR_ADDIU t1, t1, SZREG
+ PTR_ADDIU t2, t2, SZREG
+ bne t1, t3, 1b
+ PTR_L t1, PBE_NEXT(t1)
+ bnez t1, 0
+ END(swsusp_arch_resume)
diff --git a/arch/mips/kernel/swsusp.c b/arch/mips/kernel/swsusp.c
new file mode 100644
index 0000000..864dd49
--- /dev/null
+++ b/arch/mips/kernel/swsusp.c
@@ -0,0 +1,30 @@
+/*
+ * Suspend support specific for power.
+ *
+ * Distribute under GPLv2
+ *
+ * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
+ * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
+ */
+
+#include <asm/page.h>
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
+void save_processor_state(void)
+{
+ /* ... */
+}
+
+void restore_processor_state(void)
+{
+ /* ... */
+}
+
+int pfn_is_nosave(unsigned long pfn)
+{
+ unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
+ unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >>
PAGE_SHIFT;
+ return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
diff --git a/include/asm-mips/suspend.h b/include/asm-mips/suspend.h
index 2562f8f..ee5e679 100644
--- a/include/asm-mips/suspend.h
+++ b/include/asm-mips/suspend.h
@@ -1,6 +1,9 @@
#ifndef __ASM_SUSPEND_H
#define __ASM_SUSPEND_H
-/* Somewhen... Maybe :-) */
+static inline int arch_prepare_suspend(void)
+{
+ return 0;
+}
#endif /* __ASM_SUSPEND_H */
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 4360e08..854b7a9 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -1,7 +1,7 @@
#ifndef _LINUX_SUSPEND_H
#define _LINUX_SUSPEND_H
-#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32) ||
defined(CONFIG_PPC64)
+#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32) ||
defined(CONFIG_PPC64) || defined(CONFIG_MIPS)
#include <asm/suspend.h>
#endif
#include <linux/swap.h>
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 8e186c6..444f835 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -99,13 +99,13 @@ config SUSPEND
config HIBERNATION_UP_POSSIBLE
bool
- depends on X86 || PPC64_SWSUSP || PPC32
+ depends on MIPS || X86 || PPC64_SWSUSP || PPC32
depends on !SMP
default y
config HIBERNATION_SMP_POSSIBLE
bool
- depends on (X86 && !X86_VOYAGER) || PPC64_SWSUSP
+ depends on MIPS || (X86 && !X86_VOYAGER) || PPC64_SWSUSP
depends on SMP
default y
|