Skip to content

Commit 733f5c2

Browse files
committed
xtensa: add hibernation support
Define ARCH_HIBERNATION_POSSIBLE in Kconfig and implement hibernation callbacks. Signed-off-by: Max Filippov <[email protected]>
1 parent 11e969b commit 733f5c2

File tree

5 files changed

+129
-0
lines changed

5 files changed

+129
-0
lines changed

arch/xtensa/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,9 @@ endmenu
787787

788788
menu "Power management options"
789789

790+
config ARCH_HIBERNATION_POSSIBLE
791+
def_bool y
792+
790793
source "kernel/power/Kconfig"
791794

792795
endmenu

arch/xtensa/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ obj-$(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) += perf_event.o
1919
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
2020
obj-$(CONFIG_S32C1I_SELFTEST) += s32c1i_selftest.o
2121
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
22+
obj-$(CONFIG_HIBERNATION) += hibernate.o
2223

2324
# In the Xtensa architecture, assembly generates literals which must always
2425
# precede the L32R instruction with a relative offset less than 256 kB.

arch/xtensa/kernel/asm-offsets.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/ptrace.h>
2222
#include <linux/mm.h>
2323
#include <linux/kbuild.h>
24+
#include <linux/suspend.h>
2425

2526
#include <asm/ptrace.h>
2627
#include <asm/traps.h>
@@ -149,5 +150,12 @@ int main(void)
149150
offsetof(struct exc_table, fast_kernel_handler));
150151
DEFINE(EXC_TABLE_DEFAULT, offsetof(struct exc_table, default_handler));
151152

153+
#ifdef CONFIG_HIBERNATION
154+
DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));
155+
DEFINE(PBE_ORIG_ADDRESS, offsetof(struct pbe, orig_address));
156+
DEFINE(PBE_NEXT, offsetof(struct pbe, next));
157+
DEFINE(PBE_SIZE, sizeof(struct pbe));
158+
#endif
159+
152160
return 0;
153161
}

arch/xtensa/kernel/entry.S

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,3 +2155,95 @@ ENTRY(ret_from_kernel_thread)
21552155
j common_exception_return
21562156

21572157
ENDPROC(ret_from_kernel_thread)
2158+
2159+
#ifdef CONFIG_HIBERNATION
2160+
2161+
.bss
2162+
.align 4
2163+
.Lsaved_regs:
2164+
#if defined(__XTENSA_WINDOWED_ABI__)
2165+
.fill 2, 4
2166+
#elif defined(__XTENSA_CALL0_ABI__)
2167+
.fill 6, 4
2168+
#else
2169+
#error Unsupported Xtensa ABI
2170+
#endif
2171+
.align XCHAL_NCP_SA_ALIGN
2172+
.Lsaved_user_regs:
2173+
.fill XTREGS_USER_SIZE, 1
2174+
2175+
.previous
2176+
2177+
ENTRY(swsusp_arch_suspend)
2178+
2179+
abi_entry_default
2180+
2181+
movi a2, .Lsaved_regs
2182+
movi a3, .Lsaved_user_regs
2183+
s32i a0, a2, 0
2184+
s32i a1, a2, 4
2185+
save_xtregs_user a3 a4 a5 a6 a7 a8 0
2186+
#if defined(__XTENSA_WINDOWED_ABI__)
2187+
spill_registers_kernel
2188+
#elif defined(__XTENSA_CALL0_ABI__)
2189+
s32i a12, a2, 8
2190+
s32i a13, a2, 12
2191+
s32i a14, a2, 16
2192+
s32i a15, a2, 20
2193+
#else
2194+
#error Unsupported Xtensa ABI
2195+
#endif
2196+
abi_call swsusp_save
2197+
mov a2, abi_rv
2198+
abi_ret_default
2199+
2200+
ENDPROC(swsusp_arch_suspend)
2201+
2202+
ENTRY(swsusp_arch_resume)
2203+
2204+
abi_entry_default
2205+
2206+
#if defined(__XTENSA_WINDOWED_ABI__)
2207+
spill_registers_kernel
2208+
#endif
2209+
2210+
movi a2, restore_pblist
2211+
l32i a2, a2, 0
2212+
2213+
.Lcopy_pbe:
2214+
l32i a3, a2, PBE_ADDRESS
2215+
l32i a4, a2, PBE_ORIG_ADDRESS
2216+
2217+
__loopi a3, a9, PAGE_SIZE, 16
2218+
l32i a5, a3, 0
2219+
l32i a6, a3, 4
2220+
l32i a7, a3, 8
2221+
l32i a8, a3, 12
2222+
addi a3, a3, 16
2223+
s32i a5, a4, 0
2224+
s32i a6, a4, 4
2225+
s32i a7, a4, 8
2226+
s32i a8, a4, 12
2227+
addi a4, a4, 16
2228+
__endl a3, a9
2229+
2230+
l32i a2, a2, PBE_NEXT
2231+
bnez a2, .Lcopy_pbe
2232+
2233+
movi a2, .Lsaved_regs
2234+
movi a3, .Lsaved_user_regs
2235+
l32i a0, a2, 0
2236+
l32i a1, a2, 4
2237+
load_xtregs_user a3 a4 a5 a6 a7 a8 0
2238+
#if defined(__XTENSA_CALL0_ABI__)
2239+
l32i a12, a2, 8
2240+
l32i a13, a2, 12
2241+
l32i a14, a2, 16
2242+
l32i a15, a2, 20
2243+
#endif
2244+
movi a2, 0
2245+
abi_ret_default
2246+
2247+
ENDPROC(swsusp_arch_resume)
2248+
2249+
#endif

arch/xtensa/kernel/hibernate.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
#include <linux/mm.h>
4+
#include <linux/suspend.h>
5+
#include <asm/coprocessor.h>
6+
7+
int pfn_is_nosave(unsigned long pfn)
8+
{
9+
unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
10+
unsigned long nosave_end_pfn = PFN_UP(__pa(&__nosave_end));
11+
12+
return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
13+
}
14+
15+
void notrace save_processor_state(void)
16+
{
17+
WARN_ON(num_online_cpus() != 1);
18+
#if XTENSA_HAVE_COPROCESSORS
19+
local_coprocessors_flush_release_all();
20+
#endif
21+
}
22+
23+
void notrace restore_processor_state(void)
24+
{
25+
}

0 commit comments

Comments
 (0)