Skip to content

Commit

Permalink
target/riscv: Add sscofpmf extension support
Browse files Browse the repository at this point in the history
The Sscofpmf ('Ss' for Privileged arch and Supervisor-level extensions,
and 'cofpmf' for Count OverFlow and Privilege Mode Filtering)
extension allows the perf to handle overflow interrupts and filtering
support. This patch provides a framework for programmable
counters to leverage the extension. As the extension doesn't have any
provision for the overflow bit for fixed counters, the fixed events
can also be monitoring using programmable counters. The underlying
counters for cycle and instruction counters are always running. Thus,
a separate timer device is programmed to handle the overflow.

Tested-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Atish Patra <atish.patra@wdc.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Message-Id: <20220824221701.41932-2-atishp@rivosinc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
  • Loading branch information
atishp04 authored and alistair23 committed Sep 7, 2022
1 parent 3ec0fe1 commit 1466448
Show file tree
Hide file tree
Showing 7 changed files with 623 additions and 11 deletions.
12 changes: 12 additions & 0 deletions target/riscv/cpu.c
Expand Up @@ -22,6 +22,7 @@
#include "qemu/ctype.h"
#include "qemu/log.h"
#include "cpu.h"
#include "pmu.h"
#include "internals.h"
#include "time_helper.h"
#include "exec/exec-all.h"
Expand Down Expand Up @@ -102,6 +103,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
Expand Down Expand Up @@ -889,6 +891,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_misa(env, env->misa_mxl, ext);
}

#ifndef CONFIG_USER_ONLY
if (cpu->cfg.pmu_num) {
if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
riscv_pmu_timer_cb, cpu);
}
}
#endif

riscv_cpu_register_gdb_regs_for_features(cs);

qemu_init_vcpu(cs);
Expand Down Expand Up @@ -993,6 +1004,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false),
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true),
Expand Down
25 changes: 25 additions & 0 deletions target/riscv/cpu.h
Expand Up @@ -136,6 +136,8 @@ typedef struct PMUCTRState {
/* Snapshort value of a counter in RV32 */
target_ulong mhpmcounterh_prev;
bool started;
/* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */
target_ulong irq_overflow_left;
} PMUCTRState;

struct CPUArchState {
Expand Down Expand Up @@ -301,6 +303,9 @@ struct CPUArchState {
/* PMU event selector configured values. First three are unused*/
target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];

/* PMU event selector configured values for RV32*/
target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS];

target_ulong sscratch;
target_ulong mscratch;

Expand Down Expand Up @@ -447,6 +452,7 @@ struct RISCVCPUConfig {
bool ext_zmmul;
bool ext_smaia;
bool ext_ssaia;
bool ext_sscofpmf;
bool rvv_ta_all_1s;
bool rvv_ma_all_1s;

Expand Down Expand Up @@ -493,6 +499,12 @@ struct ArchCPU {

/* Configuration Settings */
RISCVCPUConfig cfg;

QEMUTimer *pmu_timer;
/* A bitmask of Available programmable counters */
uint32_t pmu_avail_ctrs;
/* Mapping of events to counters */
GHashTable *pmu_event_ctr_map;
};

static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
Expand Down Expand Up @@ -753,6 +765,19 @@ enum {
CSR_TABLE_SIZE = 0x1000
};

/**
* The event id are encoded based on the encoding specified in the
* SBI specification v0.3
*/

enum riscv_pmu_event_idx {
RISCV_PMU_EVENT_HW_CPU_CYCLES = 0x01,
RISCV_PMU_EVENT_HW_INSTRUCTIONS = 0x02,
RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS = 0x10019,
RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS = 0x1001B,
RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021,
};

/* CSR function table */
extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];

Expand Down
55 changes: 55 additions & 0 deletions target/riscv/cpu_bits.h
Expand Up @@ -390,6 +390,37 @@
#define CSR_MHPMEVENT29 0x33d
#define CSR_MHPMEVENT30 0x33e
#define CSR_MHPMEVENT31 0x33f

