diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-10 23:24:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-10 23:24:39 -0400 |
commit | bf83e61464803d386d0ec3fc92e5449d7963a409 (patch) | |
tree | 8bce8f80bad1650a776042cee13a7a0ba38efb6c /arch | |
parent | a60d4b9874dc62cf0fd0d42b247baaaef75d30f8 (diff) | |
parent | 363edbe2614aa90df706c0f19ccfa2a6c06af0be (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Ben Herrenschmidt:
"Here are a handful of small powerpc fixes.
A couple of section mismatches (always worth fixing), a missing export
of a new symbol causing build failures of modules, a page fault
deadlock fix (interestingly that bug has been around for a LONG time,
though it seems to be more easily triggered by KVM) and fixing pseries
default idle loop in the absence of the cpuidle drivers (such as
during boot)"
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
powerpc: Default arch idle could cede processor on pseries
fbdev/ps3fb: Fix section mismatch warning for ps3fb_probe
powerpc: Fix section mismatch warning for prom_rtas_call
powerpc: Fix possible deadlock on page fault
powerpc: Export cpu_to_chip_id() to fix build error
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/smp.c | 1 | ||||
-rw-r--r-- | arch/powerpc/mm/fault.c | 13 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 31 |
4 files changed, 34 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 7b6391b68fb8..12e656ffe60e 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -1297,7 +1297,8 @@ static void __init prom_query_opal(void) | |||
1297 | prom_opal_align = 0x10000; | 1297 | prom_opal_align = 0x10000; |
1298 | } | 1298 | } |
1299 | 1299 | ||
1300 | static int prom_rtas_call(int token, int nargs, int nret, int *outputs, ...) | 1300 | static int __init prom_rtas_call(int token, int nargs, int nret, |
1301 | int *outputs, ...) | ||
1301 | { | 1302 | { |
1302 | struct rtas_args rtas_args; | 1303 | struct rtas_args rtas_args; |
1303 | va_list list; | 1304 | va_list list; |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 442d8e23f8f4..8e59abc237d7 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -611,6 +611,7 @@ int cpu_to_chip_id(int cpu) | |||
611 | of_node_put(np); | 611 | of_node_put(np); |
612 | return of_get_ibm_chip_id(np); | 612 | return of_get_ibm_chip_id(np); |
613 | } | 613 | } |
614 | EXPORT_SYMBOL(cpu_to_chip_id); | ||
614 | 615 | ||
615 | /* Helper routines for cpu to core mapping */ | 616 | /* Helper routines for cpu to core mapping */ |
616 | int cpu_core_index_of_thread(int cpu) | 617 | int cpu_core_index_of_thread(int cpu) |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 76d8e7cc7805..2dd69bf4af46 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -206,7 +206,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
206 | int trap = TRAP(regs); | 206 | int trap = TRAP(regs); |
207 | int is_exec = trap == 0x400; | 207 | int is_exec = trap == 0x400; |
208 | int fault; | 208 | int fault; |
209 | int rc = 0; | 209 | int rc = 0, store_update_sp = 0; |
210 | 210 | ||
211 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | 211 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) |
212 | /* | 212 | /* |
@@ -280,6 +280,14 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
280 | 280 | ||
281 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | 281 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); |
282 | 282 | ||
283 | /* | ||
284 | * We want to do this outside mmap_sem, because reading code around nip | ||
285 | * can result in fault, which will cause a deadlock when called with | ||
286 | * mmap_sem held | ||
287 | */ | ||
288 | if (user_mode(regs)) | ||
289 | store_update_sp = store_updates_sp(regs); | ||
290 | |||
283 | /* When running in the kernel we expect faults to occur only to | 291 | /* When running in the kernel we expect faults to occur only to |
284 | * addresses in user space. All other faults represent errors in the | 292 | * addresses in user space. All other faults represent errors in the |
285 | * kernel and should generate an OOPS. Unfortunately, in the case of an | 293 | * kernel and should generate an OOPS. Unfortunately, in the case of an |
@@ -345,8 +353,7 @@ retry: | |||
345 | * between the last mapped region and the stack will | 353 | * between the last mapped region and the stack will |
346 | * expand the stack rather than segfaulting. | 354 | * expand the stack rather than segfaulting. |
347 | */ | 355 | */ |
348 | if (address + 2048 < uregs->gpr[1] | 356 | if (address + 2048 < uregs->gpr[1] && !store_update_sp) |
349 | && (!user_mode(regs) || !store_updates_sp(regs))) | ||
350 | goto bad_area; | 357 | goto bad_area; |
351 | } | 358 | } |
352 | if (expand_stack(vma, address)) | 359 | if (expand_stack(vma, address)) |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index d64feb3ea0be..1f97e2b87a62 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -354,7 +354,7 @@ static int alloc_dispatch_log_kmem_cache(void) | |||
354 | } | 354 | } |
355 | early_initcall(alloc_dispatch_log_kmem_cache); | 355 | early_initcall(alloc_dispatch_log_kmem_cache); |
356 | 356 | ||
357 | static void pSeries_idle(void) | 357 | static void pseries_lpar_idle(void) |
358 | { | 358 | { |
359 | /* This would call on the cpuidle framework, and the back-end pseries | 359 | /* This would call on the cpuidle framework, and the back-end pseries |
360 | * driver to go to idle states | 360 | * driver to go to idle states |
@@ -362,10 +362,22 @@ static void pSeries_idle(void) | |||
362 | if (cpuidle_idle_call()) { | 362 | if (cpuidle_idle_call()) { |
363 | /* On error, execute default handler | 363 | /* On error, execute default handler |
364 | * to go into low thread priority and possibly | 364 | * to go into low thread priority and possibly |
365 | * low power mode. | 365 | * low power mode by cedeing processor to hypervisor |
366 | */ | 366 | */ |
367 | HMT_low(); | 367 | |
368 | HMT_very_low(); | 368 | /* Indicate to hypervisor that we are idle. */ |
369 | get_lppaca()->idle = 1; | ||
370 | |||
371 | /* | ||
372 | * Yield the processor to the hypervisor. We return if | ||
373 | * an external interrupt occurs (which are driven prior | ||
374 | * to returning here) or if a prod occurs from another | ||
375 | * processor. When returning here, external interrupts | ||
376 | * are enabled. | ||
377 | */ | ||
378 | cede_processor(); | ||
379 | |||
380 | get_lppaca()->idle = 0; | ||
369 | } | 381 | } |
370 | } | 382 | } |
371 | 383 | ||
@@ -456,15 +468,14 @@ static void __init pSeries_setup_arch(void) | |||
456 | 468 | ||
457 | pSeries_nvram_init(); | 469 | pSeries_nvram_init(); |
458 | 470 | ||
459 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | 471 | if (firmware_has_feature(FW_FEATURE_LPAR)) { |
460 | vpa_init(boot_cpuid); | 472 | vpa_init(boot_cpuid); |
461 | ppc_md.power_save = pSeries_idle; | 473 | ppc_md.power_save = pseries_lpar_idle; |
462 | } | ||
463 | |||
464 | if (firmware_has_feature(FW_FEATURE_LPAR)) | ||
465 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; | 474 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; |
466 | else | 475 | } else { |
476 | /* No special idle routine */ | ||
467 | ppc_md.enable_pmcs = power4_enable_pmcs; | 477 | ppc_md.enable_pmcs = power4_enable_pmcs; |
478 | } | ||
468 | 479 | ||
469 | ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; | 480 | ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; |
470 | 481 | ||