aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorTkhai Kirill <tkhai@yandex.ru>2013-03-19 11:11:07 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-20 14:06:54 -0400
commitbdde6b3c8ba48fa5847b6d75f0541c8b8db9205c (patch)
tree9fccf29eca02be11f5e6e9eec13ae6d056ff3288 /arch/sparc
parent1ab0a67601ca7be81bfaaa0a2540ee0d0393f40b (diff)
sparc64: Hibernation support
This patch adds CONFIG_HIBERNATION support for sparc64 architecture. The suspend function is the same as on another platforms. The restore function uses Bypass feature of MMU which allows to make the process more comfortable and plesant. Signed-off-by: Kirill Tkhai <tkhai@yandex.ru> CC: David Miller <davem@davemloft.net> CC: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kconfig7
-rw-r--r--arch/sparc/Makefile1
-rw-r--r--arch/sparc/include/asm/hibernate.h23
-rw-r--r--arch/sparc/kernel/asm-offsets.c15
-rw-r--r--arch/sparc/power/Makefile3
-rw-r--r--arch/sparc/power/hibernate.c42
-rw-r--r--arch/sparc/power/hibernate_asm.S131
7 files changed, 222 insertions, 0 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index c3c3ad25612b..33e48cbf25ab 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -100,6 +100,9 @@ config HAVE_LATENCYTOP_SUPPORT
100 bool 100 bool
101 default y if SPARC64 101 default y if SPARC64
102 102
103config ARCH_HIBERNATION_POSSIBLE
104 def_bool y if SPARC64
105
103config AUDIT_ARCH 106config AUDIT_ARCH
104 bool 107 bool
105 default y 108 default y
@@ -327,6 +330,10 @@ config ARCH_SPARSEMEM_DEFAULT
327 330
328source "mm/Kconfig" 331source "mm/Kconfig"
329 332
333if SPARC64
334source "kernel/power/Kconfig"
335endif
336
330config SCHED_SMT 337config SCHED_SMT
331 bool "SMT (Hyperthreading) scheduler support" 338 bool "SMT (Hyperthreading) scheduler support"
332 depends on SPARC64 && SMP 339 depends on SPARC64 && SMP
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 541b8b075c7d..9ff423678cbc 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -57,6 +57,7 @@ core-y += arch/sparc/
57libs-y += arch/sparc/prom/ 57libs-y += arch/sparc/prom/
58libs-y += arch/sparc/lib/ 58libs-y += arch/sparc/lib/
59 59
60drivers-$(CONFIG_PM) += arch/sparc/power/
60drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/ 61drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/
61 62
62boot := arch/sparc/boot 63boot := arch/sparc/boot
diff --git a/arch/sparc/include/asm/hibernate.h b/arch/sparc/include/asm/hibernate.h
new file mode 100644
index 000000000000..2ec34f842249
--- /dev/null
+++ b/arch/sparc/include/asm/hibernate.h
@@ -0,0 +1,23 @@
1/*
2 * hibernate.h: Hibernaton support specific for sparc64.
3 *
4 * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
5 */
6
7#ifndef ___SPARC_HIBERNATE_H
8#define ___SPARC_HIBERNATE_H
9
10struct saved_context {
11 unsigned long fp;
12 unsigned long cwp;
13 unsigned long wstate;
14
15 unsigned long tick;
16 unsigned long pstate;
17
18 unsigned long g4;
19 unsigned long g5;
20 unsigned long g6;
21};
22
23#endif
diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
index 68f7e1118e9b..961b87f99e69 100644
--- a/arch/sparc/kernel/asm-offsets.c
+++ b/arch/sparc/kernel/asm-offsets.c
@@ -14,6 +14,8 @@
14// #include <linux/mm.h> 14// #include <linux/mm.h>
15#include <linux/kbuild.h> 15#include <linux/kbuild.h>
16 16
17#include <asm/hibernate.h>
18
17#ifdef CONFIG_SPARC32 19#ifdef CONFIG_SPARC32
18int sparc32_foo(void) 20int sparc32_foo(void)
19{ 21{
@@ -24,6 +26,19 @@ int sparc32_foo(void)
24#else 26#else
25int sparc64_foo(void) 27int sparc64_foo(void)
26{ 28{
29#ifdef CONFIG_HIBERNATION
30 BLANK();
31 OFFSET(SC_REG_FP, saved_context, fp);
32 OFFSET(SC_REG_CWP, saved_context, cwp);
33 OFFSET(SC_REG_WSTATE, saved_context, wstate);
34
35 OFFSET(SC_REG_TICK, saved_context, tick);
36 OFFSET(SC_REG_PSTATE, saved_context, pstate);
37
38 OFFSET(SC_REG_G4, saved_context, g4);
39 OFFSET(SC_REG_G5, saved_context, g5);
40 OFFSET(SC_REG_G6, saved_context, g6);
41#endif
27 return 0; 42 return 0;
28} 43}
29#endif 44#endif
diff --git a/arch/sparc/power/Makefile b/arch/sparc/power/Makefile
new file mode 100644
index 000000000000..3201ace0ddbd
--- /dev/null
+++ b/arch/sparc/power/Makefile
@@ -0,0 +1,3 @@
1# Makefile for Sparc-specific hibernate files.
2
3obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate_asm.o
diff --git a/arch/sparc/power/hibernate.c b/arch/sparc/power/hibernate.c
new file mode 100644
index 000000000000..42b0b8ce699a
--- /dev/null
+++ b/arch/sparc/power/hibernate.c
@@ -0,0 +1,42 @@
1/*
2 * hibernate.c: Hibernaton support specific for sparc64.
3 *
4 * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
5 */
6
7#include <linux/mm.h>
8
9#include <asm/hibernate.h>
10#include <asm/visasm.h>
11#include <asm/page.h>
12#include <asm/tlb.h>
13
14/* References to section boundaries */
15extern const void __nosave_begin, __nosave_end;
16
17struct saved_context saved_context;
18
19/*
20 * pfn_is_nosave - check if given pfn is in the 'nosave' section
21 */
22
23int pfn_is_nosave(unsigned long pfn)
24{
25 unsigned long nosave_begin_pfn = PFN_DOWN((unsigned long)&__nosave_begin);
26 unsigned long nosave_end_pfn = PFN_DOWN((unsigned long)&__nosave_end);
27
28 return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
29}
30
31void save_processor_state(void)
32{
33 save_and_clear_fpu();
34}
35
36void restore_processor_state(void)
37{
38 struct mm_struct *mm = current->active_mm;
39
40 load_secondary_context(mm);
41 tsb_context_switch(mm);
42}
diff --git a/arch/sparc/power/hibernate_asm.S b/arch/sparc/power/hibernate_asm.S
new file mode 100644
index 000000000000..79942166df84
--- /dev/null
+++ b/arch/sparc/power/hibernate_asm.S
@@ -0,0 +1,131 @@
1/*
2 * hibernate_asm.S: Hibernaton support specific for sparc64.
3 *
4 * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
5 */
6
7#include <linux/linkage.h>
8
9#include <asm/asm-offsets.h>
10#include <asm/cpudata.h>
11#include <asm/page.h>
12
13ENTRY(swsusp_arch_suspend)
14 save %sp, -128, %sp
15 save %sp, -128, %sp
16 flushw
17
18 setuw saved_context, %g3
19
20 /* Save window regs */
21 rdpr %cwp, %g2
22 stx %g2, [%g3 + SC_REG_CWP]
23 rdpr %wstate, %g2
24 stx %g2, [%g3 + SC_REG_WSTATE]
25 stx %fp, [%g3 + SC_REG_FP]
26
27 /* Save state regs */
28 rdpr %tick, %g2
29 stx %g2, [%g3 + SC_REG_TICK]
30 rdpr %pstate, %g2
31 stx %g2, [%g3 + SC_REG_PSTATE]
32
33 /* Save global regs */
34 stx %g4, [%g3 + SC_REG_G4]
35 stx %g5, [%g3 + SC_REG_G5]
36 stx %g6, [%g3 + SC_REG_G6]
37
38 call swsusp_save
39 nop
40
41 mov %o0, %i0
42 restore
43
44 mov %o0, %i0
45 ret
46 restore
47
48ENTRY(swsusp_arch_resume)
49 /* Write restore_pblist to %l0 */
50 sethi %hi(restore_pblist), %l0
51 ldx [%l0 + %lo(restore_pblist)], %l0
52
53 call __flush_tlb_all
54 nop
55
56 /* Write PAGE_OFFSET to %g7 */
57 sethi %uhi(PAGE_OFFSET), %g7
58 sllx %g7, 32, %g7
59
60 setuw (PAGE_SIZE-8), %g3
61
62 /* Use MMU Bypass */
63 rd %asi, %g1
64 wr %g0, ASI_PHYS_USE_EC, %asi
65
66 ba fill_itlb
67 nop
68
69pbe_loop:
70 cmp %l0, %g0
71 be restore_ctx
72 sub %l0, %g7, %l0
73
74 ldxa [%l0 ] %asi, %l1 /* address */
75 ldxa [%l0 + 8] %asi, %l2 /* orig_address */
76
77 /* phys addr */
78 sub %l1, %g7, %l1
79 sub %l2, %g7, %l2
80
81 mov %g3, %l3 /* PAGE_SIZE-8 */
82copy_loop:
83 ldxa [%l1 + %l3] ASI_PHYS_USE_EC, %g2
84 stxa %g2, [%l2 + %l3] ASI_PHYS_USE_EC
85 cmp %l3, %g0
86 bne copy_loop
87 sub %l3, 8, %l3
88
89 /* next pbe */
90 ba pbe_loop
91 ldxa [%l0 + 16] %asi, %l0
92
93restore_ctx:
94 setuw saved_context, %g3
95
96 /* Restore window regs */
97 wrpr %g0, 0, %canrestore
98 wrpr %g0, 0, %otherwin
99 wrpr %g0, 6, %cansave
100 wrpr %g0, 0, %cleanwin
101
102 ldxa [%g3 + SC_REG_CWP] %asi, %g2
103 wrpr %g2, %cwp
104 ldxa [%g3 + SC_REG_WSTATE] %asi, %g2
105 wrpr %g2, %wstate
106 ldxa [%g3 + SC_REG_FP] %asi, %fp
107
108 /* Restore state regs */
109 ldxa [%g3 + SC_REG_PSTATE] %asi, %g2
110 wrpr %g2, %pstate
111 ldxa [%g3 + SC_REG_TICK] %asi, %g2
112 wrpr %g2, %tick
113
114 /* Restore global regs */
115 ldxa [%g3 + SC_REG_G4] %asi, %g4
116 ldxa [%g3 + SC_REG_G5] %asi, %g5
117 ldxa [%g3 + SC_REG_G6] %asi, %g6
118
119 wr %g1, %g0, %asi
120
121 restore
122 restore
123
124 wrpr %g0, 14, %pil
125
126 retl
127 mov %g0, %o0
128
129fill_itlb:
130 ba pbe_loop
131 wrpr %g0, 15, %pil