aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c91
1 files changed, 72 insertions, 19 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 4e293b75f951..987437e04e61 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1034,9 +1034,68 @@ void SoftwareEmulation(struct pt_regs *regs)
1034#endif /* CONFIG_8xx */ 1034#endif /* CONFIG_8xx */
1035 1035
1036#ifdef CONFIG_PPC_ADV_DEBUG_REGS 1036#ifdef CONFIG_PPC_ADV_DEBUG_REGS
1037static void handle_debug(struct pt_regs *regs, unsigned long debug_status)
1038{
1039 int changed = 0;
1040 /*
1041 * Determine the cause of the debug event, clear the
1042 * event flags and send a trap to the handler. Torez
1043 */
1044 if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
1045 dbcr_dac(current) &= ~(DBCR_DAC1R | DBCR_DAC1W);
1046#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
1047 current->thread.dbcr2 &= ~DBCR2_DAC12MODE;
1048#endif
1049 do_send_trap(regs, mfspr(SPRN_DAC1), debug_status, TRAP_HWBKPT,
1050 5);
1051 changed |= 0x01;
1052 } else if (debug_status & (DBSR_DAC2R | DBSR_DAC2W)) {
1053 dbcr_dac(current) &= ~(DBCR_DAC2R | DBCR_DAC2W);
1054 do_send_trap(regs, mfspr(SPRN_DAC2), debug_status, TRAP_HWBKPT,
1055 6);
1056 changed |= 0x01;
1057 } else if (debug_status & DBSR_IAC1) {
1058 current->thread.dbcr0 &= ~DBCR0_IAC1;
1059 dbcr_iac_range(current) &= ~DBCR_IAC12MODE;
1060 do_send_trap(regs, mfspr(SPRN_IAC1), debug_status, TRAP_HWBKPT,
1061 1);
1062 changed |= 0x01;
1063 } else if (debug_status & DBSR_IAC2) {
1064 current->thread.dbcr0 &= ~DBCR0_IAC2;
1065 do_send_trap(regs, mfspr(SPRN_IAC2), debug_status, TRAP_HWBKPT,
1066 2);
1067 changed |= 0x01;
1068 } else if (debug_status & DBSR_IAC3) {
1069 current->thread.dbcr0 &= ~DBCR0_IAC3;
1070 dbcr_iac_range(current) &= ~DBCR_IAC34MODE;
1071 do_send_trap(regs, mfspr(SPRN_IAC3), debug_status, TRAP_HWBKPT,
1072 3);
1073 changed |= 0x01;
1074 } else if (debug_status & DBSR_IAC4) {
1075 current->thread.dbcr0 &= ~DBCR0_IAC4;
1076 do_send_trap(regs, mfspr(SPRN_IAC4), debug_status, TRAP_HWBKPT,
1077 4);
1078 changed |= 0x01;
1079 }
1080 /*
1081 * At the point this routine was called, the MSR(DE) was turned off.
1082 * Check all other debug flags and see if that bit needs to be turned
1083 * back on or not.
1084 */
1085 if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, current->thread.dbcr1))
1086 regs->msr |= MSR_DE;
1087 else
1088 /* Make sure the IDM flag is off */
1089 current->thread.dbcr0 &= ~DBCR0_IDM;
1090
1091 if (changed & 0x01)
1092 mtspr(SPRN_DBCR0, current->thread.dbcr0);
1093}
1037 1094
1038void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) 1095void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
1039{ 1096{
1097 current->thread.dbsr = debug_status;
1098
1040 /* Hack alert: On BookE, Branch Taken stops on the branch itself, while 1099 /* Hack alert: On BookE, Branch Taken stops on the branch itself, while
1041 * on server, it stops on the target of the branch. In order to simulate 1100 * on server, it stops on the target of the branch. In order to simulate
1042 * the server behaviour, we thus restart right away with a single step 1101 * the server behaviour, we thus restart right away with a single step
@@ -1080,27 +1139,21 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
1080 if (debugger_sstep(regs)) 1139 if (debugger_sstep(regs))
1081 return; 1140 return;
1082 1141
1083 if (user_mode(regs))
1084 current->thread.dbcr0 &= ~(DBCR0_IC);
1085
1086 _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
1087 } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
1088 regs->msr &= ~MSR_DE;
1089
1090 if (user_mode(regs)) { 1142 if (user_mode(regs)) {
1091 current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | 1143 current->thread.dbcr0 &= ~DBCR0_IC;
1092 DBCR0_IDM); 1144#ifdef CONFIG_PPC_ADV_DEBUG_REGS
1093 } else { 1145 if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0,
1094 /* Disable DAC interupts */ 1146 current->thread.dbcr1))
1095 mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | 1147 regs->msr |= MSR_DE;
1096 DBSR_DAC1W | DBCR0_IDM)); 1148 else
1097 1149 /* Make sure the IDM bit is off */
1098 /* Clear the DAC event */ 1150 current->thread.dbcr0 &= ~DBCR0_IDM;
1099 mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W)); 1151#endif
1100 } 1152 }
1101 /* Setup and send the trap to the handler */ 1153
1102 do_dabr(regs, mfspr(SPRN_DAC1), debug_status); 1154 _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
1103 } 1155 } else
1156 handle_debug(regs, debug_status);
1104} 1157}
1105#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ 1158#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
1106 1159