aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/alternative.c
diff options
context:
space:
mode:
authorJan Beulich <JBeulich@novell.com>2010-04-21 11:08:14 -0400
committerH. Peter Anvin <hpa@zytor.com>2010-04-28 20:15:47 -0400
commit5967ed87ade85a421ef814296c3c7f182b08c225 (patch)
tree16d08b1e34308390d189ddc52e7c4e25cc841e41 /arch/x86/kernel/alternative.c
parent402af0d7c692ddcfa2333e93d3f275ebd0487926 (diff)
x86-64: Reduce SMP locks table size
Reduce the SMP locks table size by using relative pointers instead of absolute ones, thus cutting the table size by half. Signed-off-by: Jan Beulich <jbeulich@novell.com> LKML-Reference: <4BCF30FE020000780003B3B6@vpn.id2.novell.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/alternative.c')
-rw-r--r--arch/x86/kernel/alternative.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 1a160d5d44d0..936738427223 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -194,7 +194,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
194} 194}
195 195
196extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; 196extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
197extern u8 *__smp_locks[], *__smp_locks_end[]; 197extern s32 __smp_locks[], __smp_locks_end[];
198static void *text_poke_early(void *addr, const void *opcode, size_t len); 198static void *text_poke_early(void *addr, const void *opcode, size_t len);
199 199
200/* Replace instructions with better alternatives for this CPU type. 200/* Replace instructions with better alternatives for this CPU type.
@@ -235,37 +235,39 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
235 235
236#ifdef CONFIG_SMP 236#ifdef CONFIG_SMP
237 237
238static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) 238static void alternatives_smp_lock(const s32 *start, const s32 *end,
239 u8 *text, u8 *text_end)
239{ 240{
240 u8 **ptr; 241 const s32 *poff;
241 242
242 mutex_lock(&text_mutex); 243 mutex_lock(&text_mutex);
243 for (ptr = start; ptr < end; ptr++) { 244 for (poff = start; poff < end; poff++) {
244 if (*ptr < text) 245 u8 *ptr = (u8 *)poff + *poff;
245 continue; 246
246 if (*ptr > text_end) 247 if (!*poff || ptr < text || ptr >= text_end)
247 continue; 248 continue;
248 /* turn DS segment override prefix into lock prefix */ 249 /* turn DS segment override prefix into lock prefix */
249 text_poke(*ptr, ((unsigned char []){0xf0}), 1); 250 text_poke(ptr, ((unsigned char []){0xf0}), 1);
250 }; 251 };
251 mutex_unlock(&text_mutex); 252 mutex_unlock(&text_mutex);
252} 253}
253 254
254static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) 255static void alternatives_smp_unlock(const s32 *start, const s32 *end,
256 u8 *text, u8 *text_end)
255{ 257{
256 u8 **ptr; 258 const s32 *poff;
257 259
258 if (noreplace_smp) 260 if (noreplace_smp)
259 return; 261 return;
260 262
261 mutex_lock(&text_mutex); 263 mutex_lock(&text_mutex);
262 for (ptr = start; ptr < end; ptr++) { 264 for (poff = start; poff < end; poff++) {
263 if (*ptr < text) 265 u8 *ptr = (u8 *)poff + *poff;
264 continue; 266
265 if (*ptr > text_end) 267 if (!*poff || ptr < text || ptr >= text_end)
266 continue; 268 continue;
267 /* turn lock prefix into DS segment override prefix */ 269 /* turn lock prefix into DS segment override prefix */
268 text_poke(*ptr, ((unsigned char []){0x3E}), 1); 270 text_poke(ptr, ((unsigned char []){0x3E}), 1);
269 }; 271 };
270 mutex_unlock(&text_mutex); 272 mutex_unlock(&text_mutex);
271} 273}
@@ -276,8 +278,8 @@ struct smp_alt_module {
276 char *name; 278 char *name;
277 279
278 /* ptrs to lock prefixes */ 280 /* ptrs to lock prefixes */
279 u8 **locks; 281 const s32 *locks;
280 u8 **locks_end; 282 const s32 *locks_end;
281 283
282 /* .text segment, needed to avoid patching init code ;) */ 284 /* .text segment, needed to avoid patching init code ;) */
283 u8 *text; 285 u8 *text;
@@ -398,16 +400,19 @@ void alternatives_smp_switch(int smp)
398int alternatives_text_reserved(void *start, void *end) 400int alternatives_text_reserved(void *start, void *end)
399{ 401{
400 struct smp_alt_module *mod; 402 struct smp_alt_module *mod;
401 u8 **ptr; 403 const s32 *poff;
402 u8 *text_start = start; 404 u8 *text_start = start;
403 u8 *text_end = end; 405 u8 *text_end = end;
404 406
405 list_for_each_entry(mod, &smp_alt_modules, next) { 407 list_for_each_entry(mod, &smp_alt_modules, next) {
406 if (mod->text > text_end || mod->text_end < text_start) 408 if (mod->text > text_end || mod->text_end < text_start)
407 continue; 409 continue;
408 for (ptr = mod->locks; ptr < mod->locks_end; ptr++) 410 for (poff = mod->locks; poff < mod->locks_end; poff++) {
409 if (text_start <= *ptr && text_end >= *ptr) 411 const u8 *ptr = (const u8 *)poff + *poff;
412
413 if (text_start <= ptr && text_end > ptr)
410 return 1; 414 return 1;
415 }
411 } 416 }
412 417
413 return 0; 418 return 0;