ARM: kernel: update cpu_suspend code to use cache LoUIS operations
In processors like A15/A7 L2 cache is unified and integrated within the processor cache hierarchy, so that it is not considered an outer cache anymore. For processors like A15/A7 flush_cache_all() ends up cleaning all cache levels up to Level of Coherency (LoC) that includes the L2 unified cache. When a single CPU is suspended (CPU idle) a complete L2 clean is not required, so generic cpu_suspend code must clean the data cache using the newly introduced cache LoUIS function. The context and stack pointer (context pointer) are cleaned to main memory using cache area functions that operate on MVA and guarantee that the data is written back to main memory (perform cache cleaning up to the Point of Coherency - PoC) so that the processor can fetch the context when the MMU is off in the cpu_resume code path. outer_cache management remains unchanged. Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Reviewed-by: Nicolas Pitre <nico@linaro.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Tested-by: Shawn Guo <shawn.guo@linaro.org>
This commit is contained in:
Родитель
3287be8c4e
Коммит
dbee0c6fb4
|
@ -17,6 +17,8 @@ extern void cpu_resume_mmu(void);
|
|||
*/
|
||||
void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
|
||||
{
|
||||
u32 *ctx = ptr;
|
||||
|
||||
*save_ptr = virt_to_phys(ptr);
|
||||
|
||||
/* This must correspond to the LDM in cpu_resume() assembly */
|
||||
|
@ -26,7 +28,20 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
|
|||
|
||||
cpu_do_suspend(ptr);
|
||||
|
||||
flush_cache_all();
|
||||
flush_cache_louis();
|
||||
|
||||
/*
|
||||
* flush_cache_louis does not guarantee that
|
||||
* save_ptr and ptr are cleaned to main memory,
|
||||
* just up to the Level of Unification Inner Shareable.
|
||||
* Since the context pointer and context itself
|
||||
* are to be retrieved with the MMU off that
|
||||
* data must be cleaned from all cache levels
|
||||
* to main memory using "area" cache primitives.
|
||||
*/
|
||||
__cpuc_flush_dcache_area(ctx, ptrsz);
|
||||
__cpuc_flush_dcache_area(save_ptr, sizeof(*save_ptr));
|
||||
|
||||
outer_clean_range(*save_ptr, *save_ptr + ptrsz);
|
||||
outer_clean_range(virt_to_phys(save_ptr),
|
||||
virt_to_phys(save_ptr) + sizeof(*save_ptr));
|
||||
|
|
Загрузка…
Ссылка в новой задаче