ARM: suspend: fix CPU suspend code for !CONFIG_MMU configurations
The ARM CPU suspend code can be selected even for a !CONFIG_MMU configuration. The resulting kernel will not compile and, even if it did, would access undefined co-processor registers when executing. This patch fixes the v6 and v7 CPU suspend code for the nommu case. Signed-off-by: Will Deacon <will.deacon@arm.com> Tested-by: Jonathan Austin <jonathan.austin@arm.com> CC: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> (commit_signer:1/3=33%) CC: Santosh Shilimkar <santosh.shilimkar@ti.com> (commit_signer:1/3=33%) CC: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
This commit is contained in:
Родитель
c4a1f032ed
Коммит
aa1aadc330
|
@ -10,6 +10,42 @@
|
||||||
extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
|
extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
|
||||||
extern void cpu_resume_mmu(void);
|
extern void cpu_resume_mmu(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
|
/*
|
||||||
|
* Hide the first two arguments to __cpu_suspend - these are an implementation
|
||||||
|
* detail which platform code shouldn't have to know about.
|
||||||
|
*/
|
||||||
|
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
||||||
|
{
|
||||||
|
struct mm_struct *mm = current->active_mm;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!idmap_pgd)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
ret = __cpu_suspend(arg, fn);
|
||||||
|
if (ret == 0) {
|
||||||
|
cpu_switch_mm(mm->pgd, mm);
|
||||||
|
local_flush_bp_all();
|
||||||
|
local_flush_tlb_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
||||||
|
{
|
||||||
|
return __cpu_suspend(arg, fn);
|
||||||
|
}
|
||||||
|
#define idmap_pgd NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is called by __cpu_suspend() to save the state, and do whatever
|
* 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
|
* flushing is required to ensure that when the CPU goes to sleep we have
|
||||||
|
@ -46,31 +82,3 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
|
||||||
outer_clean_range(virt_to_phys(save_ptr),
|
outer_clean_range(virt_to_phys(save_ptr),
|
||||||
virt_to_phys(save_ptr) + sizeof(*save_ptr));
|
virt_to_phys(save_ptr) + sizeof(*save_ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Hide the first two arguments to __cpu_suspend - these are an implementation
|
|
||||||
* detail which platform code shouldn't have to know about.
|
|
||||||
*/
|
|
||||||
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
|
||||||
{
|
|
||||||
struct mm_struct *mm = current->active_mm;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!idmap_pgd)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
ret = __cpu_suspend(arg, fn);
|
|
||||||
if (ret == 0) {
|
|
||||||
cpu_switch_mm(mm->pgd, mm);
|
|
||||||
local_flush_bp_all();
|
|
||||||
local_flush_tlb_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
|
@ -140,8 +140,10 @@ ENTRY(cpu_v6_set_pte_ext)
|
||||||
ENTRY(cpu_v6_do_suspend)
|
ENTRY(cpu_v6_do_suspend)
|
||||||
stmfd sp!, {r4 - r9, lr}
|
stmfd sp!, {r4 - r9, lr}
|
||||||
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
|
mrc p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||||
mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1
|
mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1
|
||||||
|
#endif
|
||||||
mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register
|
mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register
|
||||||
mrc p15, 0, r8, c1, c0, 2 @ co-processor access control
|
mrc p15, 0, r8, c1, c0, 2 @ co-processor access control
|
||||||
mrc p15, 0, r9, c1, c0, 0 @ control register
|
mrc p15, 0, r9, c1, c0, 0 @ control register
|
||||||
|
@ -158,14 +160,16 @@ ENTRY(cpu_v6_do_resume)
|
||||||
mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
|
mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
|
||||||
ldmia r0, {r4 - r9}
|
ldmia r0, {r4 - r9}
|
||||||
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
|
mcr p15, 0, r5, c3, c0, 0 @ Domain ID
|
||||||
ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
|
ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
|
||||||
ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
|
ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
|
||||||
mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0
|
mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0
|
||||||
mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1
|
mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1
|
||||||
|
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
|
||||||
|
#endif
|
||||||
mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register
|
mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register
|
||||||
mcr p15, 0, r8, c1, c0, 2 @ co-processor access control
|
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
|
mcr p15, 0, ip, c7, c5, 4 @ ISB
|
||||||
mov r0, r9 @ control register
|
mov r0, r9 @ control register
|
||||||
b cpu_resume_mmu
|
b cpu_resume_mmu
|
||||||
|
|
|
@ -98,9 +98,11 @@ ENTRY(cpu_v7_do_suspend)
|
||||||
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||||
mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID
|
mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID
|
||||||
stmia r0!, {r4 - r5}
|
stmia r0!, {r4 - r5}
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
|
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
|
||||||
mrc p15, 0, r7, c2, c0, 1 @ TTB 1
|
mrc p15, 0, r7, c2, c0, 1 @ TTB 1
|
||||||
mrc p15, 0, r11, c2, c0, 2 @ TTB control register
|
mrc p15, 0, r11, c2, c0, 2 @ TTB control register
|
||||||
|
#endif
|
||||||
mrc p15, 0, r8, c1, c0, 0 @ Control register
|
mrc p15, 0, r8, c1, c0, 0 @ Control register
|
||||||
mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register
|
mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register
|
||||||
mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
|
mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
|
||||||
|
@ -110,13 +112,14 @@ ENDPROC(cpu_v7_do_suspend)
|
||||||
|
|
||||||
ENTRY(cpu_v7_do_resume)
|
ENTRY(cpu_v7_do_resume)
|
||||||
mov ip, #0
|
mov ip, #0
|
||||||
mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs
|
|
||||||
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
|
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
|
||||||
mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
|
mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID
|
||||||
ldmia r0!, {r4 - r5}
|
ldmia r0!, {r4 - r5}
|
||||||
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||||
mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID
|
mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID
|
||||||
ldmia r0, {r6 - r11}
|
ldmia r0, {r6 - r11}
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
|
mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs
|
||||||
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
|
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
|
||||||
#ifndef CONFIG_ARM_LPAE
|
#ifndef CONFIG_ARM_LPAE
|
||||||
ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
|
ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
|
||||||
|
@ -125,14 +128,15 @@ ENTRY(cpu_v7_do_resume)
|
||||||
mcr p15, 0, r1, c2, c0, 0 @ TTB 0
|
mcr p15, 0, r1, c2, c0, 0 @ TTB 0
|
||||||
mcr p15, 0, r7, c2, c0, 1 @ TTB 1
|
mcr p15, 0, r7, c2, c0, 1 @ TTB 1
|
||||||
mcr p15, 0, r11, c2, c0, 2 @ TTB control register
|
mcr p15, 0, r11, c2, c0, 2 @ TTB control register
|
||||||
mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register
|
|
||||||
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 r4, =PRRR @ PRRR
|
||||||
ldr r5, =NMRR @ NMRR
|
ldr r5, =NMRR @ NMRR
|
||||||
mcr p15, 0, r4, c10, c2, 0 @ write PRRR
|
mcr p15, 0, r4, c10, c2, 0 @ write PRRR
|
||||||
mcr p15, 0, r5, c10, c2, 1 @ write NMRR
|
mcr p15, 0, r5, c10, c2, 1 @ write NMRR
|
||||||
|
#endif /* CONFIG_MMU */
|
||||||
|
mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register
|
||||||
|
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
|
||||||
isb
|
isb
|
||||||
dsb
|
dsb
|
||||||
mov r0, r8 @ control register
|
mov r0, r8 @ control register
|
||||||
|
|
Загрузка…
Ссылка в новой задаче