xref: /openbmc/linux/arch/riscv/kernel/hibernate-asm.S (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1*c0317210SSia Jee Heng/* SPDX-License-Identifier: GPL-2.0-only */
2*c0317210SSia Jee Heng/*
3*c0317210SSia Jee Heng * Hibernation low level support for RISCV.
4*c0317210SSia Jee Heng *
5*c0317210SSia Jee Heng * Copyright (C) 2023 StarFive Technology Co., Ltd.
6*c0317210SSia Jee Heng *
7*c0317210SSia Jee Heng * Author: Jee Heng Sia <jeeheng.sia@starfivetech.com>
8*c0317210SSia Jee Heng */
9*c0317210SSia Jee Heng
10*c0317210SSia Jee Heng#include <asm/asm.h>
11*c0317210SSia Jee Heng#include <asm/asm-offsets.h>
12*c0317210SSia Jee Heng#include <asm/assembler.h>
13*c0317210SSia Jee Heng#include <asm/csr.h>
14*c0317210SSia Jee Heng
15*c0317210SSia Jee Heng#include <linux/linkage.h>
16*c0317210SSia Jee Heng
17*c0317210SSia Jee Heng/*
18*c0317210SSia Jee Heng * int __hibernate_cpu_resume(void)
19*c0317210SSia Jee Heng * Switch back to the hibernated image's page table prior to restoring the CPU
20*c0317210SSia Jee Heng * context.
21*c0317210SSia Jee Heng *
22*c0317210SSia Jee Heng * Always returns 0
23*c0317210SSia Jee Heng */
24*c0317210SSia Jee HengENTRY(__hibernate_cpu_resume)
25*c0317210SSia Jee Heng	/* switch to hibernated image's page table. */
26*c0317210SSia Jee Heng	csrw CSR_SATP, s0
27*c0317210SSia Jee Heng	sfence.vma
28*c0317210SSia Jee Heng
29*c0317210SSia Jee Heng	REG_L	a0, hibernate_cpu_context
30*c0317210SSia Jee Heng
31*c0317210SSia Jee Heng	suspend_restore_regs
32*c0317210SSia Jee Heng
33*c0317210SSia Jee Heng	/* Return zero value. */
34*c0317210SSia Jee Heng	mv	a0, zero
35*c0317210SSia Jee Heng
36*c0317210SSia Jee Heng	ret
37*c0317210SSia Jee HengEND(__hibernate_cpu_resume)
38*c0317210SSia Jee Heng
39*c0317210SSia Jee Heng/*
40*c0317210SSia Jee Heng * Prepare to restore the image.
41*c0317210SSia Jee Heng * a0: satp of saved page tables.
42*c0317210SSia Jee Heng * a1: satp of temporary page tables.
43*c0317210SSia Jee Heng * a2: cpu_resume.
44*c0317210SSia Jee Heng */
45*c0317210SSia Jee HengENTRY(hibernate_restore_image)
46*c0317210SSia Jee Heng	mv	s0, a0
47*c0317210SSia Jee Heng	mv	s1, a1
48*c0317210SSia Jee Heng	mv	s2, a2
49*c0317210SSia Jee Heng	REG_L	s4, restore_pblist
50*c0317210SSia Jee Heng	REG_L	a1, relocated_restore_code
51*c0317210SSia Jee Heng
52*c0317210SSia Jee Heng	jr	a1
53*c0317210SSia Jee HengEND(hibernate_restore_image)
54*c0317210SSia Jee Heng
55*c0317210SSia Jee Heng/*
56*c0317210SSia Jee Heng * The below code will be executed from a 'safe' page.
57*c0317210SSia Jee Heng * It first switches to the temporary page table, then starts to copy the pages
58*c0317210SSia Jee Heng * back to the original memory location. Finally, it jumps to __hibernate_cpu_resume()
59*c0317210SSia Jee Heng * to restore the CPU context.
60*c0317210SSia Jee Heng */
61*c0317210SSia Jee HengENTRY(hibernate_core_restore_code)
62*c0317210SSia Jee Heng	/* switch to temp page table. */
63*c0317210SSia Jee Heng	csrw satp, s1
64*c0317210SSia Jee Heng	sfence.vma
65*c0317210SSia Jee Heng.Lcopy:
66*c0317210SSia Jee Heng	/* The below code will restore the hibernated image. */
67*c0317210SSia Jee Heng	REG_L	a1, HIBERN_PBE_ADDR(s4)
68*c0317210SSia Jee Heng	REG_L	a0, HIBERN_PBE_ORIG(s4)
69*c0317210SSia Jee Heng
70*c0317210SSia Jee Heng	copy_page a0, a1
71*c0317210SSia Jee Heng
72*c0317210SSia Jee Heng	REG_L	s4, HIBERN_PBE_NEXT(s4)
73*c0317210SSia Jee Heng	bnez	s4, .Lcopy
74*c0317210SSia Jee Heng
75*c0317210SSia Jee Heng	jr	s2
76*c0317210SSia Jee HengEND(hibernate_core_restore_code)
77*c0317210SSia Jee Heng