aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-19 23:43:47 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-19 23:43:47 -0400
commit3d07f0e83d4323d2cd45cc583f7cf1957aca3cac (patch)
tree279203d24b3a366ed6da93a3f9664409eb1a8488 /arch/powerpc/kernel
parent593adf317cf165f7c66facf2285db9d4befbd1c0 (diff)
parentbbfff72ee3e76bd4712b87386af00bfe97114bc9 (diff)
Merge remote branch 'kumar/next' into next
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/cpu_setup_fsl_booke.S3
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S112
-rw-r--r--arch/powerpc/kernel/setup_64.c8
3 files changed, 120 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index 913611105c1f..8053db02b85e 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -88,6 +88,9 @@ _GLOBAL(__setup_cpu_e5500)
88 bl __e500_dcache_setup 88 bl __e500_dcache_setup
89#ifdef CONFIG_PPC_BOOK3E_64 89#ifdef CONFIG_PPC_BOOK3E_64
90 bl .__setup_base_ivors 90 bl .__setup_base_ivors
91 bl .setup_perfmon_ivor
92 bl .setup_doorbell_ivors
93 bl .setup_ehv_ivors
91#else 94#else
92 bl __setup_e500mc_ivors 95 bl __setup_e500mc_ivors
93#endif 96#endif
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 4d0abb4930a1..d24d4400cc79 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -253,9 +253,6 @@ exception_marker:
253 .balign 0x1000 253 .balign 0x1000
254 .globl interrupt_base_book3e 254 .globl interrupt_base_book3e
255interrupt_base_book3e: /* fake trap */ 255interrupt_base_book3e: /* fake trap */
256 /* Note: If real debug exceptions are supported by the HW, the vector
257 * below will have to be patched up to point to an appropriate handler
258 */
259 EXCEPTION_STUB(0x000, machine_check) /* 0x0200 */ 256 EXCEPTION_STUB(0x000, machine_check) /* 0x0200 */
260 EXCEPTION_STUB(0x020, critical_input) /* 0x0580 */ 257 EXCEPTION_STUB(0x020, critical_input) /* 0x0580 */
261 EXCEPTION_STUB(0x040, debug_crit) /* 0x0d00 */ 258 EXCEPTION_STUB(0x040, debug_crit) /* 0x0d00 */
@@ -272,8 +269,13 @@ interrupt_base_book3e: /* fake trap */
272 EXCEPTION_STUB(0x1a0, watchdog) /* 0x09f0 */ 269 EXCEPTION_STUB(0x1a0, watchdog) /* 0x09f0 */
273 EXCEPTION_STUB(0x1c0, data_tlb_miss) 270 EXCEPTION_STUB(0x1c0, data_tlb_miss)
274 EXCEPTION_STUB(0x1e0, instruction_tlb_miss) 271 EXCEPTION_STUB(0x1e0, instruction_tlb_miss)
272 EXCEPTION_STUB(0x260, perfmon)
275 EXCEPTION_STUB(0x280, doorbell) 273 EXCEPTION_STUB(0x280, doorbell)
276 EXCEPTION_STUB(0x2a0, doorbell_crit) 274 EXCEPTION_STUB(0x2a0, doorbell_crit)
275 EXCEPTION_STUB(0x2c0, guest_doorbell)
276 EXCEPTION_STUB(0x2e0, guest_doorbell_crit)
277 EXCEPTION_STUB(0x300, hypercall)
278 EXCEPTION_STUB(0x320, ehpriv)
277 279
278 .globl interrupt_end_book3e 280 .globl interrupt_end_book3e
279interrupt_end_book3e: 281interrupt_end_book3e:
@@ -455,6 +457,70 @@ interrupt_end_book3e:
455kernel_dbg_exc: 457kernel_dbg_exc:
456 b . /* NYI */ 458 b . /* NYI */
457 459
460/* Debug exception as a debug interrupt*/
461 START_EXCEPTION(debug_debug);
462 DBG_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS)
463
464 /*
465 * If there is a single step or branch-taken exception in an
466 * exception entry sequence, it was probably meant to apply to
467 * the code where the exception occurred (since exception entry
468 * doesn't turn off DE automatically). We simulate the effect
469 * of turning off DE on entry to an exception handler by turning
470 * off DE in the DSRR1 value and clearing the debug status.
471 */
472
473 mfspr r14,SPRN_DBSR /* check single-step/branch taken */
474 andis. r15,r14,DBSR_IC@h
475 beq+ 1f
476
477 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
478 LOAD_REG_IMMEDIATE(r15,interrupt_end_book3e)
479 cmpld cr0,r10,r14
480 cmpld cr1,r10,r15
481 blt+ cr0,1f
482 bge+ cr1,1f
483
484 /* here it looks like we got an inappropriate debug exception. */
485 lis r14,DBSR_IC@h /* clear the IC event */
486 rlwinm r11,r11,0,~MSR_DE /* clear DE in the DSRR1 value */
487 mtspr SPRN_DBSR,r14
488 mtspr SPRN_DSRR1,r11
489 lwz r10,PACA_EXDBG+EX_CR(r13) /* restore registers */
490 ld r1,PACA_EXDBG+EX_R1(r13)
491 ld r14,PACA_EXDBG+EX_R14(r13)
492 ld r15,PACA_EXDBG+EX_R15(r13)
493 mtcr r10
494 ld r10,PACA_EXDBG+EX_R10(r13) /* restore registers */
495 ld r11,PACA_EXDBG+EX_R11(r13)
496 mfspr r13,SPRN_SPRG_DBG_SCRATCH
497 rfdi
498
499 /* Normal debug exception */
500 /* XXX We only handle coming from userspace for now since we can't
501 * quite save properly an interrupted kernel state yet
502 */
5031: andi. r14,r11,MSR_PR; /* check for userspace again */
504 beq kernel_dbg_exc; /* if from kernel mode */
505
506 /* Now we mash up things to make it look like we are coming on a
507 * normal exception
508 */
509 mfspr r15,SPRN_SPRG_DBG_SCRATCH
510 mtspr SPRN_SPRG_GEN_SCRATCH,r15
511 mfspr r14,SPRN_DBSR
512 EXCEPTION_COMMON(0xd00, PACA_EXDBG, INTS_DISABLE_ALL)
513 std r14,_DSISR(r1)
514 addi r3,r1,STACK_FRAME_OVERHEAD
515 mr r4,r14
516 ld r14,PACA_EXDBG+EX_R14(r13)
517 ld r15,PACA_EXDBG+EX_R15(r13)
518 bl .save_nvgprs
519 bl .DebugException
520 b .ret_from_except
521
522 MASKABLE_EXCEPTION(0x260, perfmon, .performance_monitor_exception, ACK_NONE)
523
458/* Doorbell interrupt */ 524/* Doorbell interrupt */
459 MASKABLE_EXCEPTION(0x2070, doorbell, .doorbell_exception, ACK_NONE) 525 MASKABLE_EXCEPTION(0x2070, doorbell, .doorbell_exception, ACK_NONE)
460 526
@@ -469,6 +535,11 @@ kernel_dbg_exc:
469// b ret_from_crit_except 535// b ret_from_crit_except
470 b . 536 b .
471 537
538 MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE)
539 MASKABLE_EXCEPTION(0x2e0, guest_doorbell_crit, .unknown_exception, ACK_NONE)
540 MASKABLE_EXCEPTION(0x310, hypercall, .unknown_exception, ACK_NONE)
541 MASKABLE_EXCEPTION(0x320, ehpriv, .unknown_exception, ACK_NONE)
542
472 543
473/* 544/*
474 * An interrupt came in while soft-disabled; clear EE in SRR1, 545 * An interrupt came in while soft-disabled; clear EE in SRR1,
@@ -588,7 +659,12 @@ fast_exception_return:
588BAD_STACK_TRAMPOLINE(0x000) 659BAD_STACK_TRAMPOLINE(0x000)
589BAD_STACK_TRAMPOLINE(0x100) 660BAD_STACK_TRAMPOLINE(0x100)
590BAD_STACK_TRAMPOLINE(0x200) 661BAD_STACK_TRAMPOLINE(0x200)
662BAD_STACK_TRAMPOLINE(0x260)
663BAD_STACK_TRAMPOLINE(0x2c0)
664BAD_STACK_TRAMPOLINE(0x2e0)
591BAD_STACK_TRAMPOLINE(0x300) 665BAD_STACK_TRAMPOLINE(0x300)
666BAD_STACK_TRAMPOLINE(0x310)
667BAD_STACK_TRAMPOLINE(0x320)
592BAD_STACK_TRAMPOLINE(0x400) 668BAD_STACK_TRAMPOLINE(0x400)
593BAD_STACK_TRAMPOLINE(0x500) 669BAD_STACK_TRAMPOLINE(0x500)
594BAD_STACK_TRAMPOLINE(0x600) 670BAD_STACK_TRAMPOLINE(0x600)
@@ -1124,3 +1200,33 @@ _GLOBAL(__setup_base_ivors)
1124 sync 1200 sync
1125 1201
1126 blr 1202 blr
1203
1204_GLOBAL(setup_perfmon_ivor)
1205 SET_IVOR(35, 0x260) /* Performance Monitor */
1206 blr
1207
1208_GLOBAL(setup_doorbell_ivors)
1209 SET_IVOR(36, 0x280) /* Processor Doorbell */
1210 SET_IVOR(37, 0x2a0) /* Processor Doorbell Crit */
1211
1212 /* Check MMUCFG[LPIDSIZE] to determine if we have category E.HV */
1213 mfspr r10,SPRN_MMUCFG
1214 rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
1215 beqlr
1216
1217 SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
1218 SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
1219 blr
1220
1221_GLOBAL(setup_ehv_ivors)
1222 /*
1223 * We may be running as a guest and lack E.HV even on a chip
1224 * that normally has it.
1225 */
1226 mfspr r10,SPRN_MMUCFG
1227 rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
1228 beqlr
1229
1230 SET_IVOR(40, 0x300) /* Embedded Hypervisor System Call */
1231 SET_IVOR(41, 0x320) /* Embedded Hypervisor Privilege */
1232 blr
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index c2ec0a12e14f..a88bf2713d41 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -62,6 +62,7 @@
62#include <asm/udbg.h> 62#include <asm/udbg.h>
63#include <asm/kexec.h> 63#include <asm/kexec.h>
64#include <asm/mmu_context.h> 64#include <asm/mmu_context.h>
65#include <asm/code-patching.h>
65 66
66#include "setup.h" 67#include "setup.h"
67 68
@@ -477,6 +478,9 @@ static void __init irqstack_early_init(void)
477#ifdef CONFIG_PPC_BOOK3E 478#ifdef CONFIG_PPC_BOOK3E
478static void __init exc_lvl_early_init(void) 479static void __init exc_lvl_early_init(void)
479{ 480{
481 extern unsigned int interrupt_base_book3e;
482 extern unsigned int exc_debug_debug_book3e;
483
480 unsigned int i; 484 unsigned int i;
481 485
482 for_each_possible_cpu(i) { 486 for_each_possible_cpu(i) {
@@ -487,6 +491,10 @@ static void __init exc_lvl_early_init(void)
487 mcheckirq_ctx[i] = (struct thread_info *) 491 mcheckirq_ctx[i] = (struct thread_info *)
488 __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE)); 492 __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
489 } 493 }
494
495 if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC))
496 patch_branch(&interrupt_base_book3e + (0x040 / 4) + 1,
497 (unsigned long)&exc_debug_debug_book3e, 0);
490} 498}
491#else 499#else
492#define exc_lvl_early_init() 500#define exc_lvl_early_init()