^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/regset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/hw_breakpoint.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "ptrace-decl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) void user_enable_single_step(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) struct pt_regs *regs = task->thread.regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) if (regs != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) task->thread.debug.dbcr0 &= ~DBCR0_BT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) task->thread.debug.dbcr0 |= DBCR0_IDM | DBCR0_IC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) regs->msr |= MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) set_tsk_thread_flag(task, TIF_SINGLESTEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) void user_enable_block_step(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct pt_regs *regs = task->thread.regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (regs != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) task->thread.debug.dbcr0 &= ~DBCR0_IC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) task->thread.debug.dbcr0 = DBCR0_IDM | DBCR0_BT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) regs->msr |= MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) set_tsk_thread_flag(task, TIF_SINGLESTEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) void user_disable_single_step(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct pt_regs *regs = task->thread.regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (regs != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * The logic to disable single stepping should be as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * simple as turning off the Instruction Complete flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * And, after doing so, if all debug flags are off, turn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * off DBCR0(IDM) and MSR(DE) .... Torez
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) task->thread.debug.dbcr0 &= ~(DBCR0_IC | DBCR0_BT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Test to see if any of the DBCR_ACTIVE_EVENTS bits are set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (!DBCR_ACTIVE_EVENTS(task->thread.debug.dbcr0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) task->thread.debug.dbcr1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * All debug events were off.....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) task->thread.debug.dbcr0 &= ~DBCR0_IDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) regs->msr &= ~MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) clear_tsk_thread_flag(task, TIF_SINGLESTEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) void ppc_gethwdinfo(struct ppc_debug_info *dbginfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) dbginfo->version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) dbginfo->num_instruction_bps = CONFIG_PPC_ADV_DEBUG_IACS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) dbginfo->num_data_bps = CONFIG_PPC_ADV_DEBUG_DACS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dbginfo->num_condition_regs = CONFIG_PPC_ADV_DEBUG_DVCS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) dbginfo->data_bp_alignment = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) dbginfo->sizeof_condition = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) dbginfo->features = PPC_DEBUG_FEATURE_INSN_BP_RANGE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) PPC_DEBUG_FEATURE_INSN_BP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (IS_ENABLED(CONFIG_PPC_ADV_DEBUG_DAC_RANGE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) dbginfo->features |= PPC_DEBUG_FEATURE_DATA_BP_RANGE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) PPC_DEBUG_FEATURE_DATA_BP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int ptrace_get_debugreg(struct task_struct *child, unsigned long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long __user *datalp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* We only support one DABR and no IABRS at the moment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (addr > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return put_user(child->thread.debug.dac1, datalp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #ifdef CONFIG_HAVE_HW_BREAKPOINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct thread_struct *thread = &task->thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct perf_event *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct perf_event_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #endif /* CONFIG_HAVE_HW_BREAKPOINT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * For embedded processors we support one DAC and no IAC's at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * moment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (addr > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* The bottom 3 bits in dabr are flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if ((data & ~0x7UL) >= TASK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* As described above, it was assumed 3 bits were passed with the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * address, but we will assume only the mode bits will be passed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * as to not cause alignment restrictions for DAC-based processors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* DAC's hold the whole address without any mode flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) task->thread.debug.dac1 = data & ~0x3UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (task->thread.debug.dac1 == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!DBCR_ACTIVE_EVENTS(task->thread.debug.dbcr0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) task->thread.debug.dbcr1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) task->thread.regs->msr &= ~MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) task->thread.debug.dbcr0 &= ~DBCR0_IDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Read or Write bits must be set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!(data & 0x3UL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) task->thread.debug.dbcr0 |= DBCR0_IDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* Check for write and read flags and set DBCR0 accordingly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (data & 0x1UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) dbcr_dac(task) |= DBCR_DAC1R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (data & 0x2UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) dbcr_dac(task) |= DBCR_DAC1W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) task->thread.regs->msr |= MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static long set_instruction_bp(struct task_struct *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct ppc_hw_breakpoint *bp_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int slot1_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC1) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int slot2_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC2) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int slot3_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC3) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int slot4_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC4) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (dbcr_iac_range(child) & DBCR_IAC12MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) slot2_in_use = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (dbcr_iac_range(child) & DBCR_IAC34MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) slot4_in_use = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (bp_info->addr >= TASK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Make sure range is valid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (bp_info->addr2 >= TASK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* We need a pair of IAC regsisters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (!slot1_in_use && !slot2_in_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) slot = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) child->thread.debug.iac1 = bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) child->thread.debug.iac2 = bp_info->addr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) child->thread.debug.dbcr0 |= DBCR0_IAC1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (bp_info->addr_mode ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dbcr_iac_range(child) |= DBCR_IAC12X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) dbcr_iac_range(child) |= DBCR_IAC12I;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #if CONFIG_PPC_ADV_DEBUG_IACS > 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) } else if ((!slot3_in_use) && (!slot4_in_use)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) slot = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) child->thread.debug.iac3 = bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) child->thread.debug.iac4 = bp_info->addr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) child->thread.debug.dbcr0 |= DBCR0_IAC3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (bp_info->addr_mode ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dbcr_iac_range(child) |= DBCR_IAC34X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dbcr_iac_range(child) |= DBCR_IAC34I;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* We only need one. If possible leave a pair free in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * case a range is needed later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (!slot1_in_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * Don't use iac1 if iac1-iac2 are free and either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * iac3 or iac4 (but not both) are free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (slot2_in_use || slot3_in_use == slot4_in_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) slot = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) child->thread.debug.iac1 = bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) child->thread.debug.dbcr0 |= DBCR0_IAC1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!slot2_in_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) slot = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) child->thread.debug.iac2 = bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) child->thread.debug.dbcr0 |= DBCR0_IAC2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #if CONFIG_PPC_ADV_DEBUG_IACS > 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) } else if (!slot3_in_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) slot = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) child->thread.debug.iac3 = bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) child->thread.debug.dbcr0 |= DBCR0_IAC3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) } else if (!slot4_in_use) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) slot = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) child->thread.debug.iac4 = bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) child->thread.debug.dbcr0 |= DBCR0_IAC4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) child->thread.debug.dbcr0 |= DBCR0_IDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) child->thread.regs->msr |= MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static int del_instruction_bp(struct task_struct *child, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) switch (slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if ((child->thread.debug.dbcr0 & DBCR0_IAC1) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (dbcr_iac_range(child) & DBCR_IAC12MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* address range - clear slots 1 & 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) child->thread.debug.iac2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dbcr_iac_range(child) &= ~DBCR_IAC12MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) child->thread.debug.iac1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) child->thread.debug.dbcr0 &= ~DBCR0_IAC1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if ((child->thread.debug.dbcr0 & DBCR0_IAC2) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (dbcr_iac_range(child) & DBCR_IAC12MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* used in a range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) child->thread.debug.iac2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) child->thread.debug.dbcr0 &= ~DBCR0_IAC2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #if CONFIG_PPC_ADV_DEBUG_IACS > 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if ((child->thread.debug.dbcr0 & DBCR0_IAC3) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (dbcr_iac_range(child) & DBCR_IAC34MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* address range - clear slots 3 & 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) child->thread.debug.iac4 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) dbcr_iac_range(child) &= ~DBCR_IAC34MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) child->thread.debug.iac3 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) child->thread.debug.dbcr0 &= ~DBCR0_IAC3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if ((child->thread.debug.dbcr0 & DBCR0_IAC4) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (dbcr_iac_range(child) & DBCR_IAC34MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* Used in a range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) child->thread.debug.iac4 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) child->thread.debug.dbcr0 &= ~DBCR0_IAC4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int set_dac(struct task_struct *child, struct ppc_hw_breakpoint *bp_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) int byte_enable =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) (bp_info->condition_mode >> PPC_BREAKPOINT_CONDITION_BE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int condition_mode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) bp_info->condition_mode & PPC_BREAKPOINT_CONDITION_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (byte_enable && condition_mode == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (bp_info->addr >= TASK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) slot = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dbcr_dac(child) |= DBCR_DAC1R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) dbcr_dac(child) |= DBCR_DAC1W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) child->thread.debug.dac1 = (unsigned long)bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (byte_enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) child->thread.debug.dvc1 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) (unsigned long)bp_info->condition_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) child->thread.debug.dbcr2 |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ((byte_enable << DBCR2_DVC1BE_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) (condition_mode << DBCR2_DVC1M_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) } else if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* Both dac1 and dac2 are part of a range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) } else if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) slot = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) dbcr_dac(child) |= DBCR_DAC2R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dbcr_dac(child) |= DBCR_DAC2W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) child->thread.debug.dac2 = (unsigned long)bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (byte_enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) child->thread.debug.dvc2 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) (unsigned long)bp_info->condition_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) child->thread.debug.dbcr2 |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ((byte_enable << DBCR2_DVC2BE_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) (condition_mode << DBCR2_DVC2M_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) child->thread.debug.dbcr0 |= DBCR0_IDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) child->thread.regs->msr |= MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return slot + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static int del_dac(struct task_struct *child, int slot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (slot == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) child->thread.debug.dac1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) child->thread.debug.dac2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) child->thread.debug.dbcr2 &= ~DBCR2_DAC12MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) child->thread.debug.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) child->thread.debug.dvc1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) } else if (slot == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* Part of a range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) child->thread.debug.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) child->thread.debug.dvc2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) child->thread.debug.dac2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int set_dac_range(struct task_struct *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct ppc_hw_breakpoint *bp_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) int mode = bp_info->addr_mode & PPC_BREAKPOINT_MODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* We don't allow range watchpoints to be used with DVC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (bp_info->condition_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * Best effort to verify the address range. The user/supervisor bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * prevent trapping in kernel space, but let's fail on an obvious bad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * range. The simple test on the mask is not fool-proof, and any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * exclusive range will spill over into kernel space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (bp_info->addr >= TASK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (mode == PPC_BREAKPOINT_MODE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * dac2 is a bitmask. Don't allow a mask that makes a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * kernel space address from a valid dac1 value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (~((unsigned long)bp_info->addr2) >= TASK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * For range breakpoints, addr2 must also be a valid address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (bp_info->addr2 >= TASK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (child->thread.debug.dbcr0 &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) (DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) child->thread.debug.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) child->thread.debug.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) child->thread.debug.dac1 = bp_info->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) child->thread.debug.dac2 = bp_info->addr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) child->thread.debug.dbcr2 |= DBCR2_DAC12M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) child->thread.debug.dbcr2 |= DBCR2_DAC12MX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) else /* PPC_BREAKPOINT_MODE_MASK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) child->thread.debug.dbcr2 |= DBCR2_DAC12MM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) child->thread.regs->msr |= MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) #endif /* CONFIG_PPC_ADV_DEBUG_DAC_RANGE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) long ppc_set_hwdebug(struct task_struct *child, struct ppc_hw_breakpoint *bp_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (bp_info->version != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * Check for invalid flags and combinations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (bp_info->trigger_type == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) (bp_info->trigger_type & ~(PPC_BREAKPOINT_TRIGGER_EXECUTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) PPC_BREAKPOINT_TRIGGER_RW)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) (bp_info->addr_mode & ~PPC_BREAKPOINT_MODE_MASK) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) (bp_info->condition_mode &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ~(PPC_BREAKPOINT_CONDITION_MODE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) PPC_BREAKPOINT_CONDITION_BE_ALL)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) #if CONFIG_PPC_ADV_DEBUG_DVCS == 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_EXECUTE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_EXECUTE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return set_instruction_bp(child, bp_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return set_dac(child, bp_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return set_dac_range(child, bp_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) long ppc_del_hwdebug(struct task_struct *child, long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (data <= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) rc = del_instruction_bp(child, (int)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) rc = del_dac(child, (int)data - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (!DBCR_ACTIVE_EVENTS(child->thread.debug.dbcr0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) child->thread.debug.dbcr1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) child->thread.debug.dbcr0 &= ~DBCR0_IDM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) child->thread.regs->msr &= ~MSR_DE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }