| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /* SPDX-License-Identifier: GPL-2.0 */
- /*
- * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
- */
- #ifndef __ASM_HW_BREAKPOINT_H
- #define __ASM_HW_BREAKPOINT_H
- #include <asm/loongarch.h>
- #ifdef __KERNEL__
- /* Breakpoint */
- #define LOONGARCH_BREAKPOINT_EXECUTE (0 << 0)
- /* Watchpoints */
- #define LOONGARCH_BREAKPOINT_LOAD (1 << 0)
- #define LOONGARCH_BREAKPOINT_STORE (1 << 1)
- struct arch_hw_breakpoint_ctrl {
- u32 __reserved : 28,
- len : 2,
- type : 2;
- };
- struct arch_hw_breakpoint {
- u64 address;
- u64 mask;
- struct arch_hw_breakpoint_ctrl ctrl;
- };
- /* Lengths */
- #define LOONGARCH_BREAKPOINT_LEN_1 0b11
- #define LOONGARCH_BREAKPOINT_LEN_2 0b10
- #define LOONGARCH_BREAKPOINT_LEN_4 0b01
- #define LOONGARCH_BREAKPOINT_LEN_8 0b00
- /*
- * Limits.
- * Changing these will require modifications to the register accessors.
- */
- #define LOONGARCH_MAX_BRP 14
- #define LOONGARCH_MAX_WRP 14
- /* Virtual debug register bases. */
- #define CSR_CFG_ADDR 0
- #define CSR_CFG_MASK (CSR_CFG_ADDR + LOONGARCH_MAX_BRP)
- #define CSR_CFG_CTRL (CSR_CFG_MASK + LOONGARCH_MAX_BRP)
- #define CSR_CFG_ASID (CSR_CFG_CTRL + LOONGARCH_MAX_WRP)
- /* Debug register names. */
- #define LOONGARCH_CSR_NAME_ADDR ADDR
- #define LOONGARCH_CSR_NAME_MASK MASK
- #define LOONGARCH_CSR_NAME_CTRL CTRL
- #define LOONGARCH_CSR_NAME_ASID ASID
- /* Accessor macros for the debug registers. */
- #define LOONGARCH_CSR_WATCH_READ(N, REG, T, VAL) \
- do { \
- if (T == 0) \
- VAL = csr_read64(LOONGARCH_CSR_##IB##N##REG); \
- else \
- VAL = csr_read64(LOONGARCH_CSR_##DB##N##REG); \
- } while (0)
- #define LOONGARCH_CSR_WATCH_WRITE(N, REG, T, VAL) \
- do { \
- if (T == 0) \
- csr_write64(VAL, LOONGARCH_CSR_##IB##N##REG); \
- else \
- csr_write64(VAL, LOONGARCH_CSR_##DB##N##REG); \
- } while (0)
- /* Exact number */
- #define CSR_FWPC_NUM 0x3f
- #define CSR_MWPC_NUM 0x3f
- #define CTRL_PLV_ENABLE 0x1e
- #define CTRL_PLV0_ENABLE 0x02
- #define CTRL_PLV3_ENABLE 0x10
- #define MWPnCFG3_LoadEn 8
- #define MWPnCFG3_StoreEn 9
- #define MWPnCFG3_Type_mask 0x3
- #define MWPnCFG3_Size_mask 0x3
- static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
- {
- return (ctrl.len << 10) | (ctrl.type << 8);
- }
- static inline void decode_ctrl_reg(u32 reg, struct arch_hw_breakpoint_ctrl *ctrl)
- {
- reg >>= 8;
- ctrl->type = reg & MWPnCFG3_Type_mask;
- reg >>= 2;
- ctrl->len = reg & MWPnCFG3_Size_mask;
- }
- struct task_struct;
- struct notifier_block;
- struct perf_event;
- struct perf_event_attr;
- extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
- int *gen_len, int *gen_type);
- extern int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw);
- extern int hw_breakpoint_arch_parse(struct perf_event *bp,
- const struct perf_event_attr *attr,
- struct arch_hw_breakpoint *hw);
- extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
- unsigned long val, void *data);
- extern int arch_install_hw_breakpoint(struct perf_event *bp);
- extern void arch_uninstall_hw_breakpoint(struct perf_event *bp);
- extern int hw_breakpoint_slots(int type);
- extern void hw_breakpoint_pmu_read(struct perf_event *bp);
- void breakpoint_handler(struct pt_regs *regs);
- void watchpoint_handler(struct pt_regs *regs);
- #ifdef CONFIG_HAVE_HW_BREAKPOINT
- extern void ptrace_hw_copy_thread(struct task_struct *task);
- extern void hw_breakpoint_thread_switch(struct task_struct *next);
- #else
- static inline void ptrace_hw_copy_thread(struct task_struct *task)
- {
- }
- static inline void hw_breakpoint_thread_switch(struct task_struct *next)
- {
- }
- #endif
- /* Determine number of BRP registers available. */
- static inline int get_num_brps(void)
- {
- return csr_read32(LOONGARCH_CSR_FWPC) & CSR_FWPC_NUM;
- }
- /* Determine number of WRP registers available. */
- static inline int get_num_wrps(void)
- {
- return csr_read32(LOONGARCH_CSR_MWPC) & CSR_MWPC_NUM;
- }
- #endif /* __KERNEL__ */
- #endif /* __ASM_BREAKPOINT_H */
|