#define CSR_MHPMEVENT3H 0x723
#define CSR_MHPMEVENT4H 0x724
#define CSR_MHPMEVENT5H 0x725
#define CSR_MHPMEVENT6H 0x726
#define CSR_MHPMEVENT7H 0x727
#define CSR_MHPMEVENT8H 0x728
#define CSR_MHPMEVENT9H 0x729
#define CSR_MHPMEVENT10H 0x72a
#define CSR_MHPMEVENT11H 0x72b
#define CSR_MHPMEVENT12H 0x72c
#define CSR_MHPMEVENT13H 0x72d
#define CSR_MHPMEVENT14H 0x72e
#define CSR_MHPMEVENT15H 0x72f
#define CSR_MHPMEVENT16H 0x730
#define CSR_MHPMEVENT17H 0x731
#define CSR_MHPMEVENT18H 0x732
#define CSR_MHPMEVENT19H 0x733
#define CSR_MHPMEVENT20H 0x734
#define CSR_MHPMEVENT21H 0x735
#define CSR_MHPMEVENT22H 0x736
#define CSR_MHPMEVENT23H 0x737
#define CSR_MHPMEVENT24H 0x738
#define CSR_MHPMEVENT25H 0x739
#define CSR_MHPMEVENT26H 0x73a
#define CSR_MHPMEVENT27H 0x73b
#define CSR_MHPMEVENT28H 0x73c
#define CSR_MHPMEVENT29H 0x73d
#define CSR_MHPMEVENT30H 0x73e
#define CSR_MHPMEVENT31H 0x73f

#define CSR_MHPMCOUNTER3H 0xb83
#define CSR_MHPMCOUNTER4H 0xb84
#define CSR_MHPMCOUNTER5H 0xb85
Expand Down Expand Up @@ -451,6 +482,7 @@
#define CSR_VSMTE 0x2c0
#define CSR_VSPMMASK 0x2c1
#define CSR_VSPMBASE 0x2c2
#define CSR_SCOUNTOVF 0xda0

/* Crypto Extension */
#define CSR_SEED 0x015
Expand Down Expand Up @@ -628,6 +660,7 @@ typedef enum RISCVException {
#define IRQ_VS_EXT 10
#define IRQ_M_EXT 11
#define IRQ_S_GEXT 12
#define IRQ_PMU_OVF 13
#define IRQ_LOCAL_MAX 16
#define IRQ_LOCAL_GUEST_MAX (TARGET_LONG_BITS - 1)

Expand All @@ -645,11 +678,13 @@ typedef enum RISCVException {
#define MIP_VSEIP (1 << IRQ_VS_EXT)
#define MIP_MEIP (1 << IRQ_M_EXT)
#define MIP_SGEIP (1 << IRQ_S_GEXT)
#define MIP_LCOFIP (1 << IRQ_PMU_OVF)

/* sip masks */
#define SIP_SSIP MIP_SSIP
#define SIP_STIP MIP_STIP
#define SIP_SEIP MIP_SEIP
#define SIP_LCOFIP MIP_LCOFIP

/* MIE masks */
#define MIE_SEIE (1 << IRQ_S_EXT)
Expand Down Expand Up @@ -803,4 +838,24 @@ typedef enum RISCVException {
#define SEED_OPST_WAIT (0b01 << 30)
#define SEED_OPST_ES16 (0b10 << 30)
#define SEED_OPST_DEAD (0b11 << 30)
/* PMU related bits */
#define MIE_LCOFIE (1 << IRQ_PMU_OVF)

#define MHPMEVENT_BIT_OF BIT_ULL(63)
#define MHPMEVENTH_BIT_OF BIT(31)
#define MHPMEVENT_BIT_MINH BIT_ULL(62)
#define MHPMEVENTH_BIT_MINH BIT(30)
#define MHPMEVENT_BIT_SINH BIT_ULL(61)
#define MHPMEVENTH_BIT_SINH BIT(29)
#define MHPMEVENT_BIT_UINH BIT_ULL(60)
#define MHPMEVENTH_BIT_UINH BIT(28)
#define MHPMEVENT_BIT_VSINH BIT_ULL(59)
#define MHPMEVENTH_BIT_VSINH BIT(27)
#define MHPMEVENT_BIT_VUINH BIT_ULL(58)
#define MHPMEVENTH_BIT_VUINH BIT(26)

#define MHPMEVENT_SSCOF_MASK _ULL(0xFFFF000000000000)
#define MHPMEVENT_IDX_MASK 0xFFFFF
#define MHPMEVENT_SSCOF_RESVD 16

#endif

0 comments on commit 1466448

Please sign in to comment.