Fix preemption errors in watchpoints
cover Fix preemption errors in watchpoints
When enabling debug config options relating to preemption, several bugs appear in the kernel log. With this series applied, the breakpoint code no longer prints bugs when running the powerpc/ptrace selftests.
Benjamin Gray (3):
powerpc/watchpoints: Disable preemption in thread_change_pc() powerpc/watchpoint: Disable pagefaults when getting user instruction powerpc/watchpoints: Annotate atomic context in more places
arch/powerpc/kernel/hw_breakpoint.c | 16 +++++++++++++++- arch/powerpc/kernel/hw_breakpoint_constraints.c | 7 ++++++- 2 files changed, 21 insertions(+), 2 deletions(-)
--
2.41.0
PATCH 1/3 powerpc/watchpoints: Disable preemption in thread_change_pc()
thread_change_pc() uses CPU local data, so must be protected from swapping CPUs while it is reading the breakpoint struct.
The error is more noticeable after 1e60f3564bad ("powerpc/watchpoints:
Track perf single step directly on the breakpoint"), which added an unconditional __this_cpu_read() call in thread_change_pc(). However the existing __this_cpu_read() that runs if a breakpoint does need to be re-inserted has the same issue.
---
There's probably a more idiomatic way to express this. We technically don't need to disable preemption for the entire function: we should only need to disable preemption within each loop iteration while handling the pointer we are working with. Each iteration itself is independent.
--- arch/powerpc/kernel/hw_breakpoint.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
arch/powerpc/kernel/hw_breakpoint.c +6 -1
@@ -230,13 +230,15 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)struct arch_hw_breakpoint *info;int i; +preempt_disable (); +for (i =0 ; i <nr_wp_slots (); i++) {struct perf_event *bp =__this_cpu_read (bp_per_reg[i]);if (unlikely (bp &&counter_arch_bp (bp)->perf_single_step)) goto reset; } -return ; + goto out; reset:regs_set_return_msr (regs, regs->msr & ~MSR_SE );
@@ -245,6 +247,9 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)__set_breakpoint (i, info); info->perf_single_step = false; } + +out: +preempt_enable (); }static bool is_larx_stcx_instr (int type)
Signature · 1 line
2.41.0
PATCH 2/3 powerpc/watchpoint: Disable pagefaults when getting user instruction
In reply to Benjamin GrayThis is called in an atomic context, so is not allowed to sleep if a user page needs to be faulted in and has nowhere it can be deferred to. The pagefault_disabled() function is documented as preventing user access methods from sleeping.
In practice the page will be mapped in nearly always because we are reading the instruction that just triggered the watchpoint trap.
--- arch/powerpc/kernel/hw_breakpoint_constraints.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
arch/powerpc/kernel/hw_breakpoint_constraints.c +6 -1
@@ -131,8 +131,13 @@ void wp_get_instr_detail(struct pt_regs *regs, ppc_inst_t *instr, int *type, int *size, unsigned long *ea) { struct instruction_op op; +int err; -if (__get_user_instr (*instr, (void __user *)regs->nip)) +pagefault_disable (); + err =__get_user_instr (*instr, (void __user *)regs->nip); +pagefault_enable (); + +if (err)return ;analyse_instr (&op, regs, *instr);
Signature · 1 line
2.41.0
PATCH 3/3 powerpc/watchpoints: Annotate atomic context in more places
In reply to Benjamin GrayIt can be easy to miss that the notifier mechanism invokes the callbacks in an atomic context, so add some comments to that effect on the two handlers we register here.
--- arch/powerpc/kernel/hw_breakpoint.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/powerpc/kernel/hw_breakpoint.c +9 -0
@@ -368,6 +368,11 @@ static void handle_p10dd1_spurious_exception(struct perf_event **bp, } } +/* +* Handle a DABR or DAWR exception. +* +* Called in atomic context. +*/ int hw_breakpoint_handler (struct die_args *args) {bool err = false;
@@ -495,6 +500,8 @@ NOKPROBE_SYMBOL(hw_breakpoint_handler);/* * Handle single-step exceptions following a DABR hit. +* +* Called in atomic context. */ static int single_step_dabr_instruction (struct die_args *args) {
@@ -546,6 +553,8 @@ NOKPROBE_SYMBOL(single_step_dabr_instruction);/* * Handle debug exception notifications. +* +* Called in atomic context. */ int hw_breakpoint_exceptions_notify (struct notifier_block *unused,unsigned long val,void *data)
Signature · 1 line
2.41.0
Quoted 9 lines · Benjamin Gray
When enabling debug config options relating to preemption, several bugs appear in the kernel log. With this series applied, the breakpoint code no longer prints bugs when running the powerpc/ptrace selftests.
Benjamin Gray (3):
powerpc/watchpoints: Disable preemption inthread_change_pc()powerpc/watchpoint: Disable pagefaults when getting user instruction powerpc/watchpoints: Annotate atomic context in more places
Quoted 6 lines
arch/powerpc/kernel/hw_breakpoint.c | 16 +++++++++++++++- arch/powerpc/kernel/hw_breakpoint_constraints.c | 7 ++++++- 2 files changed, 21 insertions(+), 2 deletions(-)--
2.41.0
The particular config is below, used by appending to a ppc64le_guest_defconfig. Not all options are relevant. Tested on a Power8 and Power10 machine (1 and 2 watchpoints).
CONFIG_LOCALVERSION="-watchpoint-sleep"CONFIG_GENERIC_IRQ_DEBUGFS=yCONFIG_PREEMPT=yCONFIG_PRINTK_INDEX=yCONFIG_CGROUP_DEBUG=yCONFIG_PPC_KUAP_DEBUG=yCONFIG_SCOM_DEBUGFS=yCONFIG_UDBG_RTAS_CONSOLE=yCONFIG_RELOCATABLE_TEST=yCONFIG_PM_DEBUG=yCONFIG_PM_ADVANCED_DEBUG=yCONFIG_STATIC_KEYS_SELFTEST=yCONFIG_MODULE_DEBUG=yCONFIG_MODULE_STATS=yCONFIG_MODULE_DEBUG_AUTOLOAD_DUPS_TRACE=yCONFIG_CMA_DEBUGFS=yCONFIG_CMA_SYSFS=yCONFIG_PERCPU_STATS=yCONFIG_USERFAULTFD=yCONFIG_VALIDATE_FS_PARSER=yCONFIG_EXT4_DEBUG=yCONFIG_HARDENED_USERCOPY=yCONFIG_FORTIFY_SOURCE=yCONFIG_DYNAMIC_DEBUG=yCONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=yCONFIG_DEBUG_INFO_SPLIT=yCONFIG_GDB_SCRIPTS=yCONFIG_READABLE_ASM=yCONFIG_NET_DEV_REFCNT_TRACKER=yCONFIG_NET_NS_REFCNT_TRACKER=yCONFIG_DEBUG_NET=yCONFIG_DEBUG_PAGEALLOC=yCONFIG_SLUB_DEBUG_ON=yCONFIG_PTDUMP_DEBUGFS=yCONFIG_DEBUG_KMEMLEAK=yCONFIG_PER_VMA_LOCK_STATS=yCONFIG_DEBUG_OBJECTS=yCONFIG_DEBUG_OBJECTS_SELFTEST=yCONFIG_DEBUG_OBJECTS_FREE=yCONFIG_DEBUG_OBJECTS_TIMERS=yCONFIG_DEBUG_OBJECTS_WORK=yCONFIG_DEBUG_OBJECTS_RCU_HEAD=yCONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=yCONFIG_SHRINKER_DEBUG=yCONFIG_SCHED_STACK_END_CHECK=yCONFIG_DEBUG_VM=yCONFIG_DEBUG_VM_MAPLE_TREE=yCONFIG_DEBUG_VM_RB=yCONFIG_DEBUG_VM_PGFLAGS=yCONFIG_DEBUG_VM_PGTABLE=yCONFIG_DEBUG_VIRTUAL=yCONFIG_DEBUG_PER_CPU_MAPS=yCONFIG_DEBUG_SHIRQ=yCONFIG_WQ_WATCHDOG=yCONFIG_DEBUG_TIMEKEEPING=yCONFIG_DEBUG_PREEMPT=yCONFIG_PROVE_LOCKING=yCONFIG_LOCK_STAT=yCONFIG_DEBUG_ATOMIC_SLEEP=yCONFIG_DEBUG_LOCKING_API_SELFTESTS=yCONFIG_CSD_LOCK_WAIT_DEBUG=yCONFIG_DEBUG_IRQFLAGS=yCONFIG_WARN_ALL_UNSEEDED_RANDOM=yCONFIG_DEBUG_NOTIFIERS=yCONFIG_DEBUG_CREDENTIALS=yCONFIG_RCU_CPU_STALL_CPUTIME=yCONFIG_RCU_EQS_DEBUG=yCONFIG_DEBUG_WQ_FORCE_RR_CPU=yCONFIG_CPU_HOTPLUG_STATE_CONTROL=yCONFIG_LATENCYTOP=yCONFIG_PPC_IRQ_SOFT_MASK_DEBUG=yCONFIG_PPC_RFI_SRR_DEBUG=y
Michael Ellerman
AppliedQuoted 10 lines · Benjamin Gray
When enabling debug config options relating to preemption, several bugs appear in the kernel log. With this series applied, the breakpoint code no longer prints bugs when running the powerpc/ptrace selftests.
Benjamin Gray (3):
powerpc/watchpoints: Disable preemption inthread_change_pc()powerpc/watchpoint: Disable pagefaults when getting user instruction powerpc/watchpoints: Annotate atomic context in more places[...]
Applied to powerpc/fixes.
[1/3] powerpc/watchpoints: Disable preemption in thread_change_pc()
https://git.kernel.org/powerpc/c/cc879ab3ce39bc39f9b1d238b283f43a5f6f957d [2/3] powerpc/watchpoint: Disable pagefaults when getting user instruction https://git.kernel.org/powerpc/c/3241f260eb830d27d09cc604690ec24533fdb433 [3/3] powerpc/watchpoints: Annotate atomic context in more places https://git.kernel.org/powerpc/c/27646b2e02b096a6936b3e3b6ba334ae20763eab
cheers