diff options
-rw-r--r-- | arch/sparc/Kconfig | 7 | ||||
-rw-r--r-- | arch/sparc/Makefile | 1 | ||||
-rw-r--r-- | arch/sparc/include/asm/hibernate.h | 23 | ||||
-rw-r--r-- | arch/sparc/kernel/asm-offsets.c | 15 | ||||
-rw-r--r-- | arch/sparc/power/Makefile | 3 | ||||
-rw-r--r-- | arch/sparc/power/hibernate.c | 42 | ||||
-rw-r--r-- | arch/sparc/power/hibernate_asm.S | 131 |
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 | ||
103 | config ARCH_HIBERNATION_POSSIBLE | ||
104 | def_bool y if SPARC64 | ||
105 | |||
103 | config AUDIT_ARCH | 106 | config AUDIT_ARCH |
104 | bool | 107 | bool |
105 | default y | 108 | default y |
@@ -327,6 +330,10 @@ config ARCH_SPARSEMEM_DEFAULT | |||
327 | 330 | ||
328 | source "mm/Kconfig" | 331 | source "mm/Kconfig" |
329 | 332 | ||
333 | if SPARC64 | ||
334 | source "kernel/power/Kconfig" | ||
335 | endif | ||
336 | |||
330 | config SCHED_SMT | 337 | config 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/ | |||
57 | libs-y += arch/sparc/prom/ | 57 | libs-y += arch/sparc/prom/ |
58 | libs-y += arch/sparc/lib/ | 58 | libs-y += arch/sparc/lib/ |
59 | 59 | ||
60 | drivers-$(CONFIG_PM) += arch/sparc/power/ | ||
60 | drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/ | 61 | drivers-$(CONFIG_OPROFILE) += arch/sparc/oprofile/ |
61 | 62 | ||
62 | boot := arch/sparc/boot | 63 | boot := 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 | |||
10 | struct 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 |
18 | int sparc32_foo(void) | 20 | int sparc32_foo(void) |
19 | { | 21 | { |
@@ -24,6 +26,19 @@ int sparc32_foo(void) | |||
24 | #else | 26 | #else |
25 | int sparc64_foo(void) | 27 | int 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 | |||
3 | obj-$(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 */ | ||
15 | extern const void __nosave_begin, __nosave_end; | ||
16 | |||
17 | struct saved_context saved_context; | ||
18 | |||
19 | /* | ||
20 | * pfn_is_nosave - check if given pfn is in the 'nosave' section | ||
21 | */ | ||
22 | |||
23 | int 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 | |||
31 | void save_processor_state(void) | ||
32 | { | ||
33 | save_and_clear_fpu(); | ||
34 | } | ||
35 | |||
36 | void 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 | |||
13 | ENTRY(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 | |||
48 | ENTRY(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 | |||
69 | pbe_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 */ | ||
82 | copy_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 | |||
93 | restore_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 | |||
129 | fill_itlb: | ||
130 | ba pbe_loop | ||
131 | wrpr %g0, 15, %pil | ||