diff options
| -rw-r--r-- | arch/arm64/kernel/debug-monitors.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 8eef30f92651..253021ef2769 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c | |||
| @@ -271,20 +271,21 @@ static int single_step_handler(unsigned long addr, unsigned int esr, | |||
| 271 | * Use reader/writer locks instead of plain spinlock. | 271 | * Use reader/writer locks instead of plain spinlock. |
| 272 | */ | 272 | */ |
| 273 | static LIST_HEAD(break_hook); | 273 | static LIST_HEAD(break_hook); |
| 274 | static DEFINE_RWLOCK(break_hook_lock); | 274 | static DEFINE_SPINLOCK(break_hook_lock); |
| 275 | 275 | ||
| 276 | void register_break_hook(struct break_hook *hook) | 276 | void register_break_hook(struct break_hook *hook) |
| 277 | { | 277 | { |
| 278 | write_lock(&break_hook_lock); | 278 | spin_lock(&break_hook_lock); |
| 279 | list_add(&hook->node, &break_hook); | 279 | list_add_rcu(&hook->node, &break_hook); |
| 280 | write_unlock(&break_hook_lock); | 280 | spin_unlock(&break_hook_lock); |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | void unregister_break_hook(struct break_hook *hook) | 283 | void unregister_break_hook(struct break_hook *hook) |
| 284 | { | 284 | { |
| 285 | write_lock(&break_hook_lock); | 285 | spin_lock(&break_hook_lock); |
| 286 | list_del(&hook->node); | 286 | list_del_rcu(&hook->node); |
| 287 | write_unlock(&break_hook_lock); | 287 | spin_unlock(&break_hook_lock); |
| 288 | synchronize_rcu(); | ||
| 288 | } | 289 | } |
| 289 | 290 | ||
| 290 | static int call_break_hook(struct pt_regs *regs, unsigned int esr) | 291 | static int call_break_hook(struct pt_regs *regs, unsigned int esr) |
| @@ -292,11 +293,11 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr) | |||
| 292 | struct break_hook *hook; | 293 | struct break_hook *hook; |
| 293 | int (*fn)(struct pt_regs *regs, unsigned int esr) = NULL; | 294 | int (*fn)(struct pt_regs *regs, unsigned int esr) = NULL; |
| 294 | 295 | ||
| 295 | read_lock(&break_hook_lock); | 296 | rcu_read_lock(); |
| 296 | list_for_each_entry(hook, &break_hook, node) | 297 | list_for_each_entry_rcu(hook, &break_hook, node) |
| 297 | if ((esr & hook->esr_mask) == hook->esr_val) | 298 | if ((esr & hook->esr_mask) == hook->esr_val) |
| 298 | fn = hook->fn; | 299 | fn = hook->fn; |
| 299 | read_unlock(&break_hook_lock); | 300 | rcu_read_unlock(); |
| 300 | 301 | ||
| 301 | return fn ? fn(regs, esr) : DBG_HOOK_ERROR; | 302 | return fn ? fn(regs, esr) : DBG_HOOK_ERROR; |
| 302 | } | 303 | } |
