diff --git a/arch/ext/Smctr.yaml b/arch/ext/Smctr.yaml new file mode 100644 index 0000000000..26be154fa2 --- /dev/null +++ b/arch/ext/Smctr.yaml @@ -0,0 +1,74 @@ +# yaml-language-server: $schema=../../schemas/ext_schema.json + +$schema: "ext_schema.json#" +kind: extension +name: Smctr +long_name: Control Transfer Records +description: | + A method for recording control flow transfer history is valuable not only for performance + profiling but also for debugging. + Control flow transfers refer to jump instructions (including function calls and returns), taken + branch instructions, traps, and trap returns. + Profiling tools, such as Linux perf, collect control transfer history when sampling software + execution, thereby enabling tools, like AutoFDO, to identify hot paths for optimization. + + Control flow trace capabilities offer very deep transfer history, but the volume of data produced + can result in significant performance overheads due to memory bandwidth consumption, buffer + management, and decoder overhead. + The Control Transfer Records (CTR) extension provides a method to record a limited history in + register-accessible internal chip storage, with the intent of dramatically reducing the + performance overhead and complexity of collecting transfer history. + + CTR defines a circular (FIFO) buffer. Each buffer entry holds a record for a single recorded + control flow transfer. + The number of records that can be held in the buffer depends upon both the implementation (the + maximum supported depth) and the CTR configuration (the software selected depth). + + Only qualified transfers are recorded. + Qualified transfers are those that meet the filtering criteria, which include the privilege mode + and the transfer type. + + Recorded transfers are inserted at the write pointer, which is then incremented, while older + recorded transfers may be overwritten once the buffer is full. + Or the user can enable RAS (Return Address Stack) emulation mode, where only function calls are + recorded, and function returns pop the last call record. + The source PC, target PC, and some optional metadata (transfer type, elapsed cycles) are stored + for each recorded transfer. + + The CTR buffer is accessible through an indirect CSR interface, such that software can specify + which logical entry in the buffer it wishes to read or write. + Logical entry 0 always corresponds to the youngest recorded transfer, followed by entry 1 as the + next youngest, and so on. +params: + CTR_CYCLE_COUNTER: + description: | + An internal counter used to count CPU cycles while CTR is active, where active implies that the + current privilege mode is enabled for recording and CTR is not frozen. This counter is only for + implementations that support cycle counting. It increments at the same rate as the mcycle counter. + This counter is used to populate the CC field of ctrdata when a qualified control transfer occurs. + It resets on writes to xctrctl and on execution of SCTRCLR. + schema: + type: integer + CCV_HW: + description: | + An internal hardware flag, which is stored in ctrdata.CCV of the next record in case of a qualified + control transfer. + It is cleared out after a write to xctrctl or execution of SCTRCLR, since CTR_CYCLE_COUNTER is reset. + This flag should additionally be cleared after any other implementation-specific scenarios where + active cycles might not be counted in CTR_CYCLE_COUNTER. + schema: + type: boolean +type: privileged +versions: + - version: "1.0.0" + state: ratified + ratification_date: 2024-11 + implies: + name: Ssctr + version: "1.0.0" + requires: + allOf: + - name: S + version: ~> 1.13 # The latest ratified version of S when Sscntr was ratified + - name: Smcsrind + version: ~> 1.0 diff --git a/arch/ext/Ssctr.yaml b/arch/ext/Ssctr.yaml new file mode 100644 index 0000000000..f2719b62fc --- /dev/null +++ b/arch/ext/Ssctr.yaml @@ -0,0 +1,19 @@ +# yaml-language-server: $schema=../../schemas/ext_schema.json + +$schema: "ext_schema.json#" +kind: extension +name: Ssctr +long_name: Control Transfer Records +description: | + The supervisor view of `Smctr`. +type: privileged +versions: + - version: "1.0.0" + state: ratified + ratification_date: 2024-11 + requires: + allOf: + - name: S + version: ~> 1.13 # The latest ratified version of S when Sscntr was ratified + - name: Sscsrind + version: ~> 1.0 diff --git a/arch/inst/Smdbltrp/sctrclr.yaml b/arch/inst/Smdbltrp/sctrclr.yaml index b8f99a943f..89020ea476 100644 --- a/arch/inst/Smdbltrp/sctrclr.yaml +++ b/arch/inst/Smdbltrp/sctrclr.yaml @@ -3,10 +3,31 @@ $schema: inst_schema.json# kind: instruction name: sctrclr -long_name: No synopsis available. +long_name: Supervisor Control Transfer Record (CTR) clear description: | - No description available. -definedBy: Smdbltrp + When `mstateen0.CTR`=1, the SCTRCLR instruction performs the following operations: + + * Zeroes all CTR Entry Registers, for all DEPTH values + * Reset to Zero the optional CTR cycle counter where implemented + ** `ctrdata.CC` and `ctrdata.CCV` bit fields. + + Any read of `ctrsource`, `ctrtarget`, or `ctrdata` that follows SCTRCLR, such that it precedes the next + qualified control transfer, will return the value 0. + + Further, the first recorded transfer following SCTRCLR will have `ctrdata.CCV`=0. + + SCTRCLR execution causes an `IllegalInstruction` exception if: + + * `Smctr` is not implemented + * The instruction is executed in S/VS/VU-mode and `Ssctr` is not implemented, or `mstateen0.CTR`=0 + * The instruction is executed in U-mode + + SCTRCLR execution causes a `VirtualInstruciton` exception if `mstateen0.CTR`=1 and: + + * The instruction is executed in VS-mode and `hstateen0.CTR`=0 + * The instruction is executed in VU-mode +definedBy: + anyOf: [Smctr, Ssctr] assembly: sctrclr encoding: match: "00010000010000000000000001110011" @@ -18,3 +39,31 @@ access: vu: always data_independent_timing: false operation(): | + if (implemented?(ExtensionName::Smstateen)) { + if (CSR[mstateen0].CTR == 1'b0) { + if (mode() != PrivilegeMode::M) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + } + else if (implemented?(ExtensionName::H)) { + if (CSR[hstateen0].CTR == 1'b0 && mode() == PrivilegeMode::VS) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } + } + } + if (mode() == PrivilegeMode::U) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + else if (implemented?(ExtensionName::H) && mode() == PrivilegeMode::VU) { + raise (ExceptionCode::VirtualInstruction, mode(), $encoding); + } + else { + for (U32 i = 0; i < (16 << CSR[sctrdepth].DEPTH); i++) { + CSR[siselect] = (0x200 + i); + CSR[sireg1] = 0; + CSR[sireg2] = 0; + CSR[sireg3] = 0; + } + CTR_CYCLE_COUNTER = 16'b0; + CCV_HW = 1'b0; + }