[RFC,v2,0/3] riscv: add support for SBI Supervisor Software Events

Message ID 20240112111720.2975069-1-cleger@rivosinc.com
Headers
Series riscv: add support for SBI Supervisor Software Events |

Message

Clément Léger Jan. 12, 2024, 11:17 a.m. UTC
  The SBI Supervisor Software Events (SSE) extensions provides a mechanism
to inject software events from an SBI implementation to supervisor
software such that it preempts all other supervisor level traps and
interrupts [1].

Various events are defined and can be send asynchronously to supervisor
software (RAS, PMU, DEBUG, Asynchronous page fault) from SBI as well
as platform specific events. Events can be either local (per-hart) or
global. Events can be nested on top of each other based on priority and
can interrupt the kernel at any time.

First patch adds the SSE definitions. Second one adds support for SSE
itself. Implementation is split between arch specific code and generic
part (similarly to what is done for ARM SDEI). Finally, the last patch
add support for SSE events in the SBI PMU driver. If the SSE event is
available from the SBI then, it will be used instead of the normal
interrupt.

Amongst the specific points that needs to be handle is the interruption
at any point of the kernel execution and more specifically during
exception handling. Due to the fact that the exception entry
implementation uses the SCRATCH CSR as both the current task struct and
as the temporary register to switch the stack and save register, it is
difficult to reliably get the current task struct if we get interrupted
at this specific moment. A fixup-like mechanism allows to mark the
location of the current task struct depending on the entry level
(user/kernel) and the location. This is then used in the SSE assembly to
determine where is located the current task_struct.

Contrary to pseudo NMI [2], SSE does not modifies the way interrupts are
handled and does not adds any overhead to existing code. Moreover, it
provides "true" NMI-like interrupts which can interrupt the kernel at
any time (even in exception handling). This is particularly crucial for
RAS errors which needs to be handled as fast as possible to avoid any
fault propagation. Additionally, SSE event handling is faster that the
standard IRQ handling path with almost half executed instruction (700 vs
1590). Some complementary tests/perf measurements will be done.

For testing purpose, one can use the provided SBI implementation at [3].
This series also needs patch [4] to fix a bug in the PMU driver.

Link: https://lists.riscv.org/g/tech-prs/message/744 [1]
Link: https://lore.kernel.org/lkml/20231023082911.23242-10-luxu.kernel@bytedance.com/T/ [2]
Link: https://github.com/rivosinc/opensbi/tree/sse_v2 [3]

---

Changes in v2:
 - Implemented specification v2
 - Fix various error handling cases
 - Added shadow stack support

v1: https://lore.kernel.org/linux-riscv/20231026143122.279437-1-cleger@rivosinc.com/

Clément Léger (3):
  riscv: add SBI SSE extension definitions
  riscv: add support for SBI Supervisor Software Events extension
  perf: RISC-V: add support for SSE event

 arch/riscv/include/asm/asm-prototypes.h |   4 +
 arch/riscv/include/asm/asm.h            |  42 +-
 arch/riscv/include/asm/sbi.h            |  47 ++
 arch/riscv/include/asm/scs.h            |   7 +
 arch/riscv/include/asm/sse.h            |  12 +
 arch/riscv/include/asm/thread_info.h    |   1 +
 arch/riscv/kernel/Makefile              |   1 +
 arch/riscv/kernel/asm-offsets.c         |  26 ++
 arch/riscv/kernel/entry.S               | 202 +++++++++
 arch/riscv/kernel/sbi.c                 |   4 +
 arch/riscv/kernel/sse.c                 | 130 ++++++
 arch/riscv/kernel/stacktrace.c          |  13 +
 arch/riscv/kernel/vmlinux.lds.S         |   6 +
 drivers/firmware/Kconfig                |  10 +
 drivers/firmware/Makefile               |   1 +
 drivers/firmware/riscv_sse.c            | 567 ++++++++++++++++++++++++
 drivers/perf/riscv_pmu_sbi.c            |  46 +-
 include/linux/riscv_sse.h               |  76 ++++
 18 files changed, 1176 insertions(+), 19 deletions(-)
 create mode 100644 arch/riscv/include/asm/sse.h
 create mode 100644 arch/riscv/kernel/sse.c
 create mode 100644 drivers/firmware/riscv_sse.c
 create mode 100644 include/linux/riscv_sse.h