Skip to content

Commit 7ab52f7

Browse files
RISC-V: Add Sstc extension support
This series implements Sstc extension support which was ratified recently. Before the Sstc extension, an SBI call is necessary to generate timer interrupts as only M-mode have access to the timecompare registers. Thus, there is significant latency to generate timer interrupts at kernel. For virtualized enviornments, its even worse as the KVM handles the SBI call and uses a software timer to emulate the timecomapre register. Sstc extension solves both these problems by defining a stimecmp/vstimecmp at supervisor (host/guest) level. It allows kernel to program a timer and recieve interrupt without supervisor execution enviornment (M-mode/HS mode) intervention. * palmer/riscv-sstc: RISC-V: Prefer sstc extension if available RISC-V: Enable sstc extension parsing from DT RISC-V: Add SSTC extension CSR details
2 parents 3dbe582 + 9f7a8ff commit 7ab52f7

File tree

5 files changed

+32
-1
lines changed

5 files changed

+32
-1
lines changed

arch/riscv/include/asm/csr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@
247247
#define CSR_SIP 0x144
248248
#define CSR_SATP 0x180
249249

250+
#define CSR_STIMECMP 0x14D
251+
#define CSR_STIMECMPH 0x15D
252+
250253
#define CSR_VSSTATUS 0x200
251254
#define CSR_VSIE 0x204
252255
#define CSR_VSTVEC 0x205
@@ -256,6 +259,8 @@
256259
#define CSR_VSTVAL 0x243
257260
#define CSR_VSIP 0x244
258261
#define CSR_VSATP 0x280
262+
#define CSR_VSTIMECMP 0x24D
263+
#define CSR_VSTIMECMPH 0x25D
259264

260265
#define CSR_HSTATUS 0x600
261266
#define CSR_HEDELEG 0x602

arch/riscv/include/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ enum riscv_isa_ext_id {
5757
RISCV_ISA_EXT_SVPBMT,
5858
RISCV_ISA_EXT_ZICBOM,
5959
RISCV_ISA_EXT_ZIHINTPAUSE,
60+
RISCV_ISA_EXT_SSTC,
6061
RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
6162
};
6263

arch/riscv/kernel/cpu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ static struct riscv_isa_ext_data isa_ext_arr[] = {
9595
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
9696
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
9797
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
98+
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
9899
__RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
99100
};
100101

arch/riscv/kernel/cpufeature.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ void __init riscv_fill_hwcap(void)
203203
SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
204204
SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM);
205205
SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE);
206+
SET_ISA_EXT_MAP("sstc", RISCV_ISA_EXT_SSTC);
206207
}
207208
#undef SET_ISA_EXT_MAP
208209
}

drivers/clocksource/timer-riscv.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
* either be read from the "time" and "timeh" CSRs, and can use the SBI to
88
* setup events, or directly accessed using MMIO registers.
99
*/
10+
11+
#define pr_fmt(fmt) "riscv-timer: " fmt
12+
1013
#include <linux/clocksource.h>
1114
#include <linux/clockchips.h>
1215
#include <linux/cpu.h>
@@ -20,14 +23,28 @@
2023
#include <linux/of_irq.h>
2124
#include <clocksource/timer-riscv.h>
2225
#include <asm/smp.h>
26+
#include <asm/hwcap.h>
2327
#include <asm/sbi.h>
2428
#include <asm/timex.h>
2529

30+
static DEFINE_STATIC_KEY_FALSE(riscv_sstc_available);
31+
2632
static int riscv_clock_next_event(unsigned long delta,
2733
struct clock_event_device *ce)
2834
{
35+
u64 next_tval = get_cycles64() + delta;
36+
2937
csr_set(CSR_IE, IE_TIE);
30-
sbi_set_timer(get_cycles64() + delta);
38+
if (static_branch_likely(&riscv_sstc_available)) {
39+
#if defined(CONFIG_32BIT)
40+
csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
41+
csr_write(CSR_STIMECMPH, next_tval >> 32);
42+
#else
43+
csr_write(CSR_STIMECMP, next_tval);
44+
#endif
45+
} else
46+
sbi_set_timer(next_tval);
47+
3148
return 0;
3249
}
3350

@@ -166,6 +183,12 @@ static int __init riscv_timer_init_dt(struct device_node *n)
166183
if (error)
167184
pr_err("cpu hp setup state failed for RISCV timer [%d]\n",
168185
error);
186+
187+
if (riscv_isa_extension_available(NULL, SSTC)) {
188+
pr_info("Timer interrupt in S-mode is available via sstc extension\n");
189+
static_branch_enable(&riscv_sstc_available);
190+
}
191+
169192
return error;
170193
}
171194

0 commit comments

Comments
 (0)