Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'loongarch-fixes-6.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson

Pull LoongArch fixes from Huacai Chen:
"Some hw breakpoint fixes, an objtool build warnging fix, and a trivial
cleanup"

* tag 'loongarch-fixes-6.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
LoongArch: KVM: Remove an unneeded semicolon
LoongArch: Fix multiple hardware watchpoint issues
LoongArch: Trigger user-space watchpoints correctly
LoongArch: Fix watchpoint setting error
LoongArch: Only allow OBJTOOL & ORC unwinder if toolchain supports -mthin-add-sub

+91 -64
+4 -1
arch/loongarch/Kconfig
··· 143 143 select HAVE_LIVEPATCH 144 144 select HAVE_MOD_ARCH_SPECIFIC 145 145 select HAVE_NMI 146 - select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS 146 + select HAVE_OBJTOOL if AS_HAS_EXPLICIT_RELOCS && AS_HAS_THIN_ADD_SUB && !CC_IS_CLANG 147 147 select HAVE_PCI 148 148 select HAVE_PERF_EVENTS 149 149 select HAVE_PERF_REGS ··· 260 260 261 261 config AS_HAS_FCSR_CLASS 262 262 def_bool $(as-instr,movfcsr2gr \$t0$(comma)\$fcsr0) 263 + 264 + config AS_HAS_THIN_ADD_SUB 265 + def_bool $(cc-option,-Wa$(comma)-mthin-add-sub) 263 266 264 267 config AS_HAS_LSX_EXTENSION 265 268 def_bool $(as-instr,vld \$vr0$(comma)\$a0$(comma)0)
+1
arch/loongarch/Kconfig.debug
··· 28 28 29 29 config UNWINDER_ORC 30 30 bool "ORC unwinder" 31 + depends on HAVE_OBJTOOL 31 32 select OBJTOOL 32 33 help 33 34 This option enables the ORC (Oops Rewind Capability) unwinder for
+3 -1
arch/loongarch/include/asm/hw_breakpoint.h
··· 75 75 #define CSR_MWPC_NUM 0x3f 76 76 77 77 #define CTRL_PLV_ENABLE 0x1e 78 + #define CTRL_PLV0_ENABLE 0x02 79 + #define CTRL_PLV3_ENABLE 0x10 78 80 79 81 #define MWPnCFG3_LoadEn 8 80 82 #define MWPnCFG3_StoreEn 9 ··· 103 101 struct perf_event_attr; 104 102 105 103 extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, 106 - int *gen_len, int *gen_type, int *offset); 104 + int *gen_len, int *gen_type); 107 105 extern int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw); 108 106 extern int hw_breakpoint_arch_parse(struct perf_event *bp, 109 107 const struct perf_event_attr *attr,
+55 -41
arch/loongarch/kernel/hw_breakpoint.c
··· 174 174 static int hw_breakpoint_control(struct perf_event *bp, 175 175 enum hw_breakpoint_ops ops) 176 176 { 177 - u32 ctrl; 177 + u32 ctrl, privilege; 178 178 int i, max_slots, enable; 179 + struct pt_regs *regs; 179 180 struct perf_event **slots; 180 181 struct arch_hw_breakpoint *info = counter_arch_bp(bp); 182 + 183 + if (arch_check_bp_in_kernelspace(info)) 184 + privilege = CTRL_PLV0_ENABLE; 185 + else 186 + privilege = CTRL_PLV3_ENABLE; 187 + 188 + /* Whether bp belongs to a task. */ 189 + if (bp->hw.target) 190 + regs = task_pt_regs(bp->hw.target); 181 191 182 192 if (info->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) { 183 193 /* Breakpoint */ ··· 207 197 switch (ops) { 208 198 case HW_BREAKPOINT_INSTALL: 209 199 /* Set the FWPnCFG/MWPnCFG 1~4 register. */ 210 - write_wb_reg(CSR_CFG_ADDR, i, 0, info->address); 211 - write_wb_reg(CSR_CFG_ADDR, i, 1, info->address); 212 - write_wb_reg(CSR_CFG_MASK, i, 0, info->mask); 213 - write_wb_reg(CSR_CFG_MASK, i, 1, info->mask); 214 - write_wb_reg(CSR_CFG_ASID, i, 0, 0); 215 - write_wb_reg(CSR_CFG_ASID, i, 1, 0); 216 200 if (info->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) { 217 - write_wb_reg(CSR_CFG_CTRL, i, 0, CTRL_PLV_ENABLE); 201 + write_wb_reg(CSR_CFG_ADDR, i, 0, info->address); 202 + write_wb_reg(CSR_CFG_MASK, i, 0, info->mask); 203 + write_wb_reg(CSR_CFG_ASID, i, 0, 0); 204 + write_wb_reg(CSR_CFG_CTRL, i, 0, privilege); 218 205 } else { 206 + write_wb_reg(CSR_CFG_ADDR, i, 1, info->address); 207 + write_wb_reg(CSR_CFG_MASK, i, 1, info->mask); 208 + write_wb_reg(CSR_CFG_ASID, i, 1, 0); 219 209 ctrl = encode_ctrl_reg(info->ctrl); 220 - write_wb_reg(CSR_CFG_CTRL, i, 1, ctrl | CTRL_PLV_ENABLE); 210 + write_wb_reg(CSR_CFG_CTRL, i, 1, ctrl | privilege); 221 211 } 222 212 enable = csr_read64(LOONGARCH_CSR_CRMD); 223 213 csr_write64(CSR_CRMD_WE | enable, LOONGARCH_CSR_CRMD); 214 + if (bp->hw.target) 215 + regs->csr_prmd |= CSR_PRMD_PWE; 224 216 break; 225 217 case HW_BREAKPOINT_UNINSTALL: 226 218 /* Reset the FWPnCFG/MWPnCFG 1~4 register. */ 227 - write_wb_reg(CSR_CFG_ADDR, i, 0, 0); 228 - write_wb_reg(CSR_CFG_ADDR, i, 1, 0); 229 - write_wb_reg(CSR_CFG_MASK, i, 0, 0); 230 - write_wb_reg(CSR_CFG_MASK, i, 1, 0); 231 - write_wb_reg(CSR_CFG_CTRL, i, 0, 0); 232 - write_wb_reg(CSR_CFG_CTRL, i, 1, 0); 233 - write_wb_reg(CSR_CFG_ASID, i, 0, 0); 234 - write_wb_reg(CSR_CFG_ASID, i, 1, 0); 219 + if (info->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) { 220 + write_wb_reg(CSR_CFG_ADDR, i, 0, 0); 221 + write_wb_reg(CSR_CFG_MASK, i, 0, 0); 222 + write_wb_reg(CSR_CFG_CTRL, i, 0, 0); 223 + write_wb_reg(CSR_CFG_ASID, i, 0, 0); 224 + } else { 225 + write_wb_reg(CSR_CFG_ADDR, i, 1, 0); 226 + write_wb_reg(CSR_CFG_MASK, i, 1, 0); 227 + write_wb_reg(CSR_CFG_CTRL, i, 1, 0); 228 + write_wb_reg(CSR_CFG_ASID, i, 1, 0); 229 + } 230 + if (bp->hw.target) 231 + regs->csr_prmd &= ~CSR_PRMD_PWE; 235 232 break; 236 233 } 237 234 ··· 300 283 * to generic breakpoint descriptions. 301 284 */ 302 285 int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, 303 - int *gen_len, int *gen_type, int *offset) 286 + int *gen_len, int *gen_type) 304 287 { 305 288 /* Type */ 306 289 switch (ctrl.type) { ··· 319 302 default: 320 303 return -EINVAL; 321 304 } 322 - 323 - if (!ctrl.len) 324 - return -EINVAL; 325 - 326 - *offset = __ffs(ctrl.len); 327 305 328 306 /* Len */ 329 307 switch (ctrl.len) { ··· 398 386 struct arch_hw_breakpoint *hw) 399 387 { 400 388 int ret; 401 - u64 alignment_mask, offset; 389 + u64 alignment_mask; 402 390 403 391 /* Build the arch_hw_breakpoint. */ 404 392 ret = arch_build_bp_info(bp, attr, hw); 405 393 if (ret) 406 394 return ret; 407 395 408 - if (hw->ctrl.type != LOONGARCH_BREAKPOINT_EXECUTE) 409 - alignment_mask = 0x7; 410 - else 396 + if (hw->ctrl.type == LOONGARCH_BREAKPOINT_EXECUTE) { 411 397 alignment_mask = 0x3; 412 - offset = hw->address & alignment_mask; 413 - 414 - hw->address &= ~alignment_mask; 415 - hw->ctrl.len <<= offset; 398 + hw->address &= ~alignment_mask; 399 + } 416 400 417 401 return 0; 418 402 } ··· 479 471 slots = this_cpu_ptr(bp_on_reg); 480 472 481 473 for (i = 0; i < boot_cpu_data.watch_ireg_count; ++i) { 482 - bp = slots[i]; 483 - if (bp == NULL) 484 - continue; 485 - perf_bp_event(bp, regs); 474 + if ((csr_read32(LOONGARCH_CSR_FWPS) & (0x1 << i))) { 475 + bp = slots[i]; 476 + if (bp == NULL) 477 + continue; 478 + perf_bp_event(bp, regs); 479 + csr_write32(0x1 << i, LOONGARCH_CSR_FWPS); 480 + update_bp_registers(regs, 0, 0); 481 + } 486 482 } 487 - update_bp_registers(regs, 0, 0); 488 483 } 489 484 NOKPROBE_SYMBOL(breakpoint_handler); 490 485 ··· 499 488 slots = this_cpu_ptr(wp_on_reg); 500 489 501 490 for (i = 0; i < boot_cpu_data.watch_dreg_count; ++i) { 502 - wp = slots[i]; 503 - if (wp == NULL) 504 - continue; 505 - perf_bp_event(wp, regs); 491 + if ((csr_read32(LOONGARCH_CSR_MWPS) & (0x1 << i))) { 492 + wp = slots[i]; 493 + if (wp == NULL) 494 + continue; 495 + perf_bp_event(wp, regs); 496 + csr_write32(0x1 << i, LOONGARCH_CSR_MWPS); 497 + update_bp_registers(regs, 0, 1); 498 + } 506 499 } 507 - update_bp_registers(regs, 0, 1); 508 500 } 509 501 NOKPROBE_SYMBOL(watchpoint_handler); 510 502
+27 -20
arch/loongarch/kernel/ptrace.c
··· 494 494 struct arch_hw_breakpoint_ctrl ctrl, 495 495 struct perf_event_attr *attr) 496 496 { 497 - int err, len, type, offset; 497 + int err, len, type; 498 498 499 - err = arch_bp_generic_fields(ctrl, &len, &type, &offset); 499 + err = arch_bp_generic_fields(ctrl, &len, &type); 500 500 if (err) 501 501 return err; 502 502 503 - switch (note_type) { 504 - case NT_LOONGARCH_HW_BREAK: 505 - if ((type & HW_BREAKPOINT_X) != type) 506 - return -EINVAL; 507 - break; 508 - case NT_LOONGARCH_HW_WATCH: 509 - if ((type & HW_BREAKPOINT_RW) != type) 510 - return -EINVAL; 511 - break; 512 - default: 513 - return -EINVAL; 514 - } 515 - 516 503 attr->bp_len = len; 517 504 attr->bp_type = type; 518 - attr->bp_addr += offset; 519 505 520 506 return 0; 521 507 } ··· 595 609 return PTR_ERR(bp); 596 610 597 611 attr = bp->attr; 598 - decode_ctrl_reg(uctrl, &ctrl); 599 - err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr); 600 - if (err) 601 - return err; 612 + 613 + switch (note_type) { 614 + case NT_LOONGARCH_HW_BREAK: 615 + ctrl.type = LOONGARCH_BREAKPOINT_EXECUTE; 616 + ctrl.len = LOONGARCH_BREAKPOINT_LEN_4; 617 + break; 618 + case NT_LOONGARCH_HW_WATCH: 619 + decode_ctrl_reg(uctrl, &ctrl); 620 + break; 621 + default: 622 + return -EINVAL; 623 + } 624 + 625 + if (uctrl & CTRL_PLV_ENABLE) { 626 + err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr); 627 + if (err) 628 + return err; 629 + attr.disabled = 0; 630 + } else { 631 + attr.disabled = 1; 632 + } 602 633 603 634 return modify_user_hw_breakpoint(bp, &attr); 604 635 } ··· 645 642 { 646 643 struct perf_event *bp; 647 644 struct perf_event_attr attr; 645 + 646 + /* Kernel-space address cannot be monitored by user-space */ 647 + if ((unsigned long)addr >= XKPRANGE) 648 + return -EINVAL; 648 649 649 650 bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); 650 651 if (IS_ERR(bp))
+1 -1
arch/loongarch/kvm/exit.c
··· 761 761 default: 762 762 ret = KVM_HCALL_INVALID_CODE; 763 763 break; 764 - }; 764 + } 765 765 766 766 kvm_write_reg(vcpu, LOONGARCH_GPR_A0, ret); 767 767 }