| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 3 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 4 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 5 | | - * (at your option) any later version. |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 8 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 9 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 10 | | - * GNU General Public License for more details. |
|---|
| 11 | | - * |
|---|
| 12 | | - * You should have received a copy of the GNU General Public License |
|---|
| 13 | | - * along with this program; if not, write to the Free Software |
|---|
| 14 | | - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 15 | 3 | * |
|---|
| 16 | 4 | * Copyright (C) 2007 Alan Stern |
|---|
| 17 | 5 | * Copyright (C) 2009 IBM Corporation |
|---|
| .. | .. |
|---|
| 44 | 32 | #include <asm/processor.h> |
|---|
| 45 | 33 | #include <asm/debugreg.h> |
|---|
| 46 | 34 | #include <asm/user.h> |
|---|
| 35 | +#include <asm/desc.h> |
|---|
| 36 | +#include <asm/tlbflush.h> |
|---|
| 47 | 37 | |
|---|
| 48 | 38 | /* Per cpu debug control register value */ |
|---|
| 49 | 39 | DEFINE_PER_CPU(unsigned long, cpu_dr7); |
|---|
| .. | .. |
|---|
| 109 | 99 | unsigned long *dr7; |
|---|
| 110 | 100 | int i; |
|---|
| 111 | 101 | |
|---|
| 102 | + lockdep_assert_irqs_disabled(); |
|---|
| 103 | + |
|---|
| 112 | 104 | for (i = 0; i < HBP_NUM; i++) { |
|---|
| 113 | 105 | struct perf_event **slot = this_cpu_ptr(&bp_per_reg[i]); |
|---|
| 114 | 106 | |
|---|
| .. | .. |
|---|
| 126 | 118 | |
|---|
| 127 | 119 | dr7 = this_cpu_ptr(&cpu_dr7); |
|---|
| 128 | 120 | *dr7 |= encode_dr7(i, info->len, info->type); |
|---|
| 121 | + |
|---|
| 122 | + /* |
|---|
| 123 | + * Ensure we first write cpu_dr7 before we set the DR7 register. |
|---|
| 124 | + * This ensures an NMI never see cpu_dr7 0 when DR7 is not. |
|---|
| 125 | + */ |
|---|
| 126 | + barrier(); |
|---|
| 129 | 127 | |
|---|
| 130 | 128 | set_debugreg(*dr7, 7); |
|---|
| 131 | 129 | if (info->mask) |
|---|
| .. | .. |
|---|
| 146 | 144 | void arch_uninstall_hw_breakpoint(struct perf_event *bp) |
|---|
| 147 | 145 | { |
|---|
| 148 | 146 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); |
|---|
| 149 | | - unsigned long *dr7; |
|---|
| 147 | + unsigned long dr7; |
|---|
| 150 | 148 | int i; |
|---|
| 149 | + |
|---|
| 150 | + lockdep_assert_irqs_disabled(); |
|---|
| 151 | 151 | |
|---|
| 152 | 152 | for (i = 0; i < HBP_NUM; i++) { |
|---|
| 153 | 153 | struct perf_event **slot = this_cpu_ptr(&bp_per_reg[i]); |
|---|
| .. | .. |
|---|
| 161 | 161 | if (WARN_ONCE(i == HBP_NUM, "Can't find any breakpoint slot")) |
|---|
| 162 | 162 | return; |
|---|
| 163 | 163 | |
|---|
| 164 | | - dr7 = this_cpu_ptr(&cpu_dr7); |
|---|
| 165 | | - *dr7 &= ~__encode_dr7(i, info->len, info->type); |
|---|
| 164 | + dr7 = this_cpu_read(cpu_dr7); |
|---|
| 165 | + dr7 &= ~__encode_dr7(i, info->len, info->type); |
|---|
| 166 | 166 | |
|---|
| 167 | | - set_debugreg(*dr7, 7); |
|---|
| 167 | + set_debugreg(dr7, 7); |
|---|
| 168 | 168 | if (info->mask) |
|---|
| 169 | 169 | set_dr_addr_mask(0, i); |
|---|
| 170 | + |
|---|
| 171 | + /* |
|---|
| 172 | + * Ensure the write to cpu_dr7 is after we've set the DR7 register. |
|---|
| 173 | + * This ensures an NMI never see cpu_dr7 0 when DR7 is not. |
|---|
| 174 | + */ |
|---|
| 175 | + barrier(); |
|---|
| 176 | + |
|---|
| 177 | + this_cpu_write(cpu_dr7, dr7); |
|---|
| 170 | 178 | } |
|---|
| 171 | 179 | |
|---|
| 172 | 180 | static int arch_bp_generic_len(int x86_len) |
|---|
| .. | .. |
|---|
| 239 | 247 | return (va >= TASK_SIZE_MAX) || ((va + len - 1) >= TASK_SIZE_MAX); |
|---|
| 240 | 248 | } |
|---|
| 241 | 249 | |
|---|
| 250 | +/* |
|---|
| 251 | + * Checks whether the range [addr, end], overlaps the area [base, base + size). |
|---|
| 252 | + */ |
|---|
| 253 | +static inline bool within_area(unsigned long addr, unsigned long end, |
|---|
| 254 | + unsigned long base, unsigned long size) |
|---|
| 255 | +{ |
|---|
| 256 | + return end >= base && addr < (base + size); |
|---|
| 257 | +} |
|---|
| 258 | + |
|---|
| 259 | +/* |
|---|
| 260 | + * Checks whether the range from addr to end, inclusive, overlaps the fixed |
|---|
| 261 | + * mapped CPU entry area range or other ranges used for CPU entry. |
|---|
| 262 | + */ |
|---|
| 263 | +static inline bool within_cpu_entry(unsigned long addr, unsigned long end) |
|---|
| 264 | +{ |
|---|
| 265 | + int cpu; |
|---|
| 266 | + |
|---|
| 267 | + /* CPU entry erea is always used for CPU entry */ |
|---|
| 268 | + if (within_area(addr, end, CPU_ENTRY_AREA_BASE, |
|---|
| 269 | + CPU_ENTRY_AREA_TOTAL_SIZE)) |
|---|
| 270 | + return true; |
|---|
| 271 | + |
|---|
| 272 | + /* |
|---|
| 273 | + * When FSGSBASE is enabled, paranoid_entry() fetches the per-CPU |
|---|
| 274 | + * GSBASE value via __per_cpu_offset or pcpu_unit_offsets. |
|---|
| 275 | + */ |
|---|
| 276 | +#ifdef CONFIG_SMP |
|---|
| 277 | + if (within_area(addr, end, (unsigned long)__per_cpu_offset, |
|---|
| 278 | + sizeof(unsigned long) * nr_cpu_ids)) |
|---|
| 279 | + return true; |
|---|
| 280 | +#else |
|---|
| 281 | + if (within_area(addr, end, (unsigned long)&pcpu_unit_offsets, |
|---|
| 282 | + sizeof(pcpu_unit_offsets))) |
|---|
| 283 | + return true; |
|---|
| 284 | +#endif |
|---|
| 285 | + |
|---|
| 286 | + for_each_possible_cpu(cpu) { |
|---|
| 287 | + /* The original rw GDT is being used after load_direct_gdt() */ |
|---|
| 288 | + if (within_area(addr, end, (unsigned long)get_cpu_gdt_rw(cpu), |
|---|
| 289 | + GDT_SIZE)) |
|---|
| 290 | + return true; |
|---|
| 291 | + |
|---|
| 292 | + /* |
|---|
| 293 | + * cpu_tss_rw is not directly referenced by hardware, but |
|---|
| 294 | + * cpu_tss_rw is also used in CPU entry code, |
|---|
| 295 | + */ |
|---|
| 296 | + if (within_area(addr, end, |
|---|
| 297 | + (unsigned long)&per_cpu(cpu_tss_rw, cpu), |
|---|
| 298 | + sizeof(struct tss_struct))) |
|---|
| 299 | + return true; |
|---|
| 300 | + |
|---|
| 301 | + /* |
|---|
| 302 | + * cpu_tlbstate.user_pcid_flush_mask is used for CPU entry. |
|---|
| 303 | + * If a data breakpoint on it, it will cause an unwanted #DB. |
|---|
| 304 | + * Protect the full cpu_tlbstate structure to be sure. |
|---|
| 305 | + */ |
|---|
| 306 | + if (within_area(addr, end, |
|---|
| 307 | + (unsigned long)&per_cpu(cpu_tlbstate, cpu), |
|---|
| 308 | + sizeof(struct tlb_state))) |
|---|
| 309 | + return true; |
|---|
| 310 | + |
|---|
| 311 | + /* |
|---|
| 312 | + * When in guest (X86_FEATURE_HYPERVISOR), local_db_save() |
|---|
| 313 | + * will read per-cpu cpu_dr7 before clear dr7 register. |
|---|
| 314 | + */ |
|---|
| 315 | + if (within_area(addr, end, (unsigned long)&per_cpu(cpu_dr7, cpu), |
|---|
| 316 | + sizeof(cpu_dr7))) |
|---|
| 317 | + return true; |
|---|
| 318 | + } |
|---|
| 319 | + |
|---|
| 320 | + return false; |
|---|
| 321 | +} |
|---|
| 322 | + |
|---|
| 242 | 323 | static int arch_build_bp_info(struct perf_event *bp, |
|---|
| 243 | 324 | const struct perf_event_attr *attr, |
|---|
| 244 | 325 | struct arch_hw_breakpoint *hw) |
|---|
| 245 | 326 | { |
|---|
| 327 | + unsigned long bp_end; |
|---|
| 328 | + |
|---|
| 329 | + bp_end = attr->bp_addr + attr->bp_len - 1; |
|---|
| 330 | + if (bp_end < attr->bp_addr) |
|---|
| 331 | + return -EINVAL; |
|---|
| 332 | + |
|---|
| 333 | + /* |
|---|
| 334 | + * Prevent any breakpoint of any type that overlaps the CPU |
|---|
| 335 | + * entry area and data. This protects the IST stacks and also |
|---|
| 336 | + * reduces the chance that we ever find out what happens if |
|---|
| 337 | + * there's a data breakpoint on the GDT, IDT, or TSS. |
|---|
| 338 | + */ |
|---|
| 339 | + if (within_cpu_entry(attr->bp_addr, bp_end)) |
|---|
| 340 | + return -EINVAL; |
|---|
| 341 | + |
|---|
| 246 | 342 | hw->address = attr->bp_addr; |
|---|
| 247 | 343 | hw->mask = 0; |
|---|
| 248 | 344 | |
|---|
| .. | .. |
|---|
| 261 | 357 | * allow kernel breakpoints at all. |
|---|
| 262 | 358 | */ |
|---|
| 263 | 359 | if (attr->bp_addr >= TASK_SIZE_MAX) { |
|---|
| 264 | | -#ifdef CONFIG_KPROBES |
|---|
| 265 | 360 | if (within_kprobe_blacklist(attr->bp_addr)) |
|---|
| 266 | 361 | return -EINVAL; |
|---|
| 267 | | -#else |
|---|
| 268 | | - return -EINVAL; |
|---|
| 269 | | -#endif |
|---|
| 270 | 362 | } |
|---|
| 271 | 363 | |
|---|
| 272 | 364 | hw->type = X86_BREAKPOINT_EXECUTE; |
|---|
| .. | .. |
|---|
| 279 | 371 | hw->len = X86_BREAKPOINT_LEN_X; |
|---|
| 280 | 372 | return 0; |
|---|
| 281 | 373 | } |
|---|
| 374 | + fallthrough; |
|---|
| 282 | 375 | default: |
|---|
| 283 | 376 | return -EINVAL; |
|---|
| 284 | 377 | } |
|---|
| .. | .. |
|---|
| 371 | 464 | } |
|---|
| 372 | 465 | |
|---|
| 373 | 466 | /* |
|---|
| 374 | | - * Dump the debug register contents to the user. |
|---|
| 375 | | - * We can't dump our per cpu values because it |
|---|
| 376 | | - * may contain cpu wide breakpoint, something that |
|---|
| 377 | | - * doesn't belong to the current task. |
|---|
| 378 | | - * |
|---|
| 379 | | - * TODO: include non-ptrace user breakpoints (perf) |
|---|
| 380 | | - */ |
|---|
| 381 | | -void aout_dump_debugregs(struct user *dump) |
|---|
| 382 | | -{ |
|---|
| 383 | | - int i; |
|---|
| 384 | | - int dr7 = 0; |
|---|
| 385 | | - struct perf_event *bp; |
|---|
| 386 | | - struct arch_hw_breakpoint *info; |
|---|
| 387 | | - struct thread_struct *thread = ¤t->thread; |
|---|
| 388 | | - |
|---|
| 389 | | - for (i = 0; i < HBP_NUM; i++) { |
|---|
| 390 | | - bp = thread->ptrace_bps[i]; |
|---|
| 391 | | - |
|---|
| 392 | | - if (bp && !bp->attr.disabled) { |
|---|
| 393 | | - dump->u_debugreg[i] = bp->attr.bp_addr; |
|---|
| 394 | | - info = counter_arch_bp(bp); |
|---|
| 395 | | - dr7 |= encode_dr7(i, info->len, info->type); |
|---|
| 396 | | - } else { |
|---|
| 397 | | - dump->u_debugreg[i] = 0; |
|---|
| 398 | | - } |
|---|
| 399 | | - } |
|---|
| 400 | | - |
|---|
| 401 | | - dump->u_debugreg[4] = 0; |
|---|
| 402 | | - dump->u_debugreg[5] = 0; |
|---|
| 403 | | - dump->u_debugreg[6] = current->thread.debugreg6; |
|---|
| 404 | | - |
|---|
| 405 | | - dump->u_debugreg[7] = dr7; |
|---|
| 406 | | -} |
|---|
| 407 | | -EXPORT_SYMBOL_GPL(aout_dump_debugregs); |
|---|
| 408 | | - |
|---|
| 409 | | -/* |
|---|
| 410 | 467 | * Release the user breakpoints used by ptrace |
|---|
| 411 | 468 | */ |
|---|
| 412 | 469 | void flush_ptrace_hw_breakpoint(struct task_struct *tsk) |
|---|
| .. | .. |
|---|
| 419 | 476 | t->ptrace_bps[i] = NULL; |
|---|
| 420 | 477 | } |
|---|
| 421 | 478 | |
|---|
| 422 | | - t->debugreg6 = 0; |
|---|
| 479 | + t->virtual_dr6 = 0; |
|---|
| 423 | 480 | t->ptrace_dr7 = 0; |
|---|
| 424 | 481 | } |
|---|
| 425 | 482 | |
|---|
| .. | .. |
|---|
| 429 | 486 | set_debugreg(__this_cpu_read(cpu_debugreg[1]), 1); |
|---|
| 430 | 487 | set_debugreg(__this_cpu_read(cpu_debugreg[2]), 2); |
|---|
| 431 | 488 | set_debugreg(__this_cpu_read(cpu_debugreg[3]), 3); |
|---|
| 432 | | - set_debugreg(current->thread.debugreg6, 6); |
|---|
| 489 | + set_debugreg(DR6_RESERVED, 6); |
|---|
| 433 | 490 | set_debugreg(__this_cpu_read(cpu_dr7), 7); |
|---|
| 434 | 491 | } |
|---|
| 435 | 492 | EXPORT_SYMBOL_GPL(hw_breakpoint_restore); |
|---|
| .. | .. |
|---|
| 452 | 509 | */ |
|---|
| 453 | 510 | static int hw_breakpoint_handler(struct die_args *args) |
|---|
| 454 | 511 | { |
|---|
| 455 | | - int i, cpu, rc = NOTIFY_STOP; |
|---|
| 512 | + int i, rc = NOTIFY_STOP; |
|---|
| 456 | 513 | struct perf_event *bp; |
|---|
| 457 | | - unsigned long dr7, dr6; |
|---|
| 458 | 514 | unsigned long *dr6_p; |
|---|
| 515 | + unsigned long dr6; |
|---|
| 516 | + bool bpx; |
|---|
| 459 | 517 | |
|---|
| 460 | 518 | /* The DR6 value is pointed by args->err */ |
|---|
| 461 | 519 | dr6_p = (unsigned long *)ERR_PTR(args->err); |
|---|
| 462 | 520 | dr6 = *dr6_p; |
|---|
| 463 | 521 | |
|---|
| 464 | | - /* If it's a single step, TRAP bits are random */ |
|---|
| 465 | | - if (dr6 & DR_STEP) |
|---|
| 466 | | - return NOTIFY_DONE; |
|---|
| 467 | | - |
|---|
| 468 | 522 | /* Do an early return if no trap bits are set in DR6 */ |
|---|
| 469 | 523 | if ((dr6 & DR_TRAP_BITS) == 0) |
|---|
| 470 | 524 | return NOTIFY_DONE; |
|---|
| 471 | | - |
|---|
| 472 | | - get_debugreg(dr7, 7); |
|---|
| 473 | | - /* Disable breakpoints during exception handling */ |
|---|
| 474 | | - set_debugreg(0UL, 7); |
|---|
| 475 | | - /* |
|---|
| 476 | | - * Assert that local interrupts are disabled |
|---|
| 477 | | - * Reset the DRn bits in the virtualized register value. |
|---|
| 478 | | - * The ptrace trigger routine will add in whatever is needed. |
|---|
| 479 | | - */ |
|---|
| 480 | | - current->thread.debugreg6 &= ~DR_TRAP_BITS; |
|---|
| 481 | | - cpu = get_cpu(); |
|---|
| 482 | 525 | |
|---|
| 483 | 526 | /* Handle all the breakpoints that were triggered */ |
|---|
| 484 | 527 | for (i = 0; i < HBP_NUM; ++i) { |
|---|
| 485 | 528 | if (likely(!(dr6 & (DR_TRAP0 << i)))) |
|---|
| 486 | 529 | continue; |
|---|
| 487 | 530 | |
|---|
| 488 | | - /* |
|---|
| 489 | | - * The counter may be concurrently released but that can only |
|---|
| 490 | | - * occur from a call_rcu() path. We can then safely fetch |
|---|
| 491 | | - * the breakpoint, use its callback, touch its counter |
|---|
| 492 | | - * while we are in an rcu_read_lock() path. |
|---|
| 493 | | - */ |
|---|
| 494 | | - rcu_read_lock(); |
|---|
| 531 | + bp = this_cpu_read(bp_per_reg[i]); |
|---|
| 532 | + if (!bp) |
|---|
| 533 | + continue; |
|---|
| 495 | 534 | |
|---|
| 496 | | - bp = per_cpu(bp_per_reg[i], cpu); |
|---|
| 535 | + bpx = bp->hw.info.type == X86_BREAKPOINT_EXECUTE; |
|---|
| 536 | + |
|---|
| 537 | + /* |
|---|
| 538 | + * TF and data breakpoints are traps and can be merged, however |
|---|
| 539 | + * instruction breakpoints are faults and will be raised |
|---|
| 540 | + * separately. |
|---|
| 541 | + * |
|---|
| 542 | + * However DR6 can indicate both TF and instruction |
|---|
| 543 | + * breakpoints. In that case take TF as that has precedence and |
|---|
| 544 | + * delay the instruction breakpoint for the next exception. |
|---|
| 545 | + */ |
|---|
| 546 | + if (bpx && (dr6 & DR_STEP)) |
|---|
| 547 | + continue; |
|---|
| 548 | + |
|---|
| 497 | 549 | /* |
|---|
| 498 | 550 | * Reset the 'i'th TRAP bit in dr6 to denote completion of |
|---|
| 499 | 551 | * exception handling |
|---|
| 500 | 552 | */ |
|---|
| 501 | 553 | (*dr6_p) &= ~(DR_TRAP0 << i); |
|---|
| 502 | | - /* |
|---|
| 503 | | - * bp can be NULL due to lazy debug register switching |
|---|
| 504 | | - * or due to concurrent perf counter removing. |
|---|
| 505 | | - */ |
|---|
| 506 | | - if (!bp) { |
|---|
| 507 | | - rcu_read_unlock(); |
|---|
| 508 | | - break; |
|---|
| 509 | | - } |
|---|
| 510 | 554 | |
|---|
| 511 | 555 | perf_bp_event(bp, args->regs); |
|---|
| 512 | 556 | |
|---|
| .. | .. |
|---|
| 514 | 558 | * Set up resume flag to avoid breakpoint recursion when |
|---|
| 515 | 559 | * returning back to origin. |
|---|
| 516 | 560 | */ |
|---|
| 517 | | - if (bp->hw.info.type == X86_BREAKPOINT_EXECUTE) |
|---|
| 561 | + if (bpx) |
|---|
| 518 | 562 | args->regs->flags |= X86_EFLAGS_RF; |
|---|
| 519 | | - |
|---|
| 520 | | - rcu_read_unlock(); |
|---|
| 521 | 563 | } |
|---|
| 564 | + |
|---|
| 522 | 565 | /* |
|---|
| 523 | 566 | * Further processing in do_debug() is needed for a) user-space |
|---|
| 524 | 567 | * breakpoints (to generate signals) and b) when the system has |
|---|
| 525 | 568 | * taken exception due to multiple causes |
|---|
| 526 | 569 | */ |
|---|
| 527 | | - if ((current->thread.debugreg6 & DR_TRAP_BITS) || |
|---|
| 570 | + if ((current->thread.virtual_dr6 & DR_TRAP_BITS) || |
|---|
| 528 | 571 | (dr6 & (~DR_TRAP_BITS))) |
|---|
| 529 | 572 | rc = NOTIFY_DONE; |
|---|
| 530 | | - |
|---|
| 531 | | - set_debugreg(dr7, 7); |
|---|
| 532 | | - put_cpu(); |
|---|
| 533 | 573 | |
|---|
| 534 | 574 | return rc; |
|---|
| 535 | 575 | } |
|---|