Add L2 cache cleaning to generic CPU suspend
Subsystems (2)
cover Add L2 cache cleaning to generic CPU suspend
This is a re-post of the previous patch series, but with an additional TLB flush to ensure that hte global TLB entry in the page tables is flushed out. This is a flush of all TLB entries, but it could probably be more targetted if we need to.
Original cover mail follows:
Some systems (such as OMAP) preserve the L2 cache across a suspend/ resume cycle. This means they do not perform L2 cache maintanence in their suspend finisher function.
However, the side effect is that the saved CPU state is not readable by the resume code because it is sitting in the L2 cache.
This patch series adds L2 cache cleaning to the generic CPU suspend/ resume support code, making it possible to use this on systems with L2 cache enabled without having to clean/invalidate the entire L2 cache.
We also add a separate page table, allocated at boot time, for the resume process to use so we don't have to fiddle about with tweaking entries in the current processes page table. Moreover, the current processes page table may be in use by another CPU in the system if these paths are used from cpuidle or hotplug, so changing the page table is technically unsound.
Overall, this makes it possible for OMAP4 systems to use this code.
PATCH 1/7 ARM: pm: force non-zero return value from __cpu_suspend when aborting
Ensure that the return value from __cpu_suspend is non-zero when aborting. Zero indicates a successful suspend occurred.
--- arch/arm/kernel/sleep.S | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/kernel/sleep.S +2 -0
@@ -61,6 +61,8 @@ ENDPROC(__cpu_suspend) cpu_suspend_abort: ldmia sp!, {r1 - r3} @ pop v:p, virt SP, phys resume fn + teq r0, #0 + moveq r0, #1 @ force non-zero value mov sp, r2 ldmfd sp!, {r4 - r11, pc} ENDPROC(cpu_suspend_abort)
Signature · 1 line
1.7.4.4
PATCH 2/7 ARM: pm: preallocate a page table for suspend/resume
In reply to Russell King - ARM LinuxPreallocate a page table and setup an identity mapping for the MMU enable code. This means we don't have to "borrow" a page table to do this, avoiding complexities with L2 cache coherency.
--- arch/arm/include/asm/suspend.h | 17 +------------- arch/arm/kernel/Makefile | 2 +- arch/arm/kernel/sleep.S | 33 ++++++++++----------------- arch/arm/kernel/suspend.c | 48 ++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/proc-arm920.S | 4 --- arch/arm/mm/proc-arm926.S | 4 --- arch/arm/mm/proc-sa1100.S | 4 --- arch/arm/mm/proc-v6.S | 6 ----- arch/arm/mm/proc-v7.S | 6 ----- arch/arm/mm/proc-xsc3.S | 6 ----- arch/arm/mm/proc-xscale.S | 4 --- 11 files changed, 62 insertions(+), 72 deletions(-) create mode 100644 arch/arm/kernel/suspend.c
arch/arm/include/asm/suspend.h +1 -16
@@ -1,22 +1,7 @@#ifndef __ASM_ARM_SUSPEND_H#define __ASM_ARM_SUSPEND_H -#include <asm/memory.h> -#include <asm/tlbflush.h> -extern void cpu_resume (void ); - -/* -* Hide the first two arguments to __cpu_suspend - these are an implementation -* detail which platform code shouldn't have to know about. -*/ -static inline int cpu_suspend (unsigned long arg,int (*fn)(unsigned long )) -{ -extern int __cpu_suspend (int ,long ,unsigned long , -int (*)(unsigned long )); -int ret =__cpu_suspend (0 ,PHYS_OFFSET -PAGE_OFFSET , arg, fn); -flush_tlb_all (); -return ret; -} +extern int cpu_suspend (unsigned long ,int (*)(unsigned long ));#endif
arch/arm/kernel/Makefile +1 -1
@@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o isa.o -obj-$(CONFIG_PM_SLEEP) += sleep.o +obj-$(CONFIG_PM_SLEEP) += sleep.o suspend.o obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o obj-$(CONFIG_SMP) += smp.o smp_tlb.o obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
arch/arm/kernel/sleep.S +12 -21
@@ -27,7 +27,7 @@ ENTRY(__cpu_suspend) sub sp, sp, r5 @ allocate CPU state on stack mov r0, sp @ save pointer to CPU save block add ip, ip, r1 @ convert resume fn to phys - stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn + stmfd sp!, {r6, ip} @ save virt SP, phys resume fn ldr r5, =sleep_save_sp add r6, sp, r1 @ convert SP to phys stmfd sp!, {r2, r3} @ save suspend func arg and pointer
@@ -60,7 +60,7 @@ ENDPROC(__cpu_suspend) .ltorg cpu_suspend_abort: - ldmia sp!, {r1 - r3} @ pop v:p, virt SP, phys resume fn + ldmia sp!, {r2 - r3} @ pop virt SP, phys resume fn teq r0, #0 moveq r0, #1 @ force non-zero value mov sp, r2
@@ -74,28 +74,19 @@ ENDPROC(cpu_suspend_abort) * r3 = L1 section flags */ ENTRY(cpu_resume_mmu) - adr r4, cpu_resume_turn_mmu_on - mov r4, r4, lsr #20 - orr r3, r3, r4, lsl #20 - ldr r5, [r2, r4, lsl #2] @ save old mapping - str r3, [r2, r4, lsl #2] @ setup 1:1 mapping for mmu code - sub r2, r2, r1 ldr r3, =cpu_resume_after_mmu - bic r1, r0, #CR_C @ ensure D-cache is disabled b cpu_resume_turn_mmu_on ENDPROC(cpu_resume_mmu) .ltorg .align 5 -cpu_resume_turn_mmu_on: - mcr p15, 0, r1, c1, c0, 0 @ turn on MMU, I-cache, etc - mrc p15, 0, r1, c0, c0, 0 @ read id reg - mov r1, r1 - mov r1, r1 +ENTRY(cpu_resume_turn_mmu_on) + mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc + mrc p15, 0, r0, c0, c0, 0 @ read id reg + mov r0, r0 + mov r0, r0 mov pc, r3 @ jump to virtual address ENDPROC(cpu_resume_turn_mmu_on) cpu_resume_after_mmu: - str r5, [r2, r4, lsl #2] @ restore old mapping - mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache bl cpu_init @ restore the und/abt/irq banked regs mov r0, #0 @ return zero on success ldmfd sp!, {r4 - r11, pc}
@@ -121,11 +112,11 @@ ENTRY(cpu_resume) ldr r0, sleep_save_sp @ stack phys addr #endif setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off - @ load v:p, stack, resume fn - ARM( ldmia r0!, {r1, sp, pc} ) -THUMB( ldmia r0!, {r1, r2, r3} ) -THUMB( mov sp, r2 ) -THUMB( bx r3 ) + @ load stack, resume fn + ARM( ldmia r0!, {sp, pc} ) +THUMB( ldmia r0!, {r2, r3} ) +THUMB( mov sp, r2 ) +THUMB( bx r3 ) ENDPROC(cpu_resume) sleep_save_sp:
arch/arm/kernel/suspend.c new file +48 -0
48 lines not on this page · raw message
arch/arm/mm/proc-arm920.S +0 -4
@@ -400,10 +400,6 @@ ENTRY(cpu_arm920_do_resume) mcr p15, 0, r5, c3, c0, 0 @ Domain ID mcr p15, 0, r6, c2, c0, 0 @ TTB address mov r0, r7 @ control register - mov r2, r6, lsr #14 @ get TTB0 base - mov r2, r2, lsl #14 - ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \ - PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE b cpu_resume_mmu ENDPROC(cpu_arm920_do_resume) #endif
arch/arm/mm/proc-arm926.S +0 -4
@@ -415,10 +415,6 @@ ENTRY(cpu_arm926_do_resume) mcr p15, 0, r5, c3, c0, 0 @ Domain ID mcr p15, 0, r6, c2, c0, 0 @ TTB address mov r0, r7 @ control register - mov r2, r6, lsr #14 @ get TTB0 base - mov r2, r2, lsl #14 - ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \ - PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE b cpu_resume_mmu ENDPROC(cpu_arm926_do_resume) #endif
arch/arm/mm/proc-sa1100.S +0 -4
@@ -192,10 +192,6 @@ ENTRY(cpu_sa1100_do_resume) mcr p15, 0, r5, c2, c0, 0 @ translation table base addr mcr p15, 0, r6, c13, c0, 0 @ PID mov r0, r7 @ control register - mov r2, r5, lsr #14 @ get TTB0 base - mov r2, r2, lsl #14 - ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \ - PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE b cpu_resume_mmu ENDPROC(cpu_sa1100_do_resume) #endif
arch/arm/mm/proc-v6.S +0 -6
@@ -161,14 +161,8 @@ ENTRY(cpu_v6_do_resume) mcr p15, 0, ip, c2, c0, 2 @ TTB control register mcr p15, 0, ip, c7, c5, 4 @ ISB mov r0, r11 @ control register - mov r2, r7, lsr #14 @ get TTB0 base - mov r2, r2, lsl #14 - ldr r3, cpu_resume_l1_flags b cpu_resume_mmu ENDPROC(cpu_v6_do_resume) -cpu_resume_l1_flags: - ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP) - ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP) #endif string cpu_v6_name, "ARMv6-compatible processor"
arch/arm/mm/proc-v7.S +0 -6
@@ -259,14 +259,8 @@ ENTRY(cpu_v7_do_resume) isb dsb mov r0, r9 @ control register - mov r2, r7, lsr #14 @ get TTB0 base - mov r2, r2, lsl #14 - ldr r3, cpu_resume_l1_flags b cpu_resume_mmu ENDPROC(cpu_v7_do_resume) -cpu_resume_l1_flags: - ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP) - ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP) #endif __CPUINIT
arch/arm/mm/proc-xsc3.S +0 -6
@@ -435,13 +435,7 @@ ENTRY(cpu_xsc3_do_resume) mcr p15, 0, r7, c3, c0, 0 @ domain ID mcr p15, 0, r8, c2, c0, 0 @ translation table base addr mcr p15, 0, r9, c1, c0, 1 @ auxiliary control reg - - @ temporarily map resume_turn_on_mmu into the page table, - @ otherwise prefetch abort occurs after MMU is turned on mov r0, r10 @ control register - mov r2, r8, lsr #14 @ get TTB0 base - mov r2, r2, lsl #14 - ldr r3, =0x542e @ section flags b cpu_resume_mmu ENDPROC(cpu_xsc3_do_resume) #endif
arch/arm/mm/proc-xscale.S +0 -4
@@ -548,10 +548,6 @@ ENTRY(cpu_xscale_do_resume) mcr p15, 0, r8, c2, c0, 0 @ translation table base addr mcr p15, 0, r9, c1, c1, 0 @ auxiliary control reg mov r0, r10 @ control register - mov r2, r8, lsr #14 @ get TTB0 base - mov r2, r2, lsl #14 - ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \ - PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE b cpu_resume_mmu ENDPROC(cpu_xscale_do_resume) #endif
Signature · 1 line
1.7.4.4
PATCH 3/7 ARM: pm: only use preallocated page table during resume
In reply to Russell King - ARM LinuxOnly use the preallocated page table during the resume, not while suspending. This avoids the overhead of having to switch unnecessarily to the resume page table in the suspend path.
--- arch/arm/kernel/sleep.S | 19 +++++++++---------- arch/arm/kernel/suspend.c | 17 ++++++++++------- arch/arm/mm/proc-arm920.S | 17 ++++++++--------- arch/arm/mm/proc-arm926.S | 17 ++++++++--------- arch/arm/mm/proc-sa1100.S | 21 ++++++++++----------- arch/arm/mm/proc-v6.S | 31 ++++++++++++++++--------------- arch/arm/mm/proc-v7.S | 33 +++++++++++++++++---------------- arch/arm/mm/proc-xsc3.S | 22 +++++++++++----------- arch/arm/mm/proc-xscale.S | 21 ++++++++++----------- 9 files changed, 99 insertions(+), 99 deletions(-)
arch/arm/kernel/sleep.S +9 -10
@@ -9,12 +9,14 @@ /* * Save CPU state for a suspend + * r0 = phys addr of temporary page tables * r1 = v:p offset * r2 = suspend function arg0 * r3 = suspend function */ ENTRY(__cpu_suspend) stmfd sp!, {r4 - r11, lr} + mov r4, r0 #ifdef MULTI_CPU ldr r10, =processor ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
@@ -27,7 +29,7 @@ ENTRY(__cpu_suspend) sub sp, sp, r5 @ allocate CPU state on stack mov r0, sp @ save pointer to CPU save block add ip, ip, r1 @ convert resume fn to phys - stmfd sp!, {r6, ip} @ save virt SP, phys resume fn + stmfd sp!, {r4, r6, ip} @ save phys pgd, virt SP, phys resume fn ldr r5, =sleep_save_sp add r6, sp, r1 @ convert SP to phys stmfd sp!, {r2, r3} @ save suspend func arg and pointer
@@ -60,7 +62,7 @@ ENDPROC(__cpu_suspend) .ltorg cpu_suspend_abort: - ldmia sp!, {r2 - r3} @ pop virt SP, phys resume fn + ldmia sp!, {r1 - r3} @ pop phys pgd, virt SP, phys resume fn teq r0, #0 moveq r0, #1 @ force non-zero value mov sp, r2
@@ -69,9 +71,6 @@ ENDPROC(cpu_suspend_abort) /* * r0 = control register value - * r1 = v:p offset (preserved by cpu_do_resume) - * r2 = phys page table base - * r3 = L1 section flags */ ENTRY(cpu_resume_mmu) ldr r3, =cpu_resume_after_mmu
@@ -112,11 +111,11 @@ ENTRY(cpu_resume) ldr r0, sleep_save_sp @ stack phys addr #endif setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off - @ load stack, resume fn - ARM( ldmia r0!, {sp, pc} ) -THUMB( ldmia r0!, {r2, r3} ) -THUMB( mov sp, r2 ) -THUMB( bx r3 ) + @ load phys pgd, stack, resume fn + ARM( ldmia r0!, {r1, sp, pc} ) +THUMB( ldmia r0!, {r1, r2, r3} ) +THUMB( mov sp, r2 ) +THUMB( bx r3 ) ENDPROC(cpu_resume) sleep_save_sp:
arch/arm/kernel/suspend.c +10 -7
@@ -24,14 +24,17 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))return -EINVAL ;/* -* Temporarily switch the page tables to our suspend page -* tables, which contain the temporary identity mapping -* required for resuming. +* Provide a temporary page table with an identity mapping for +* the MMU-enable code, required for resuming. On successful +* resume (indicated by a zero return code), we need to switch +* back to the correct page tables. */ -cpu_switch_mm (suspend_pgd, mm); - ret =__cpu_suspend (0 ,PHYS_OFFSET -PAGE_OFFSET , arg, fn); -cpu_switch_mm (mm->pgd, mm); -local_flush_tlb_all (); + ret =__cpu_suspend (virt_to_phys (suspend_pgd), +PHYS_OFFSET -PAGE_OFFSET , arg, fn); +if (ret ==0 ) { +cpu_switch_mm (mm->pgd, mm); +local_flush_tlb_all (); + }return ret; }
arch/arm/mm/proc-arm920.S +8 -9
@@ -379,27 +379,26 @@ ENTRY(cpu_arm920_set_pte_ext) /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ .globl cpu_arm920_suspend_size -.equ cpu_arm920_suspend_size, 4 * 4 +.equ cpu_arm920_suspend_size, 4 * 3 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_arm920_do_suspend) - stmfd sp!, {r4 - r7, lr} + stmfd sp!, {r4 - r6, lr} mrc p15, 0, r4, c13, c0, 0 @ PID mrc p15, 0, r5, c3, c0, 0 @ Domain ID - mrc p15, 0, r6, c2, c0, 0 @ TTB address - mrc p15, 0, r7, c1, c0, 0 @ Control register - stmia r0, {r4 - r7} - ldmfd sp!, {r4 - r7, pc} + mrc p15, 0, r6, c1, c0, 0 @ Control register + stmia r0, {r4 - r6} + ldmfd sp!, {r4 - r6, pc} ENDPROC(cpu_arm920_do_suspend) ENTRY(cpu_arm920_do_resume) mov ip, #0 mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches - ldmia r0, {r4 - r7} + ldmia r0, {r4 - r6} mcr p15, 0, r4, c13, c0, 0 @ PID mcr p15, 0, r5, c3, c0, 0 @ Domain ID - mcr p15, 0, r6, c2, c0, 0 @ TTB address - mov r0, r7 @ control register + mcr p15, 0, r1, c2, c0, 0 @ TTB address + mov r0, r6 @ control register b cpu_resume_mmu ENDPROC(cpu_arm920_do_resume) #endif
arch/arm/mm/proc-arm926.S +8 -9
@@ -394,27 +394,26 @@ ENTRY(cpu_arm926_set_pte_ext) /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ .globl cpu_arm926_suspend_size -.equ cpu_arm926_suspend_size, 4 * 4 +.equ cpu_arm926_suspend_size, 4 * 3 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_arm926_do_suspend) - stmfd sp!, {r4 - r7, lr} + stmfd sp!, {r4 - r6, lr} mrc p15, 0, r4, c13, c0, 0 @ PID mrc p15, 0, r5, c3, c0, 0 @ Domain ID - mrc p15, 0, r6, c2, c0, 0 @ TTB address - mrc p15, 0, r7, c1, c0, 0 @ Control register - stmia r0, {r4 - r7} - ldmfd sp!, {r4 - r7, pc} + mrc p15, 0, r6, c1, c0, 0 @ Control register + stmia r0, {r4 - r6} + ldmfd sp!, {r4 - r6, pc} ENDPROC(cpu_arm926_do_suspend) ENTRY(cpu_arm926_do_resume) mov ip, #0 mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches - ldmia r0, {r4 - r7} + ldmia r0, {r4 - r6} mcr p15, 0, r4, c13, c0, 0 @ PID mcr p15, 0, r5, c3, c0, 0 @ Domain ID - mcr p15, 0, r6, c2, c0, 0 @ TTB address - mov r0, r7 @ control register + mcr p15, 0, r1, c2, c0, 0 @ TTB address + mov r0, r6 @ control register b cpu_resume_mmu ENDPROC(cpu_arm926_do_resume) #endif
arch/arm/mm/proc-sa1100.S +10 -11
@@ -168,20 +168,19 @@ ENTRY(cpu_sa1100_set_pte_ext) mov pc, lr .globl cpu_sa1100_suspend_size -.equ cpu_sa1100_suspend_size, 4*4 +.equ cpu_sa1100_suspend_size, 4 * 3 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_sa1100_do_suspend) - stmfd sp!, {r4 - r7, lr} + stmfd sp!, {r4 - r6, lr} mrc p15, 0, r4, c3, c0, 0 @ domain ID - mrc p15, 0, r5, c2, c0, 0 @ translation table base addr - mrc p15, 0, r6, c13, c0, 0 @ PID - mrc p15, 0, r7, c1, c0, 0 @ control reg - stmia r0, {r4 - r7} @ store cp regs - ldmfd sp!, {r4 - r7, pc} + mrc p15, 0, r5, c13, c0, 0 @ PID + mrc p15, 0, r6, c1, c0, 0 @ control reg + stmia r0, {r4 - r6} @ store cp regs + ldmfd sp!, {r4 - r6, pc} ENDPROC(cpu_sa1100_do_suspend) ENTRY(cpu_sa1100_do_resume) - ldmia r0, {r4 - r7} @ load cp regs + ldmia r0, {r4 - r6} @ load cp regs mov ip, #0 mcr p15, 0, ip, c8, c7, 0 @ flush I+D TLBs mcr p15, 0, ip, c7, c7, 0 @ flush I&D cache
@@ -189,9 +188,9 @@ ENTRY(cpu_sa1100_do_resume) mcr p15, 0, ip, c9, c0, 5 @ allow user space to use RB mcr p15, 0, r4, c3, c0, 0 @ domain ID - mcr p15, 0, r5, c2, c0, 0 @ translation table base addr - mcr p15, 0, r6, c13, c0, 0 @ PID - mov r0, r7 @ control register + mcr p15, 0, r1, c2, c0, 0 @ translation table base addr + mcr p15, 0, r5, c13, c0, 0 @ PID + mov r0, r6 @ control register b cpu_resume_mmu ENDPROC(cpu_sa1100_do_resume) #endif
arch/arm/mm/proc-v6.S +16 -15
@@ -128,20 +128,19 @@ ENTRY(cpu_v6_set_pte_ext) /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */ .globl cpu_v6_suspend_size -.equ cpu_v6_suspend_size, 4 * 8 +.equ cpu_v6_suspend_size, 4 * 7 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_v6_do_suspend) - stmfd sp!, {r4 - r11, lr} + stmfd sp!, {r4 - r10, lr} mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID mrc p15, 0, r5, c13, c0, 1 @ Context ID mrc p15, 0, r6, c3, c0, 0 @ Domain ID - mrc p15, 0, r7, c2, c0, 0 @ Translation table base 0 - mrc p15, 0, r8, c2, c0, 1 @ Translation table base 1 - mrc p15, 0, r9, c1, c0, 1 @ auxiliary control register - mrc p15, 0, r10, c1, c0, 2 @ co-processor access control - mrc p15, 0, r11, c1, c0, 0 @ control register - stmia r0, {r4 - r11} - ldmfd sp!, {r4- r11, pc} + mrc p15, 0, r7, c2, c0, 1 @ Translation table base 1 + mrc p15, 0, r8, c1, c0, 1 @ auxiliary control register + mrc p15, 0, r9, c1, c0, 2 @ co-processor access control + mrc p15, 0, r10, c1, c0, 0 @ control register + stmia r0, {r4 - r10} + ldmfd sp!, {r4- r10, pc} ENDPROC(cpu_v6_do_suspend) ENTRY(cpu_v6_do_resume)
@@ -150,17 +149,19 @@ ENTRY(cpu_v6_do_resume) mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache mcr p15, 0, ip, c7, c15, 0 @ clean+invalidate cache mcr p15, 0, ip, c7, c10, 4 @ drain write buffer - ldmia r0, {r4 - r11} + ldmia r0, {r4 - r10} mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID mcr p15, 0, r5, c13, c0, 1 @ Context ID mcr p15, 0, r6, c3, c0, 0 @ Domain ID - mcr p15, 0, r7, c2, c0, 0 @ Translation table base 0 - mcr p15, 0, r8, c2, c0, 1 @ Translation table base 1 - mcr p15, 0, r9, c1, c0, 1 @ auxiliary control register - mcr p15, 0, r10, c1, c0, 2 @ co-processor access control + ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) + ALT_UP(orr r1, r1, #TTB_FLAGS_UP) + mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0 + mcr p15, 0, r7, c2, c0, 1 @ Translation table base 1 + mcr p15, 0, r8, c1, c0, 1 @ auxiliary control register + mcr p15, 0, r9, c1, c0, 2 @ co-processor access control mcr p15, 0, ip, c2, c0, 2 @ TTB control register mcr p15, 0, ip, c7, c5, 4 @ ISB - mov r0, r11 @ control register + mov r0, r10 @ control register b cpu_resume_mmu ENDPROC(cpu_v6_do_resume) #endif
arch/arm/mm/proc-v7.S +17 -16
@@ -217,22 +217,21 @@ ENDPROC(cpu_v7_set_pte_ext) /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */ .globl cpu_v7_suspend_size -.equ cpu_v7_suspend_size, 4 * 9 +.equ cpu_v7_suspend_size, 4 * 8 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_v7_do_suspend) - stmfd sp!, {r4 - r11, lr} + stmfd sp!, {r4 - r10, lr} mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID mrc p15, 0, r5, c13, c0, 1 @ Context ID mrc p15, 0, r6, c13, c0, 3 @ User r/o thread ID stmia r0!, {r4 - r6} mrc p15, 0, r6, c3, c0, 0 @ Domain ID - mrc p15, 0, r7, c2, c0, 0 @ TTB 0 - mrc p15, 0, r8, c2, c0, 1 @ TTB 1 - mrc p15, 0, r9, c1, c0, 0 @ Control register - mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register - mrc p15, 0, r11, c1, c0, 2 @ Co-processor access control - stmia r0, {r6 - r11} - ldmfd sp!, {r4 - r11, pc} + mrc p15, 0, r7, c2, c0, 1 @ TTB 1 + mrc p15, 0, r8, c1, c0, 0 @ Control register + mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register + mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control + stmia r0, {r6 - r10} + ldmfd sp!, {r4 - r10, pc} ENDPROC(cpu_v7_do_suspend) ENTRY(cpu_v7_do_resume)
@@ -243,22 +242,24 @@ ENTRY(cpu_v7_do_resume) mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID mcr p15, 0, r5, c13, c0, 1 @ Context ID mcr p15, 0, r6, c13, c0, 3 @ User r/o thread ID - ldmia r0, {r6 - r11} + ldmia r0, {r6 - r10} mcr p15, 0, r6, c3, c0, 0 @ Domain ID - mcr p15, 0, r7, c2, c0, 0 @ TTB 0 - mcr p15, 0, r8, c2, c0, 1 @ TTB 1 + ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) + ALT_UP(orr r1, r1, #TTB_FLAGS_UP) + mcr p15, 0, r1, c2, c0, 0 @ TTB 0 + mcr p15, 0, r7, c2, c0, 1 @ TTB 1 mcr p15, 0, ip, c2, c0, 2 @ TTB control register mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register - teq r4, r10 @ Is it already set? - mcrne p15, 0, r10, c1, c0, 1 @ No, so write it - mcr p15, 0, r11, c1, c0, 2 @ Co-processor access control + teq r4, r9 @ Is it already set? + mcrne p15, 0, r9, c1, c0, 1 @ No, so write it + mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control ldr r4, =PRRR @ PRRR ldr r5, =NMRR @ NMRR mcr p15, 0, r4, c10, c2, 0 @ write PRRR mcr p15, 0, r5, c10, c2, 1 @ write NMRR isb dsb - mov r0, r9 @ control register + mov r0, r8 @ control register b cpu_resume_mmu ENDPROC(cpu_v7_do_resume) #endif
arch/arm/mm/proc-xsc3.S +11 -11
@@ -406,24 +406,23 @@ ENTRY(cpu_xsc3_set_pte_ext) .align .globl cpu_xsc3_suspend_size -.equ cpu_xsc3_suspend_size, 4 * 7 +.equ cpu_xsc3_suspend_size, 4 * 6 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_xsc3_do_suspend) - stmfd sp!, {r4 - r10, lr} + stmfd sp!, {r4 - r9, lr} mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode mrc p15, 0, r5, c15, c1, 0 @ CP access reg mrc p15, 0, r6, c13, c0, 0 @ PID mrc p15, 0, r7, c3, c0, 0 @ domain ID - mrc p15, 0, r8, c2, c0, 0 @ translation table base addr - mrc p15, 0, r9, c1, c0, 1 @ auxiliary control reg - mrc p15, 0, r10, c1, c0, 0 @ control reg + mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg + mrc p15, 0, r9, c1, c0, 0 @ control reg bic r4, r4, #2 @ clear frequency change bit - stmia r0, {r4 - r10} @ store cp regs - ldmia sp!, {r4 - r10, pc} + stmia r0, {r4 - r9} @ store cp regs + ldmia sp!, {r4 - r9, pc} ENDPROC(cpu_xsc3_do_suspend) ENTRY(cpu_xsc3_do_resume) - ldmia r0, {r4 - r10} @ load cp regs + ldmia r0, {r4 - r9} @ load cp regs mov ip, #0 mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB mcr p15, 0, ip, c7, c10, 4 @ drain write (&fill) buffer
@@ -433,9 +432,10 @@ ENTRY(cpu_xsc3_do_resume) mcr p15, 0, r5, c15, c1, 0 @ CP access reg mcr p15, 0, r6, c13, c0, 0 @ PID mcr p15, 0, r7, c3, c0, 0 @ domain ID - mcr p15, 0, r8, c2, c0, 0 @ translation table base addr - mcr p15, 0, r9, c1, c0, 1 @ auxiliary control reg - mov r0, r10 @ control register + orr r1, r1, #0x18 @ cache the page table in L2 + mcr p15, 0, r1, c2, c0, 0 @ translation table base addr + mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg + mov r0, r9 @ control register b cpu_resume_mmu ENDPROC(cpu_xsc3_do_resume) #endif
arch/arm/mm/proc-xscale.S +10 -11
@@ -520,24 +520,23 @@ ENTRY(cpu_xscale_set_pte_ext) .align .globl cpu_xscale_suspend_size -.equ cpu_xscale_suspend_size, 4 * 7 +.equ cpu_xscale_suspend_size, 4 * 6 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_xscale_do_suspend) - stmfd sp!, {r4 - r10, lr} + stmfd sp!, {r4 - r9, lr} mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode mrc p15, 0, r5, c15, c1, 0 @ CP access reg mrc p15, 0, r6, c13, c0, 0 @ PID mrc p15, 0, r7, c3, c0, 0 @ domain ID - mrc p15, 0, r8, c2, c0, 0 @ translation table base addr - mrc p15, 0, r9, c1, c1, 0 @ auxiliary control reg - mrc p15, 0, r10, c1, c0, 0 @ control reg + mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg + mrc p15, 0, r9, c1, c0, 0 @ control reg bic r4, r4, #2 @ clear frequency change bit - stmia r0, {r4 - r10} @ store cp regs - ldmfd sp!, {r4 - r10, pc} + stmia r0, {r4 - r9} @ store cp regs + ldmfd sp!, {r4 - r9, pc} ENDPROC(cpu_xscale_do_suspend) ENTRY(cpu_xscale_do_resume) - ldmia r0, {r4 - r10} @ load cp regs + ldmia r0, {r4 - r9} @ load cp regs mov ip, #0 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB
@@ -545,9 +544,9 @@ ENTRY(cpu_xscale_do_resume) mcr p15, 0, r5, c15, c1, 0 @ CP access reg mcr p15, 0, r6, c13, c0, 0 @ PID mcr p15, 0, r7, c3, c0, 0 @ domain ID - mcr p15, 0, r8, c2, c0, 0 @ translation table base addr - mcr p15, 0, r9, c1, c1, 0 @ auxiliary control reg - mov r0, r10 @ control register + mcr p15, 0, r1, c2, c0, 0 @ translation table base addr + mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg + mov r0, r9 @ control register b cpu_resume_mmu ENDPROC(cpu_xscale_do_resume) #endif
Signature · 1 line
1.7.4.4
PATCH 4/7 ARM: pm: no need to save/restore context ID register
In reply to Russell King - ARM LinuxThere is no need to save and restore the context ID register on ARMv6 and ARMv7 with a temporary page table as we write the context ID register when we switch back to the real page tables for the thread.
Moreover, the temporary page tables do not contain any non-global mappings, so the context ID value should not be used. To be safe, initialize the register to a reserved context ID value.
--- arch/arm/mm/proc-v6.S | 33 ++++++++++++++++----------------- arch/arm/mm/proc-v7.S | 13 ++++++------- 2 files changed, 22 insertions(+), 24 deletions(-)
arch/arm/mm/proc-v6.S +16 -17
@@ -128,19 +128,18 @@ ENTRY(cpu_v6_set_pte_ext) /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */ .globl cpu_v6_suspend_size -.equ cpu_v6_suspend_size, 4 * 7 +.equ cpu_v6_suspend_size, 4 * 6 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_v6_do_suspend) - stmfd sp!, {r4 - r10, lr} + stmfd sp!, {r4 - r9, lr} mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID - mrc p15, 0, r5, c13, c0, 1 @ Context ID - mrc p15, 0, r6, c3, c0, 0 @ Domain ID - mrc p15, 0, r7, c2, c0, 1 @ Translation table base 1 - mrc p15, 0, r8, c1, c0, 1 @ auxiliary control register - mrc p15, 0, r9, c1, c0, 2 @ co-processor access control - mrc p15, 0, r10, c1, c0, 0 @ control register - stmia r0, {r4 - r10} - ldmfd sp!, {r4- r10, pc} + mrc p15, 0, r5, c3, c0, 0 @ Domain ID + mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1 + mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register + mrc p15, 0, r8, c1, c0, 2 @ co-processor access control + mrc p15, 0, r9, c1, c0, 0 @ control register + stmia r0, {r4 - r9} + ldmfd sp!, {r4- r9, pc} ENDPROC(cpu_v6_do_suspend) ENTRY(cpu_v6_do_resume)
@@ -149,19 +148,19 @@ ENTRY(cpu_v6_do_resume) mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache mcr p15, 0, ip, c7, c15, 0 @ clean+invalidate cache mcr p15, 0, ip, c7, c10, 4 @ drain write buffer - ldmia r0, {r4 - r10} + mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID + ldmia r0, {r4 - r9} mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID - mcr p15, 0, r5, c13, c0, 1 @ Context ID - mcr p15, 0, r6, c3, c0, 0 @ Domain ID + mcr p15, 0, r5, c3, c0, 0 @ Domain ID ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) ALT_UP(orr r1, r1, #TTB_FLAGS_UP) mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0 - mcr p15, 0, r7, c2, c0, 1 @ Translation table base 1 - mcr p15, 0, r8, c1, c0, 1 @ auxiliary control register - mcr p15, 0, r9, c1, c0, 2 @ co-processor access control + mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1 + mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register + mcr p15, 0, r8, c1, c0, 2 @ co-processor access control mcr p15, 0, ip, c2, c0, 2 @ TTB control register mcr p15, 0, ip, c7, c5, 4 @ ISB - mov r0, r10 @ control register + mov r0, r9 @ control register b cpu_resume_mmu ENDPROC(cpu_v6_do_resume) #endif
arch/arm/mm/proc-v7.S +6 -7
@@ -217,14 +217,13 @@ ENDPROC(cpu_v7_set_pte_ext) /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */ .globl cpu_v7_suspend_size -.equ cpu_v7_suspend_size, 4 * 8 +.equ cpu_v7_suspend_size, 4 * 7 #ifdef CONFIG_PM_SLEEP ENTRY(cpu_v7_do_suspend) stmfd sp!, {r4 - r10, lr} mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID - mrc p15, 0, r5, c13, c0, 1 @ Context ID - mrc p15, 0, r6, c13, c0, 3 @ User r/o thread ID - stmia r0!, {r4 - r6} + mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID + stmia r0!, {r4 - r5} mrc p15, 0, r6, c3, c0, 0 @ Domain ID mrc p15, 0, r7, c2, c0, 1 @ TTB 1 mrc p15, 0, r8, c1, c0, 0 @ Control register
@@ -238,10 +237,10 @@ ENTRY(cpu_v7_do_resume) mov ip, #0 mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache - ldmia r0!, {r4 - r6} + mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID + ldmia r0!, {r4 - r5} mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID - mcr p15, 0, r5, c13, c0, 1 @ Context ID - mcr p15, 0, r6, c13, c0, 3 @ User r/o thread ID + mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID ldmia r0, {r6 - r10} mcr p15, 0, r6, c3, c0, 0 @ Domain ID ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
Signature · 1 line
1.7.4.4
PATCH 5/7 ARM: pm: get rid of cpu_resume_turn_mmu_on
In reply to Russell King - ARM LinuxWe don't require cpu_resume_turn_mmu_on as we can combine the ldr instruction with the following code provided we ensure that cpu_resume_mmu is aligned for older CPUs. Note that we also align to a 32-byte boundary to ensure that the code can't cross a section boundary.
--- arch/arm/kernel/sleep.S | 8 ++------ arch/arm/kernel/suspend.c | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-)
arch/arm/kernel/sleep.S +2 -6
@@ -72,19 +72,15 @@ ENDPROC(cpu_suspend_abort) /* * r0 = control register value */ + .align 5 ENTRY(cpu_resume_mmu) ldr r3, =cpu_resume_after_mmu - b cpu_resume_turn_mmu_on -ENDPROC(cpu_resume_mmu) - .ltorg - .align 5 -ENTRY(cpu_resume_turn_mmu_on) mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc mrc p15, 0, r0, c0, c0, 0 @ read id reg mov r0, r0 mov r0, r0 mov pc, r3 @ jump to virtual address -ENDPROC(cpu_resume_turn_mmu_on) +ENDPROC(cpu_resume_mmu) cpu_resume_after_mmu: bl cpu_init @ restore the und/abt/irq banked regs mov r0, #0 @ return zero on success
arch/arm/kernel/suspend.c +2 -2
@@ -9,7 +9,7 @@static pgd_t *suspend_pgd;extern int __cpu_suspend (int ,long ,unsigned long ,int (*)(unsigned long )); -extern void cpu_resume_turn_mmu_on (void ); +extern void cpu_resume_mmu (void );/* * Hide the first two arguments to __cpu_suspend - these are an implementation
@@ -43,7 +43,7 @@ static int __init cpu_suspend_init(void) { suspend_pgd =pgd_alloc (&init_mm);if (suspend_pgd) { -unsigned long addr =virt_to_phys (cpu_resume_turn_mmu_on); +unsigned long addr =virt_to_phys (cpu_resume_mmu);identity_mapping_add (suspend_pgd, addr, addr +SECTION_SIZE ); }return suspend_pgd ?0 : -ENOMEM ;
Signature · 1 line
1.7.4.4
PATCH 6/7 ARM: pm: convert some assembly to C
In reply to Russell King - ARM LinuxConvert some of the sleep.S guts to C code, which makes it easier to use our macros and to add L2 cache handling. We provide a helper function, __cpu_suspend_save(), which deals with saving the common state, setting up for resume, and flushing caches.
The remainder left as assembly code is the saving of the CPU general purpose registers, and allocating space on the stack to save the CPU specific registers and resume state.
--- arch/arm/include/asm/proc-fns.h | 8 ++++++ arch/arm/kernel/sleep.S | 53 ++++++++++++-------------------------- arch/arm/kernel/suspend.c | 24 +++++++++++++++-- 3 files changed, 46 insertions(+), 39 deletions(-)
arch/arm/include/asm/proc-fns.h +8 -0
@@ -81,6 +81,10 @@ extern void cpu_dcache_clean_area(void *, int);extern void cpu_do_switch_mm (unsigned long pgd_phys,struct mm_struct *mm);extern void cpu_set_pte_ext (pte_t *ptep,pte_t pte,unsigned int ext);extern void cpu_reset (unsigned long addr) __attribute__((noreturn)); + +/* These three are private to arch/arm/kernel/suspend.c */ +extern void cpu_do_suspend (void *); +extern void cpu_do_resume (void *);#else #define cpu_proc_init processor._proc_init#define cpu_proc_fin processor._proc_fin
@@ -89,6 +93,10 @@ extern void cpu_reset(unsigned long addr) __attribute__((noreturn));#define cpu_dcache_clean_area processor.dcache_clean_area#define cpu_set_pte_ext processor.set_pte_ext#define cpu_do_switch_mm processor.switch_mm + +/* These three are private to arch/arm/kernel/suspend.c */ +#define cpu_do_suspend processor.do_suspend +#define cpu_do_resume processor.do_resume#endif extern void cpu_resume (void );
arch/arm/kernel/sleep.S +17 -36
71 lines not on this page · raw message
arch/arm/kernel/suspend.c +21 -3
@@ -8,10 +8,29 @@static pgd_t *suspend_pgd; -extern int __cpu_suspend (int ,long ,unsigned long ,int (*)(unsigned long )); +extern int __cpu_suspend (unsigned long ,int (*)(unsigned long ));extern void cpu_resume_mmu (void );/* +* This is called by __cpu_suspend() to save the state, and do whatever +* flushing is required to ensure that when the CPU goes to sleep we have +* the necessary data available when the caches are not searched. +*/ +void __cpu_suspend_save (u32 *ptr,u32 ptrsz,u32 sp,u32 *save_ptr) +{ + *save_ptr =virt_to_phys (ptr); + +/* This must correspond to the LDM in cpu_resume() assembly */ + *ptr++ =virt_to_phys (suspend_pgd); + *ptr++ = sp; + *ptr++ =virt_to_phys (cpu_do_resume); + +cpu_do_suspend (ptr); + +flush_cache_all (); +} + +/* * Hide the first two arguments to __cpu_suspend - these are an implementation * detail which platform code shouldn't have to know about. */
@@ -29,8 +48,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))* resume (indicated by a zero return code), we need to switch * back to the correct page tables. */ - ret =__cpu_suspend (virt_to_phys (suspend_pgd), -PHYS_OFFSET -PAGE_OFFSET , arg, fn); + ret =__cpu_suspend (arg, fn);if (ret ==0 ) {cpu_switch_mm (mm->pgd, mm);local_flush_tlb_all ();
Signature · 1 line
1.7.4.4
PATCH 7/7 ARM: pm: add L2 cache cleaning for suspend
In reply to Russell King - ARM LinuxWe need to ensure that state is pushed out from the L2 cache when suspending so that the resume paths can access their data before the MMU and caches have been re-initialized. Add the necessary calls to __cpu_suspend_save().
--- arch/arm/kernel/suspend.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
arch/arm/kernel/suspend.c +3 -0
@@ -28,6 +28,9 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)cpu_do_suspend (ptr);flush_cache_all (); +outer_clean_range (*save_ptr, *save_ptr + ptrsz); +outer_clean_range (virt_to_phys (save_ptr), +virt_to_phys (save_ptr) +sizeof (*save_ptr)); }/*
Signature · 1 line
1.7.4.4
cover Add L2 cache cleaning to generic CPU suspend
In reply to Russell King - ARM LinuxQuoted 5 lines · Russell King - ARM Linux
This is a re-post of the previous patch series, but with an additional TLB flush to ensure that hte global TLB entry in the page tables is flushed out. This is a flush of all TLB entries, but it could probably be more targetted if we need to.
Here is the diff on suspend.c between last post and this series. With the outer_clean_range() calls added back, the series works fine on imx6q, otherwise it hangs on resume.
arch/arm/kernel/suspend.c +3 -4
@@ -28,9 +28,6 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)cpu_do_suspend (ptr);flush_cache_all (); -outer_clean_range (*save_ptr, *save_ptr + ptrsz); -outer_clean_range (virt_to_phys (save_ptr), -virt_to_phys (save_ptr) +sizeof (*save_ptr)); }/*
@@ -52,8 +49,10 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))* back to the correct page tables. */ ret =__cpu_suspend (arg, fn); -if (ret ==0 ) +if (ret ==0 ) {cpu_switch_mm (mm->pgd, mm); +local_flush_tlb_all (); + }return ret; }
Signature · 2 lines
Regards, Shawn
cover Add L2 cache cleaning to generic CPU suspend
Quoted 10 lines · Shawn Guo
Quoted 5 lines · Russell King - ARM Linux
This is a re-post of the previous patch series, but with an additional TLB flush to ensure that hte global TLB entry in the page tables is flushed out. This is a flush of all TLB entries, but it could probably be more targetted if we need to.
Here is the diff on
suspend.cbetween last post and this series. With theouter_clean_range()calls added back, the series works fine on imx6q, otherwise it hangs on resume.
You seem to be missing patch 7 from the second series.
cover Add L2 cache cleaning to generic CPU suspend
Quoted 8 lines · Russell King - ARM Linux
Quoted 7 lines · Shawn Guo
Quoted 5 lines · Russell King - ARM Linux
This is a re-post of the previous patch series, but with an additional TLB flush to ensure that hte global TLB entry in the page tables is flushed out. This is a flush of all TLB entries, but it could probably be more targetted if we need to.
Quoted 6 lines
Quoted 3 lines
Here is the diff on
suspend.cbetween last post and this series. With theouter_clean_range()calls added back, the series works fine on imx6q, otherwise it hangs on resume.You seem to be missing patch 7 from the second series.
Oops, indeed. So on imx6q for all the series:
Signature · 2 lines
Regards, Shawn
cover Add L2 cache cleaning to generic CPU suspend
In reply to Russell King - ARM LinuxQuoted 5 lines · Russell King - ARM Linux
This is a re-post of the previous patch series, but with an additional TLB flush to ensure that hte global TLB entry in the page tables is flushed out. This is a flush of all TLB entries, but it could probably be more targetted if we need to.
I have tried this seven patches + already merged 4 patches against RC4 and OMAP4 PM patches and they continue to work as expected.
I guess once Lorenzo confirms that his userspace segmentation faults are fixed with the TLB flush updates, the series is good for the merge.
Regards
Santosh
cover Add L2 cache cleaning to generic CPU suspend
In reply to Russell King - ARM LinuxQuoted 19 lines · Russell King - ARM Linux
This is a re-post of the previous patch series, but with an additional TLB flush to ensure that hte global TLB entry in the page tables is flushed out. This is a flush of all TLB entries, but it could probably be more targetted if we need to.
Original cover mail follows:
Some systems (such as OMAP) preserve the L2 cache across a suspend/ resume cycle. This means they do not perform L2 cache maintanence in their suspend finisher function.
However, the side effect is that the saved CPU state is not readable by the resume code because it is sitting in the L2 cache.
This patch series adds L2 cache cleaning to the generic CPU suspend/ resume support code, making it possible to use this on systems with L2 cache enabled without having to clean/invalidate the entire L2 cache.
Quoted 10 lines
We also add a separate page table, allocated at boot time, for the resume process to use so we don't have to fiddle about with tweaking entries in the current processes page table. Moreover, the current processes page table may be in use by another CPU in the system if these paths are used from cpuidle or hotplug, so changing the page table is technically unsound.
Overall, this makes it possible for OMAP4 systems to use this code.
Thanks Russell for this.
As expected, it does fix the issue. Tested on ARM internal platforms and Origen with both suspend and cpuidle. So, on the whole series: