diff options
-rw-r--r-- | arch/arm/common/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/common/mcpm_head.S | 41 | ||||
-rw-r--r-- | arch/arm/kernel/asm-offsets.c | 1 |
3 files changed, 38 insertions, 6 deletions
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index b070671033ae..9ec273188ccb 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile | |||
@@ -11,4 +11,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o | |||
11 | obj-$(CONFIG_SHARP_SCOOP) += scoop.o | 11 | obj-$(CONFIG_SHARP_SCOOP) += scoop.o |
12 | obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o | 12 | obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o |
13 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o | 13 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o |
14 | obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o | 14 | obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o vlock.o |
diff --git a/arch/arm/common/mcpm_head.S b/arch/arm/common/mcpm_head.S index 7d729bd72674..8178705c4b24 100644 --- a/arch/arm/common/mcpm_head.S +++ b/arch/arm/common/mcpm_head.S | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/linkage.h> | 16 | #include <linux/linkage.h> |
17 | #include <asm/mcpm.h> | 17 | #include <asm/mcpm.h> |
18 | 18 | ||
19 | #include "vlock.h" | ||
20 | |||
19 | .if MCPM_SYNC_CLUSTER_CPUS | 21 | .if MCPM_SYNC_CLUSTER_CPUS |
20 | .error "cpus must be the first member of struct mcpm_sync_struct" | 22 | .error "cpus must be the first member of struct mcpm_sync_struct" |
21 | .endif | 23 | .endif |
@@ -69,10 +71,11 @@ ENTRY(mcpm_entry_point) | |||
69 | * position independent way. | 71 | * position independent way. |
70 | */ | 72 | */ |
71 | adr r5, 3f | 73 | adr r5, 3f |
72 | ldmia r5, {r6, r7, r8} | 74 | ldmia r5, {r6, r7, r8, r11} |
73 | add r6, r5, r6 @ r6 = mcpm_entry_vectors | 75 | add r6, r5, r6 @ r6 = mcpm_entry_vectors |
74 | ldr r7, [r5, r7] @ r7 = mcpm_power_up_setup_phys | 76 | ldr r7, [r5, r7] @ r7 = mcpm_power_up_setup_phys |
75 | add r8, r5, r8 @ r8 = mcpm_sync | 77 | add r8, r5, r8 @ r8 = mcpm_sync |
78 | add r11, r5, r11 @ r11 = first_man_locks | ||
76 | 79 | ||
77 | mov r0, #MCPM_SYNC_CLUSTER_SIZE | 80 | mov r0, #MCPM_SYNC_CLUSTER_SIZE |
78 | mla r8, r0, r10, r8 @ r8 = sync cluster base | 81 | mla r8, r0, r10, r8 @ r8 = sync cluster base |
@@ -86,13 +89,22 @@ ENTRY(mcpm_entry_point) | |||
86 | @ At this point, the cluster cannot unexpectedly enter the GOING_DOWN | 89 | @ At this point, the cluster cannot unexpectedly enter the GOING_DOWN |
87 | @ state, because there is at least one active CPU (this CPU). | 90 | @ state, because there is at least one active CPU (this CPU). |
88 | 91 | ||
89 | @ Note: the following is racy as another CPU might be testing | 92 | mov r0, #VLOCK_SIZE |
90 | @ the same flag at the same moment. That'll be fixed later. | 93 | mla r11, r0, r10, r11 @ r11 = cluster first man lock |
94 | mov r0, r11 | ||
95 | mov r1, r9 @ cpu | ||
96 | bl vlock_trylock @ implies DMB | ||
97 | |||
98 | cmp r0, #0 @ failed to get the lock? | ||
99 | bne mcpm_setup_wait @ wait for cluster setup if so | ||
100 | |||
91 | ldrb r0, [r8, #MCPM_SYNC_CLUSTER_CLUSTER] | 101 | ldrb r0, [r8, #MCPM_SYNC_CLUSTER_CLUSTER] |
92 | cmp r0, #CLUSTER_UP @ cluster already up? | 102 | cmp r0, #CLUSTER_UP @ cluster already up? |
93 | bne mcpm_setup @ if not, set up the cluster | 103 | bne mcpm_setup @ if not, set up the cluster |
94 | 104 | ||
95 | @ Otherwise, skip setup: | 105 | @ Otherwise, release the first man lock and skip setup: |
106 | mov r0, r11 | ||
107 | bl vlock_unlock | ||
96 | b mcpm_setup_complete | 108 | b mcpm_setup_complete |
97 | 109 | ||
98 | mcpm_setup: | 110 | mcpm_setup: |
@@ -142,6 +154,19 @@ mcpm_setup_leave: | |||
142 | dsb | 154 | dsb |
143 | sev | 155 | sev |
144 | 156 | ||
157 | mov r0, r11 | ||
158 | bl vlock_unlock @ implies DMB | ||
159 | b mcpm_setup_complete | ||
160 | |||
161 | @ In the contended case, non-first men wait here for cluster setup | ||
162 | @ to complete: | ||
163 | mcpm_setup_wait: | ||
164 | ldrb r0, [r8, #MCPM_SYNC_CLUSTER_CLUSTER] | ||
165 | cmp r0, #CLUSTER_UP | ||
166 | wfene | ||
167 | bne mcpm_setup_wait | ||
168 | dmb | ||
169 | |||
145 | mcpm_setup_complete: | 170 | mcpm_setup_complete: |
146 | @ If a platform-specific CPU setup hook is needed, it is | 171 | @ If a platform-specific CPU setup hook is needed, it is |
147 | @ called from here. | 172 | @ called from here. |
@@ -173,11 +198,17 @@ mcpm_entry_gated: | |||
173 | 3: .word mcpm_entry_vectors - . | 198 | 3: .word mcpm_entry_vectors - . |
174 | .word mcpm_power_up_setup_phys - 3b | 199 | .word mcpm_power_up_setup_phys - 3b |
175 | .word mcpm_sync - 3b | 200 | .word mcpm_sync - 3b |
201 | .word first_man_locks - 3b | ||
176 | 202 | ||
177 | ENDPROC(mcpm_entry_point) | 203 | ENDPROC(mcpm_entry_point) |
178 | 204 | ||
179 | .bss | 205 | .bss |
180 | .align 5 | 206 | |
207 | .align CACHE_WRITEBACK_ORDER | ||
208 | .type first_man_locks, #object | ||
209 | first_man_locks: | ||
210 | .space VLOCK_SIZE * MAX_NR_CLUSTERS | ||
211 | .align CACHE_WRITEBACK_ORDER | ||
181 | 212 | ||
182 | .type mcpm_entry_vectors, #object | 213 | .type mcpm_entry_vectors, #object |
183 | ENTRY(mcpm_entry_vectors) | 214 | ENTRY(mcpm_entry_vectors) |
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 1bed82a0a9e0..3f088225e71c 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c | |||
@@ -150,6 +150,7 @@ int main(void) | |||
150 | DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); | 150 | DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); |
151 | DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); | 151 | DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); |
152 | BLANK(); | 152 | BLANK(); |
153 | DEFINE(CACHE_WRITEBACK_ORDER, __CACHE_WRITEBACK_ORDER); | ||
153 | DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE); | 154 | DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE); |
154 | BLANK(); | 155 | BLANK(); |
155 | #ifdef CONFIG_KVM_ARM_HOST | 156 | #ifdef CONFIG_KVM_ARM_HOST |