提交 3671f4eb 编写于 作者: J Jordan Niethe 提交者: Michael Ellerman

powerpc: Allow clearing and restoring registers independent of saved breakpoint state

For the coming temporary mm used for instruction patching, the
breakpoint registers need to be cleared to prevent them from
accidentally being triggered. As soon as the patching is done, the
breakpoints will be restored.

The breakpoint state is stored in the per-cpu variable current_brk[].
Add a suspend_breakpoints() function which will clear the breakpoint
registers without touching the state in current_brk[]. Add a pair
function restore_breakpoints() which will move the state in
current_brk[] back to the registers.
Signed-off-by: NJordan Niethe <jniethe5@gmail.com>
Signed-off-by: NBenjamin Gray <bgray@linux.ibm.com>
Signed-off-by: NMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20221109045112.187069-2-bgray@linux.ibm.com
上级 e082e99f
...@@ -46,6 +46,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } ...@@ -46,6 +46,8 @@ static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
#endif #endif
void __set_breakpoint(int nr, struct arch_hw_breakpoint *brk); void __set_breakpoint(int nr, struct arch_hw_breakpoint *brk);
void suspend_breakpoints(void);
void restore_breakpoints(void);
bool ppc_breakpoint_available(void); bool ppc_breakpoint_available(void);
#ifdef CONFIG_PPC_ADV_DEBUG_REGS #ifdef CONFIG_PPC_ADV_DEBUG_REGS
extern void do_send_trap(struct pt_regs *regs, unsigned long address, extern void do_send_trap(struct pt_regs *regs, unsigned long address,
......
...@@ -862,10 +862,8 @@ static inline int set_breakpoint_8xx(struct arch_hw_breakpoint *brk) ...@@ -862,10 +862,8 @@ static inline int set_breakpoint_8xx(struct arch_hw_breakpoint *brk)
return 0; return 0;
} }
void __set_breakpoint(int nr, struct arch_hw_breakpoint *brk) static void set_hw_breakpoint(int nr, struct arch_hw_breakpoint *brk)
{ {
memcpy(this_cpu_ptr(&current_brk[nr]), brk, sizeof(*brk));
if (dawr_enabled()) if (dawr_enabled())
// Power8 or later // Power8 or later
set_dawr(nr, brk); set_dawr(nr, brk);
...@@ -879,6 +877,12 @@ void __set_breakpoint(int nr, struct arch_hw_breakpoint *brk) ...@@ -879,6 +877,12 @@ void __set_breakpoint(int nr, struct arch_hw_breakpoint *brk)
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} }
void __set_breakpoint(int nr, struct arch_hw_breakpoint *brk)
{
memcpy(this_cpu_ptr(&current_brk[nr]), brk, sizeof(*brk));
set_hw_breakpoint(nr, brk);
}
/* Check if we have DAWR or DABR hardware */ /* Check if we have DAWR or DABR hardware */
bool ppc_breakpoint_available(void) bool ppc_breakpoint_available(void)
{ {
...@@ -891,6 +895,34 @@ bool ppc_breakpoint_available(void) ...@@ -891,6 +895,34 @@ bool ppc_breakpoint_available(void)
} }
EXPORT_SYMBOL_GPL(ppc_breakpoint_available); EXPORT_SYMBOL_GPL(ppc_breakpoint_available);
/* Disable the breakpoint in hardware without touching current_brk[] */
void suspend_breakpoints(void)
{
struct arch_hw_breakpoint brk = {0};
int i;
if (!ppc_breakpoint_available())
return;
for (i = 0; i < nr_wp_slots(); i++)
set_hw_breakpoint(i, &brk);
}
/*
* Re-enable breakpoints suspended by suspend_breakpoints() in hardware
* from current_brk[]
*/
void restore_breakpoints(void)
{
int i;
if (!ppc_breakpoint_available())
return;
for (i = 0; i < nr_wp_slots(); i++)
set_hw_breakpoint(i, this_cpu_ptr(&current_brk[i]));
}
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
static inline bool tm_enabled(struct task_struct *tsk) static inline bool tm_enabled(struct task_struct *tsk)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册