diff options
author | Will Deacon <will.deacon@arm.com> | 2012-02-23 08:51:38 -0500 |
---|---|---|
committer | Jonathan Austin <jonathan.austin@arm.com> | 2013-06-07 12:02:44 -0400 |
commit | aa1aadc3305c4917c39f0291613a5ec81dd4c73b (patch) | |
tree | 6cb4cdb683aa041bc640b27df85eb9fa6663eab1 /arch | |
parent | c4a1f032ed35d744e3d74b8aebe8d85f29aecd88 (diff) |
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/kernel/suspend.c | 64 | ||||
-rw-r--r-- | arch/arm/mm/proc-v6.S | 6 | ||||
-rw-r--r-- | arch/arm/mm/proc-v7.S | 14 |
3 files changed, 50 insertions, 34 deletions
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index c59c97ea8268..38a50676213b 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c | |||
@@ -10,6 +10,42 @@ | |||
10 | extern int __cpu_suspend(unsigned long, int (*)(unsigned long)); | 10 | extern int __cpu_suspend(unsigned long, int (*)(unsigned long)); |
11 | extern void cpu_resume_mmu(void); | 11 | extern void cpu_resume_mmu(void); |
12 | 12 | ||
13 | #ifdef CONFIG_MMU | ||
14 | /* | ||
15 | * Hide the first two arguments to __cpu_suspend - these are an implementation | ||
16 | * detail which platform code shouldn't have to know about. | ||
17 | */ | ||
18 | int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) | ||
19 | { | ||
20 | struct mm_struct *mm = current->active_mm; | ||
21 | int ret; | ||
22 | |||
23 | if (!idmap_pgd) | ||
24 | return -EINVAL; | ||
25 | |||
26 | /* | ||
27 | * Provide a temporary page table with an identity mapping for | ||
28 | * the MMU-enable code, required for resuming. On successful | ||
29 | * resume (indicated by a zero return code), we need to switch | ||
30 | * back to the correct page tables. | ||
31 | */ | ||
32 | ret = __cpu_suspend(arg, fn); | ||
33 | if (ret == 0) { | ||
34 | cpu_switch_mm(mm->pgd, mm); | ||
35 | local_flush_bp_all(); | ||
36 | local_flush_tlb_all(); | ||
37 | } | ||
38 | |||
39 | return ret; | ||
40 | } | ||
41 | #else | ||
42 | int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) | ||
43 | { | ||
44 | return __cpu_suspend(arg, fn); | ||
45 | } | ||
46 | #define idmap_pgd NULL | ||
47 | #endif | ||
48 | |||
13 | /* | 49 | /* |
14 | * This is called by __cpu_suspend() to save the state, and do whatever | 50 | * This is called by __cpu_suspend() to save the state, and do whatever |
15 | * flushing is required to ensure that when the CPU goes to sleep we have | 51 | * 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) | |||
46 | outer_clean_range(virt_to_phys(save_ptr), | 82 | outer_clean_range(virt_to_phys(save_ptr), |
47 | virt_to_phys(save_ptr) + sizeof(*save_ptr)); | 83 | virt_to_phys(save_ptr) + sizeof(*save_ptr)); |
48 | } | 84 | } |
49 | |||
50 | /* | ||
51 | * Hide the first two arguments to __cpu_suspend - these are an implementation | ||
52 | * detail which platform code shouldn't have to know about. | ||
53 | */ | ||
54 | int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) | ||
55 | { | ||
56 | struct mm_struct *mm = current->active_mm; | ||
57 | int ret; | ||
58 | |||
59 | if (!idmap_pgd) | ||
60 | return -EINVAL; | ||
61 | |||
62 | /* | ||
63 | * Provide a temporary page table with an identity mapping for | ||
64 | * the MMU-enable code, required for resuming. On successful | ||
65 | * resume (indicated by a zero return code), we need to switch | ||
66 | * back to the correct page tables. | ||
67 | */ | ||
68 | ret = __cpu_suspend(arg, fn); | ||
69 | if (ret == 0) { | ||
70 | cpu_switch_mm(mm->pgd, mm); | ||
71 | local_flush_bp_all(); | ||
72 | local_flush_tlb_all(); | ||
73 | } | ||
74 | |||
75 | return ret; | ||
76 | } | ||
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 919405e20b80..2d1ef87328a1 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S | |||
@@ -140,8 +140,10 @@ ENTRY(cpu_v6_set_pte_ext) | |||
140 | ENTRY(cpu_v6_do_suspend) | 140 | ENTRY(cpu_v6_do_suspend) |
141 | stmfd sp!, {r4 - r9, lr} | 141 | stmfd sp!, {r4 - r9, lr} |
142 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID | 142 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID |
143 | #ifdef CONFIG_MMU | ||
143 | mrc p15, 0, r5, c3, c0, 0 @ Domain ID | 144 | mrc p15, 0, r5, c3, c0, 0 @ Domain ID |
144 | mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1 | 145 | mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1 |
146 | #endif | ||
145 | mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register | 147 | mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register |
146 | mrc p15, 0, r8, c1, c0, 2 @ co-processor access control | 148 | mrc p15, 0, r8, c1, c0, 2 @ co-processor access control |
147 | mrc p15, 0, r9, c1, c0, 0 @ control register | 149 | mrc p15, 0, r9, c1, c0, 0 @ control register |
@@ -158,14 +160,16 @@ ENTRY(cpu_v6_do_resume) | |||
158 | mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID | 160 | mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID |
159 | ldmia r0, {r4 - r9} | 161 | ldmia r0, {r4 - r9} |
160 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID | 162 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID |
163 | #ifdef CONFIG_MMU | ||
161 | mcr p15, 0, r5, c3, c0, 0 @ Domain ID | 164 | mcr p15, 0, r5, c3, c0, 0 @ Domain ID |
162 | ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) | 165 | ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) |
163 | ALT_UP(orr r1, r1, #TTB_FLAGS_UP) | 166 | ALT_UP(orr r1, r1, #TTB_FLAGS_UP) |
164 | mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0 | 167 | mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0 |
165 | mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1 | 168 | mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1 |
169 | mcr p15, 0, ip, c2, c0, 2 @ TTB control register | ||
170 | #endif | ||
166 | mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register | 171 | mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register |
167 | mcr p15, 0, r8, c1, c0, 2 @ co-processor access control | 172 | mcr p15, 0, r8, c1, c0, 2 @ co-processor access control |
168 | mcr p15, 0, ip, c2, c0, 2 @ TTB control register | ||
169 | mcr p15, 0, ip, c7, c5, 4 @ ISB | 173 | mcr p15, 0, ip, c7, c5, 4 @ ISB |
170 | mov r0, r9 @ control register | 174 | mov r0, r9 @ control register |
171 | b cpu_resume_mmu | 175 | b cpu_resume_mmu |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 2c73a7301ff7..a851e3433afe 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -98,9 +98,11 @@ ENTRY(cpu_v7_do_suspend) | |||
98 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID | 98 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID |
99 | mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID | 99 | mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID |
100 | stmia r0!, {r4 - r5} | 100 | stmia r0!, {r4 - r5} |
101 | #ifdef CONFIG_MMU | ||
101 | mrc p15, 0, r6, c3, c0, 0 @ Domain ID | 102 | mrc p15, 0, r6, c3, c0, 0 @ Domain ID |
102 | mrc p15, 0, r7, c2, c0, 1 @ TTB 1 | 103 | mrc p15, 0, r7, c2, c0, 1 @ TTB 1 |
103 | mrc p15, 0, r11, c2, c0, 2 @ TTB control register | 104 | mrc p15, 0, r11, c2, c0, 2 @ TTB control register |
105 | #endif | ||
104 | mrc p15, 0, r8, c1, c0, 0 @ Control register | 106 | mrc p15, 0, r8, c1, c0, 0 @ Control register |
105 | mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register | 107 | mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register |
106 | mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control | 108 | mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control |
@@ -110,13 +112,14 @@ ENDPROC(cpu_v7_do_suspend) | |||
110 | 112 | ||
111 | ENTRY(cpu_v7_do_resume) | 113 | ENTRY(cpu_v7_do_resume) |
112 | mov ip, #0 | 114 | mov ip, #0 |
113 | mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs | ||
114 | mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache | 115 | mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache |
115 | mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID | 116 | mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID |
116 | ldmia r0!, {r4 - r5} | 117 | ldmia r0!, {r4 - r5} |
117 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID | 118 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID |
118 | mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID | 119 | mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID |
119 | ldmia r0, {r6 - r11} | 120 | ldmia r0, {r6 - r11} |
121 | #ifdef CONFIG_MMU | ||
122 | mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs | ||
120 | mcr p15, 0, r6, c3, c0, 0 @ Domain ID | 123 | mcr p15, 0, r6, c3, c0, 0 @ Domain ID |
121 | #ifndef CONFIG_ARM_LPAE | 124 | #ifndef CONFIG_ARM_LPAE |
122 | ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) | 125 | ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) |
@@ -125,14 +128,15 @@ ENTRY(cpu_v7_do_resume) | |||
125 | mcr p15, 0, r1, c2, c0, 0 @ TTB 0 | 128 | mcr p15, 0, r1, c2, c0, 0 @ TTB 0 |
126 | mcr p15, 0, r7, c2, c0, 1 @ TTB 1 | 129 | mcr p15, 0, r7, c2, c0, 1 @ TTB 1 |
127 | mcr p15, 0, r11, c2, c0, 2 @ TTB control register | 130 | mcr p15, 0, r11, c2, c0, 2 @ TTB control register |
128 | mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register | ||
129 | teq r4, r9 @ Is it already set? | ||
130 | mcrne p15, 0, r9, c1, c0, 1 @ No, so write it | ||
131 | mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control | ||
132 | ldr r4, =PRRR @ PRRR | 131 | ldr r4, =PRRR @ PRRR |
133 | ldr r5, =NMRR @ NMRR | 132 | ldr r5, =NMRR @ NMRR |
134 | mcr p15, 0, r4, c10, c2, 0 @ write PRRR | 133 | mcr p15, 0, r4, c10, c2, 0 @ write PRRR |
135 | mcr p15, 0, r5, c10, c2, 1 @ write NMRR | 134 | mcr p15, 0, r5, c10, c2, 1 @ write NMRR |
135 | #endif /* CONFIG_MMU */ | ||
136 | mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register | ||
137 | teq r4, r9 @ Is it already set? | ||
138 | mcrne p15, 0, r9, c1, c0, 1 @ No, so write it | ||
139 | mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control | ||
136 | isb | 140 | isb |
137 | dsb | 141 | dsb |
138 | mov r0, r8 @ control register | 142 | mov r0, r8 @ control register |