Files
opensbi/include/sbi/sbi_dbtr.h
T
David E. Garcia Porras 27d9545384 lib: sbi: dbtr: add platform device for per-slot trigger capabilities
The tinfo probe only discovers trigger types; WARL fields tied off
inside an implemented trigger CSR (e.g. an mcontrol6 trigger without
load/store address match) are not discoverable. sbi_alloc_trigger()
also selects the first free trigger slot irrespective of the requested
trigger type or configuration. Unsupported configurations are thus
silently dropped by the hardware while SBI reports success, where SBI
v3.0 sections 19.4 / 19.5 require SBI_ERR_NOT_SUPPORTED.

Add an optional platform device, struct sbi_dbtr_device, with a
trigger_supported(idx, tdata1, tdata2, tdata3) callback reporting
whether the trigger slot selected by idx (the tselect value) supports
a given configuration. Use it, together with the probed per-slot
type_mask, to:

  - allocate only trigger slots supporting the requested configuration
    (new dbtr_find_free_slot() helper)
  - reject unsupportable install/update requests with
    SBI_ERR_NOT_SUPPORTED
  - count only supporting slots in sbi_dbtr_num_trig() (SBI v3.0
    section 19.1)

The install path now dry-runs the allocation of the whole batch before
programming any trigger, so a partially-installed batch is never left
behind. Without a registered device, only the type matching applies (unchanged behavior).

Fixes: 97f234f15c ("lib: sbi: Introduce the SBI debug triggers extension support")
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260727183041.258377-2-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2026-09-01 10:36:07 +05:30

135 lines
3.6 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2023 Ventana Micro Systems, Inc.
*
* Authors:
* Himanshu Chauhan <hchauhan@ventanamicro.com>
*/
#ifndef __SBI_DBTR_H__
#define __SBI_DBTR_H__
#include <sbi/riscv_dbtr.h>
#include <sbi/sbi_types.h>
struct sbi_domain;
enum {
RV_DBTR_DECLARE_BIT(TS, MAPPED, 0), /* trigger mapped to hw trigger */
RV_DBTR_DECLARE_BIT(TS, U, 1),
RV_DBTR_DECLARE_BIT(TS, S, 2),
RV_DBTR_DECLARE_BIT(TS, VU, 3),
RV_DBTR_DECLARE_BIT(TS, VS, 4),
RV_DBTR_DECLARE_BIT(TS, HAVE_TRIG, 5), /* H/w dbtr details available */
RV_DBTR_DECLARE_BIT(TS, HW_IDX, 8), /* Hardware index of trigger */
};
enum {
RV_DBTR_DECLARE_BIT_MASK(TS, MAPPED, 1),
RV_DBTR_DECLARE_BIT_MASK(TS, U, 1),
RV_DBTR_DECLARE_BIT_MASK(TS, S, 1),
RV_DBTR_DECLARE_BIT_MASK(TS, VU, 1),
RV_DBTR_DECLARE_BIT_MASK(TS, VS, 1),
RV_DBTR_DECLARE_BIT_MASK(TS, HAVE_TRIG, 1),
RV_DBTR_DECLARE_BIT_MASK(TS, HW_IDX, (__riscv_xlen-9)),
};
#if __riscv_xlen == 64
#define SBI_DBTR_SHMEM_INVALID_ADDR 0xFFFFFFFFFFFFFFFFUL
#elif __riscv_xlen == 32
#define SBI_DBTR_SHMEM_INVALID_ADDR 0xFFFFFFFFUL
#else
#error "Unexpected __riscv_xlen"
#endif
struct sbi_dbtr_shmem {
unsigned long phys_lo;
unsigned long phys_hi;
};
struct sbi_dbtr_trigger {
unsigned long index;
unsigned long type_mask;
unsigned long state;
unsigned long tdata1;
unsigned long tdata2;
unsigned long tdata3;
};
struct sbi_dbtr_data_msg {
unsigned long tstate;
unsigned long tdata1;
unsigned long tdata2;
unsigned long tdata3;
};
struct sbi_dbtr_id_msg {
unsigned long idx;
};
struct sbi_dbtr_hart_triggers_state {
struct sbi_dbtr_trigger triggers[RV_MAX_TRIGGERS];
struct sbi_dbtr_shmem shmem;
u32 total_trigs;
u32 available_trigs;
u32 hartid;
u32 probed;
};
/** Platform specific debug trigger operations */
struct sbi_dbtr_device {
char name[32];
bool (*trigger_supported)(unsigned long idx, unsigned long tdata1,
unsigned long tdata2, unsigned long tdata3);
};
const struct sbi_dbtr_device *sbi_dbtr_get_device(void);
void sbi_dbtr_set_device(const struct sbi_dbtr_device *dev);
#define TDATA1_GET_TYPE(_t1) \
EXTRACT_FIELD(_t1, RV_DBTR_BIT_MASK(TDATA1, TYPE))
/* Set the hardware index of trigger in logical trigger state */
#define SET_TRIG_HW_INDEX(_state, _idx) \
do { \
_state &= ~RV_DBTR_BIT_MASK(TS, HW_IDX); \
_state |= (((unsigned long)_idx \
<< RV_DBTR_BIT(TS, HW_IDX)) \
& RV_DBTR_BIT_MASK(TS, HW_IDX)); \
}while (0);
/** SBI shared mem messages layout */
union sbi_dbtr_shmem_entry {
struct sbi_dbtr_data_msg data;
struct sbi_dbtr_id_msg id;
};
#define SBI_DBTR_SHMEM_ALIGN_MASK ((__riscv_xlen / 8) - 1)
/** Initialize debug triggers */
int sbi_dbtr_init(struct sbi_scratch *scratch, bool coldboot);
/** SBI DBTR extension functions */
int sbi_dbtr_supported(void);
int sbi_dbtr_setup_shmem(const struct sbi_domain *dom, unsigned long smode,
unsigned long shmem_phys_lo,
unsigned long shmem_phys_hi);
int sbi_dbtr_num_trig(unsigned long trig_tdata1, unsigned long *out);
int sbi_dbtr_read_trig(unsigned long smode,
unsigned long trig_idx_base, unsigned long trig_count);
int sbi_dbtr_install_trig(unsigned long smode,
unsigned long trig_count, unsigned long *out);
int sbi_dbtr_uninstall_trig(unsigned long trig_idx_base,
unsigned long trig_idx_mask);
int sbi_dbtr_enable_trig(unsigned long trig_idx_base,
unsigned long trig_idx_mask);
int sbi_dbtr_update_trig(unsigned long smode,
unsigned long trig_count);
int sbi_dbtr_disable_trig(unsigned long trig_idx_base,
unsigned long trig_idx_mask);
int sbi_dbtr_get_total_triggers(void);
#endif