2013-07-17 03:14:45 -06:00
|
|
|
#ifndef __ASM_SUSPEND_H
|
|
|
|
#define __ASM_SUSPEND_H
|
|
|
|
|
2016-04-27 10:47:07 -06:00
|
|
|
#define NR_CTX_REGS 10
|
2016-04-27 10:47:06 -06:00
|
|
|
#define NR_CALLEE_SAVED_REGS 12
|
2013-07-17 03:14:45 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* struct cpu_suspend_ctx must be 16-byte aligned since it is allocated on
|
|
|
|
* the stack, which must be 16-byte aligned on v8
|
|
|
|
*/
|
|
|
|
struct cpu_suspend_ctx {
|
|
|
|
/*
|
|
|
|
* This struct must be kept in sync with
|
|
|
|
* cpu_do_{suspend/resume} in mm/proc.S
|
|
|
|
*/
|
|
|
|
u64 ctx_regs[NR_CTX_REGS];
|
|
|
|
u64 sp;
|
|
|
|
} __aligned(16);
|
arm64: kernel: cpu_{suspend/resume} implementation
Kernel subsystems like CPU idle and suspend to RAM require a generic
mechanism to suspend a processor, save its context and put it into
a quiescent state. The cpu_{suspend}/{resume} implementation provides
such a framework through a kernel interface allowing to save/restore
registers, flush the context to DRAM and suspend/resume to/from
low-power states where processor context may be lost.
The CPU suspend implementation relies on the suspend protocol registered
in CPU operations to carry out a suspend request after context is
saved and flushed to DRAM. The cpu_suspend interface:
int cpu_suspend(unsigned long arg);
allows to pass an opaque parameter that is handed over to the suspend CPU
operations back-end so that it can take action according to the
semantics attached to it. The arg parameter allows suspend to RAM and CPU
idle drivers to communicate to suspend protocol back-ends; it requires
standardization so that the interface can be reused seamlessly across
systems, paving the way for generic drivers.
Context memory is allocated on the stack, whose address is stashed in a
per-cpu variable to keep track of it and passed to core functions that
save/restore the registers required by the architecture.
Even though, upon successful execution, the cpu_suspend function shuts
down the suspending processor, the warm boot resume mechanism, based
on the cpu_resume function, makes the resume path operate as a
cpu_suspend function return, so that cpu_suspend can be treated as a C
function by the caller, which simplifies coding the PM drivers that rely
on the cpu_suspend API.
Upon context save, the minimal amount of memory is flushed to DRAM so
that it can be retrieved when the MMU is off and caches are not searched.
The suspend CPU operation, depending on the required operations (eg CPU vs
Cluster shutdown) is in charge of flushing the cache hierarchy either
implicitly (by calling firmware implementations like PSCI) or explicitly
by executing the required cache maintainance functions.
Debug exceptions are disabled during cpu_{suspend}/{resume} operations
so that debug registers can be saved and restored properly preventing
preemption from debug agents enabled in the kernel.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
2013-07-22 05:22:13 -06:00
|
|
|
|
2016-04-27 10:47:06 -06:00
|
|
|
/*
|
|
|
|
* Memory to save the cpu state is allocated on the stack by
|
|
|
|
* __cpu_suspend_enter()'s caller, and populated by __cpu_suspend_enter().
|
|
|
|
* This data must survive until cpu_resume() is called.
|
|
|
|
*
|
|
|
|
* This struct desribes the size and the layout of the saved cpu state.
|
|
|
|
* The layout of the callee_saved_regs is defined by the implementation
|
|
|
|
* of __cpu_suspend_enter(), and cpu_resume(). This struct must be passed
|
|
|
|
* in by the caller as __cpu_suspend_enter()'s stack-frame is gone once it
|
|
|
|
* returns, and the data would be subsequently corrupted by the call to the
|
|
|
|
* finisher.
|
|
|
|
*/
|
|
|
|
struct sleep_stack_data {
|
|
|
|
struct cpu_suspend_ctx system_regs;
|
|
|
|
unsigned long callee_saved_regs[NR_CALLEE_SAVED_REGS];
|
|
|
|
};
|
|
|
|
|
2016-04-27 10:47:07 -06:00
|
|
|
extern unsigned long *sleep_save_stash;
|
|
|
|
|
2015-06-18 08:41:32 -06:00
|
|
|
extern int cpu_suspend(unsigned long arg, int (*fn)(unsigned long));
|
arm64: kernel: cpu_{suspend/resume} implementation
Kernel subsystems like CPU idle and suspend to RAM require a generic
mechanism to suspend a processor, save its context and put it into
a quiescent state. The cpu_{suspend}/{resume} implementation provides
such a framework through a kernel interface allowing to save/restore
registers, flush the context to DRAM and suspend/resume to/from
low-power states where processor context may be lost.
The CPU suspend implementation relies on the suspend protocol registered
in CPU operations to carry out a suspend request after context is
saved and flushed to DRAM. The cpu_suspend interface:
int cpu_suspend(unsigned long arg);
allows to pass an opaque parameter that is handed over to the suspend CPU
operations back-end so that it can take action according to the
semantics attached to it. The arg parameter allows suspend to RAM and CPU
idle drivers to communicate to suspend protocol back-ends; it requires
standardization so that the interface can be reused seamlessly across
systems, paving the way for generic drivers.
Context memory is allocated on the stack, whose address is stashed in a
per-cpu variable to keep track of it and passed to core functions that
save/restore the registers required by the architecture.
Even though, upon successful execution, the cpu_suspend function shuts
down the suspending processor, the warm boot resume mechanism, based
on the cpu_resume function, makes the resume path operate as a
cpu_suspend function return, so that cpu_suspend can be treated as a C
function by the caller, which simplifies coding the PM drivers that rely
on the cpu_suspend API.
Upon context save, the minimal amount of memory is flushed to DRAM so
that it can be retrieved when the MMU is off and caches are not searched.
The suspend CPU operation, depending on the required operations (eg CPU vs
Cluster shutdown) is in charge of flushing the cache hierarchy either
implicitly (by calling firmware implementations like PSCI) or explicitly
by executing the required cache maintainance functions.
Debug exceptions are disabled during cpu_{suspend}/{resume} operations
so that debug registers can be saved and restored properly preventing
preemption from debug agents enabled in the kernel.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
2013-07-22 05:22:13 -06:00
|
|
|
extern void cpu_resume(void);
|
2016-04-27 10:47:06 -06:00
|
|
|
int __cpu_suspend_enter(struct sleep_stack_data *state);
|
|
|
|
void __cpu_suspend_exit(void);
|
2016-04-27 10:47:12 -06:00
|
|
|
void _cpu_resume(void);
|
|
|
|
|
|
|
|
int swsusp_arch_suspend(void);
|
|
|
|
int swsusp_arch_resume(void);
|
|
|
|
int arch_hibernation_header_save(void *addr, unsigned int max_size);
|
|
|
|
int arch_hibernation_header_restore(void *addr);
|
|
|
|
|
2013-07-17 03:14:45 -06:00
|
|
|
#endif
|