mirror of
https://github.com/devkitPro/wut.git
synced 2026-03-21 17:34:47 -05:00
* Added `OSSetPerformanceMonitor()`. --HG-- branch : perf-mon * Renamed everything. --HG-- branch : perf-mon * Added header to tests. --HG-- branch : perf-mon --------- Co-authored-by: Daniel K. O. (dkosmari) <none@none>
207 lines
8.3 KiB
C
207 lines
8.3 KiB
C
#pragma once
|
|
#include <wut.h>
|
|
|
|
/**
|
|
* \defgroup coreinit_performancemonitor Performance Monitor
|
|
* \ingroup coreinit
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/// Used to tell OSSetPerformanceMonitor() which arguments are valid.
|
|
typedef enum OSPerfMonArg {
|
|
OS_PM_ARG_MMCR0 = 1u << 0u,
|
|
OS_PM_ARG_MMCR1 = 1u << 1u,
|
|
OS_PM_ARG_PMC1 = 1u << 2u,
|
|
OS_PM_ARG_PMC2 = 1u << 3u,
|
|
OS_PM_ARG_PMC3 = 1u << 4u,
|
|
OS_PM_ARG_PMC4 = 1u << 5u,
|
|
} OSPerfMonArg;
|
|
|
|
/**
|
|
* Flags to write to (U)MMCR0 register.
|
|
*
|
|
* \sa OSSetPerformanceMonitor
|
|
*/
|
|
typedef enum OSPerfMonMMCR0Flags {
|
|
OS_PM_MMCR0_PMC1_CURRENT = 0b0000000u << 6,
|
|
OS_PM_MMCR0_PMC1_CPU_CYCLES = 0b0000001u << 6,
|
|
OS_PM_MMCR0_PMC1_INSTRUCTIONS_COMPLETED = 0b0000010u << 6,
|
|
OS_PM_MMCR0_PMC1_TBL_RISING_TRANSITIONS = 0b0000011u << 6,
|
|
OS_PM_MMCR0_PMC1_INSTRUCTIONS_DISPATCHED = 0b0000100u << 6,
|
|
OS_PM_MMCR0_PMC1_EIEIO_INSTRUCTIONS_COMPLETED = 0b0000101u << 6,
|
|
OS_PM_MMCR0_PMC1_ITLB_SEARCH_CYCLES = 0b0000110u << 6,
|
|
OS_PM_MMCR0_PMC1_L2_HITS = 0b0000111u << 6,
|
|
OS_PM_MMCR0_PMC1_INSTRUCTIONS_EA_DELIVERED = 0b0001000u << 6,
|
|
OS_PM_MMCR0_PMC1_INSTRUCTIONS_COMPLETED_MATCHES_IABR = 0b0001001u << 6,
|
|
OS_PM_MMCR0_PMC1_SLOW_L1_MISSES = 0b0001010u << 6,
|
|
OS_PM_MMCR0_PMC1_UNRESOLVED_BRANCHES = 0b0001011u << 6,
|
|
OS_PM_MMCR0_PMC1_UNRESOLVED_STALL_CYCLES = 0b0001100u << 6,
|
|
OS_PM_MMCR0_PMC1_L1_SHARED_STORES = 0b0001110u << 6,
|
|
OS_PM_MMCR0_PMC1_L2_SHARED_INTERVENTIONS = 0b0001111u << 6,
|
|
OS_PM_MMCR0_PMC1_CACHE_PARADOXES = 0b0010000u << 6,
|
|
OS_PM_MMCR0_PMC1_CIU_LOAD_REQUESTS = 0b0010100u << 6,
|
|
OS_PM_MMCR0_PMC1_BIU_ADDRESS_ONLY_REQUESTS = 0b0010101u << 6,
|
|
OS_PM_MMCR0_PMC1_CIU_PARADOXES = 0b0010110u << 6,
|
|
OS_PM_MMCR0_PMC1_60XE_BUS_DATA_BEATS = 0b0010111u << 6,
|
|
|
|
OS_PM_MMCR0_PMC2_CURRENT = 0b000000u,
|
|
OS_PM_MMCR0_PMC2_CPU_CYCLES = 0b000001u,
|
|
OS_PM_MMCR0_PMC2_INSTRUCTIONS_COMPLETED = 0b000010u,
|
|
OS_PM_MMCR0_PMC2_TBL_RISING_TRANSITIONS = 0b000011u,
|
|
OS_PM_MMCR0_PMC2_INSTRUCTIONS_DISPATCHED = 0b000100u,
|
|
OS_PM_MMCR0_PMC2_L1_ICACHE_MISSES = 0b000101u,
|
|
OS_PM_MMCR0_PMC2_ITLB_MISSES = 0b000110u,
|
|
OS_PM_MMCR0_PMC2_L2_INSTRUCTION_MISSES = 0b000111u,
|
|
OS_PM_MMCR0_PMC2_PRED_BRANCHES_NOT_TAKEN = 0b001000u,
|
|
OS_PM_MMCR0_PMC2_RESERVED_LOADS = 0b001010u,
|
|
OS_PM_MMCR0_PMC2_LOADS_AND_STORES = 0b001011u,
|
|
OS_PM_MMCR0_PMC2_CACHE_SNOOPS = 0b001100u,
|
|
OS_PM_MMCR0_PMC2_L1_TO_L2_CASTOUTS = 0b001101u,
|
|
OS_PM_MMCR0_PMC2_SYSTEM_UNIT_INSTRUCTIONS = 0b001110u,
|
|
OS_PM_MMCR0_PMC2_L1_INSTRUCTION_MISS_CYCLES = 0b001111u,
|
|
OS_PM_MMCR0_PMC2_FIRST_SPECULATIVE_BRANCH_RESOLVES = 0b010000u,
|
|
OS_PM_MMCR0_PMC2_L2_SHARED_STORES = 0b010001u,
|
|
OS_PM_MMCR0_PMC2_L1_SHARED_INTERVENTIONS = 0b010010u,
|
|
OS_PM_MMCR0_PMC2_CIU_STORE_REQUESTS = 0b010100u,
|
|
OS_PM_MMCR0_PMC2_SLOW_OUTSTANDING_BIU_TRANSACTIONS = 0b010101u,
|
|
OS_PM_MMCR0_PMC2_CIU_MODIFIED_INTERVENTIONS = 0b010110u,
|
|
} OSPerfMonMMCR0Flags;
|
|
|
|
/**
|
|
* Flags to write to (U)MMCR1 register.
|
|
*
|
|
* \sa OSSetPerformanceMonitor
|
|
*/
|
|
typedef enum OSPerfMonMMCR1Flags {
|
|
OS_PM_MMCR1_PMC3_CURRENT = 0b00000u << 27,
|
|
OS_PM_MMCR1_PMC3_CPU_CYCLES = 0b00001u << 27,
|
|
OS_PM_MMCR1_PMC3_INSTRUCTIONS_COMPLETED = 0b00010u << 27,
|
|
OS_PM_MMCR1_PMC3_TBL_RISING_TRANSITIONS = 0b00011u << 27,
|
|
OS_PM_MMCR1_PMC3_INSTRUCTIONS_DISPATCHED = 0b00100u << 27,
|
|
OS_PM_MMCR1_PMC3_L1_DCACHE_MISSES = 0b00101u << 27,
|
|
OS_PM_MMCR1_PMC3_DTLB_MISSES = 0b00110u << 27,
|
|
OS_PM_MMCR1_PMC3_L2_DATA_MISSES = 0b00111u << 27,
|
|
OS_PM_MMCR1_PMC3_PRED_BRANCHES_TAKEN = 0b01000u << 27,
|
|
OS_PM_MMCR1_PMC3_COND_STORES_COMPLETED = 0b01010u << 27,
|
|
OS_PM_MMCR1_PMC3_FPU_INSTRUCTIONS_COMPLETED = 0b01011u << 27,
|
|
OS_PM_MMCR1_PMC3_L2_CASTOUTS_BY_SNOOPS = 0b01100u << 27,
|
|
OS_PM_MMCR1_PMC3_L2_CACHE_OPERATIONS = 0b01101u << 27,
|
|
OS_PM_MMCR1_PMC3_L1_LOAD_MISS_CYCLES = 0b01111u << 27,
|
|
OS_PM_MMCR1_PMC3_SECOND_SPECULATIVE_BRANCH_RESOLVES = 0b10000u << 27,
|
|
OS_PM_MMCR1_PMC3_BPU_STALL_LR_CR_CYCLES = 0b10001u << 27,
|
|
OS_PM_MMCR1_PMC3_L1_MODIFIED_INTERVENTIONS = 0b10010u << 27,
|
|
OS_PM_MMCR1_PMC3_ICBI_SNOOPS = 0b10011u << 27,
|
|
OS_PM_MMCR1_PMC3_CIU_ADDRESS_ONLY_REQUESTS = 0b10100u << 27,
|
|
OS_PM_MMCR1_PMC3_BIU_LOAD_REQUESTS = 0b10101u << 27,
|
|
OS_PM_MMCR1_PMC3_CIU_SHARED_INTERVENTIONS = 0b10110u << 27,
|
|
|
|
OS_PM_MMCR1_PMC4_CURRENT = 0b00000u << 22,
|
|
OS_PM_MMCR1_PMC4_CPU_CYCLES = 0b00001u << 22,
|
|
OS_PM_MMCR1_PMC4_INSTRUCTIONS_COMPLETED = 0b00010u << 22,
|
|
OS_PM_MMCR1_PMC4_TBL_RISING_TRANSITIONS = 0b00011u << 22,
|
|
OS_PM_MMCR1_PMC4_INSTRUCTIONS_DISPATCHED = 0b00100u << 22,
|
|
OS_PM_MMCR1_PMC4_L2_CASTOUTS = 0b00101u << 22,
|
|
OS_PM_MMCR1_PMC4_DTLB_SEARCH_CYCLES = 0b00110u << 22,
|
|
OS_PM_MMCR1_PMC4_BRANCHES_MISPREDICTED = 0b01000u << 22,
|
|
OS_PM_MMCR1_PMC4_INTACT_COND_STORES_COMPLETED = 0b01010u << 22,
|
|
OS_PM_MMCR1_PMC4_SYNC_INSTRUCTIONS_COMPLETED = 0b01011u << 22,
|
|
OS_PM_MMCR1_PMC4_SNOOP_RETRIES = 0b01100u << 22,
|
|
OS_PM_MMCR1_PMC4_INTEGER_OPERATIONS = 0b01101u << 22,
|
|
OS_PM_MMCR1_PMC4_BPU_STALL_TWO_BRANCHES_CYCLES = 0b01110u << 22,
|
|
OS_PM_MMCR1_PMC4_L2_MODIFIED_INTERVENTIONS = 0b10000u << 22,
|
|
OS_PM_MMCR1_PMC4_TLBIE_SNOOPS = 0b10001u << 22,
|
|
OS_PM_MMCR1_PMC4_L2_BANK_REFRESH_OVERFLOWS = 0b10010u << 22,
|
|
OS_PM_MMCR1_PMC4_CIU_ARTRY_COUNT = 0b10100u << 22,
|
|
OS_PM_MMCR1_PMC4_BIU_STORE_REQUESTS = 0b10101u << 22,
|
|
OS_PM_MMCR1_PMC4_CIU_TWO_CORE_SHARED_INTERVENTIONS = 0b10110u << 22,
|
|
} OSPerfMonMMCR1Flags;
|
|
|
|
/**
|
|
* Write to performance monitor registers.
|
|
*
|
|
* Performance monitor registers can only be written by the kernel, this allows userspace
|
|
* to write to them.
|
|
*
|
|
* \param arg_mask OR-ed values from `OSPerfMonArg`, indicating which of the following
|
|
* arguments are to be written to registers.
|
|
*
|
|
* \param mmcr0 OR-ed values from `OSPerfMonMMCR0Flags` to write to register MMCR0.
|
|
* \param mmcr1 OR-ed values from `OSPerfMonMMCR1Flags` to write to register MMCR1.
|
|
* \param pmc1 Value to write to register PMC1.
|
|
* \param pmc2 Value to write to register PMC2.
|
|
* \param pmc3 Value to write to register PMC3.
|
|
* \param pmc4 Value to write to register PMC4.
|
|
*/
|
|
void OSSetPerformanceMonitor(uint32_t arg_mask,
|
|
uint32_t mmcr0,
|
|
uint32_t mmcr1,
|
|
uint32_t pmc1,
|
|
uint32_t pmc2,
|
|
uint32_t pmc3,
|
|
uint32_t pmc4);
|
|
|
|
/**
|
|
* Convenience function to read from UPMC1.
|
|
*/
|
|
static inline
|
|
uint32_t
|
|
OSGetUPMC1()
|
|
{
|
|
uint32_t result;
|
|
asm("mfupmc1 %[result]"
|
|
: [result] "=r"(result));
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Convenience function to read from UPMC2.
|
|
*/
|
|
static inline
|
|
uint32_t
|
|
OSGetUPMC2()
|
|
{
|
|
uint32_t result;
|
|
asm("mfupmc2 %[result]"
|
|
: [result] "=r"(result));
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Convenience function to read from UPMC3.
|
|
*/
|
|
static inline
|
|
uint32_t
|
|
OSGetUPMC3()
|
|
{
|
|
uint32_t result;
|
|
asm("mfupmc3 %[result]"
|
|
: [result] "=r"(result));
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Convenience function to read from UPMC4.
|
|
*/
|
|
static inline
|
|
uint32_t
|
|
OSGetUPMC4()
|
|
{
|
|
uint32_t result;
|
|
asm("mfupmc4 %[result]"
|
|
: [result] "=r"(result));
|
|
return result;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/** @} */
|