From: James Raphael Tiovalen <jamestiotio@gmail.com>
To: kvm@vger.kernel.org, kvm-riscv@lists.infradead.org
Cc: andrew.jones@linux.dev, atishp@rivosinc.com,
cade.richard@berkeley.edu,
James Raphael Tiovalen <jamestiotio@gmail.com>
Subject: [kvm-unit-tests PATCH 4/4] riscv: sbi: Add test for timer extension
Date: Wed, 19 Jun 2024 01:30:53 +0800 [thread overview]
Message-ID: <20240618173053.364776-5-jamestiotio@gmail.com> (raw)
In-Reply-To: <20240618173053.364776-1-jamestiotio@gmail.com>
Add a test for the set_timer function of the time extension. The test
checks that:
- The time extension is available
- The time counter monotonically increases
- The installed timer interrupt handler is called
- The timer interrupt is received within a reasonable time frame
The timer interrupt delay can be set using the TIMER_DELAY environment
variable. If the variable is not set, the default delay value is
1000000. The time interval used to validate the timer interrupt is
between the specified delay and double the delay. Because of this, the
test might fail if the delay is too short. Hence, we set the default
delay value as the minimum value.
This test has been verified on RV32 and RV64 with OpenSBI using QEMU.
Signed-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>
---
lib/riscv/asm/csr.h | 6 ++++
lib/riscv/asm/sbi.h | 5 +++
riscv/sbi.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+)
diff --git a/lib/riscv/asm/csr.h b/lib/riscv/asm/csr.h
index da58b0ce..c4435650 100644
--- a/lib/riscv/asm/csr.h
+++ b/lib/riscv/asm/csr.h
@@ -12,6 +12,7 @@
#define CSR_STVAL 0x143
#define CSR_SIP 0x144
#define CSR_SATP 0x180
+#define CSR_TIME 0xc01
#define SSTATUS_SIE (_AC(1, UL) << 1)
@@ -108,5 +109,10 @@
: "memory"); \
})
+#define wfi() \
+({ \
+ __asm__ __volatile__("wfi" ::: "memory"); \
+})
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASMRISCV_CSR_H_ */
diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h
index d82a384d..eb4c77ef 100644
--- a/lib/riscv/asm/sbi.h
+++ b/lib/riscv/asm/sbi.h
@@ -18,6 +18,7 @@ enum sbi_ext_id {
SBI_EXT_BASE = 0x10,
SBI_EXT_HSM = 0x48534d,
SBI_EXT_SRST = 0x53525354,
+ SBI_EXT_TIME = 0x54494D45,
};
enum sbi_ext_base_fid {
@@ -37,6 +38,10 @@ enum sbi_ext_hsm_fid {
SBI_EXT_HSM_HART_SUSPEND,
};
+enum sbi_ext_time_fid {
+ SBI_EXT_TIME_SET_TIMER = 0,
+};
+
struct sbiret {
long error;
long value;
diff --git a/riscv/sbi.c b/riscv/sbi.c
index 762e9711..6ad1dff6 100644
--- a/riscv/sbi.c
+++ b/riscv/sbi.c
@@ -6,8 +6,13 @@
*/
#include <libcflat.h>
#include <stdlib.h>
+#include <asm/csr.h>
+#include <asm/interrupt.h>
+#include <asm/processor.h>
#include <asm/sbi.h>
+static bool timer_work;
+
static void help(void)
{
puts("Test SBI\n");
@@ -19,6 +24,18 @@ static struct sbiret __base_sbi_ecall(int fid, unsigned long arg0)
return sbi_ecall(SBI_EXT_BASE, fid, arg0, 0, 0, 0, 0, 0);
}
+static struct sbiret __time_sbi_ecall(int fid, unsigned long arg0)
+{
+ return sbi_ecall(SBI_EXT_TIME, fid, arg0, 0, 0, 0, 0, 0);
+}
+
+static void timer_interrupt_handler(struct pt_regs *regs)
+{
+ timer_work = true;
+ toggle_timer_interrupt(false);
+ local_irq_disable();
+}
+
static bool env_or_skip(const char *env)
{
if (!getenv(env)) {
@@ -112,6 +129,75 @@ static void check_base(void)
report_prefix_pop();
}
+static void check_time(void)
+{
+ struct sbiret ret;
+ unsigned long begin, end, duration;
+ const unsigned long default_delay = 1000000;
+ unsigned long delay = getenv("TIMER_DELAY")
+ ? MAX(strtol(getenv("TIMER_DELAY"), NULL, 0), default_delay)
+ : default_delay;
+
+ report_prefix_push("time");
+
+ ret = __base_sbi_ecall(SBI_EXT_BASE_PROBE_EXT, SBI_EXT_TIME);
+
+ if (ret.error) {
+ report_fail("probing for time extension failed");
+ report_prefix_pop();
+ return;
+ }
+
+ if (!ret.value) {
+ report_skip("time extension not available");
+ report_prefix_pop();
+ return;
+ }
+
+ begin = csr_read(CSR_TIME);
+ end = csr_read(CSR_TIME);
+ if (begin >= end) {
+ report_fail("time counter has decreased");
+ report_prefix_pop();
+ return;
+ }
+
+ report_prefix_push("set_timer");
+
+ install_irq_handler(IRQ_SUPERVISOR_TIMER, timer_interrupt_handler);
+ local_irq_enable();
+
+ begin = csr_read(CSR_TIME);
+ ret = __time_sbi_ecall(SBI_EXT_TIME_SET_TIMER, csr_read(CSR_TIME) + delay);
+
+ if (ret.error) {
+ report_fail("setting timer failed");
+ install_irq_handler(IRQ_SUPERVISOR_TIMER, NULL);
+ report_prefix_pop();
+ report_prefix_pop();
+ return;
+ }
+
+ toggle_timer_interrupt(true);
+
+ while ((!timer_work) && (csr_read(CSR_TIME) <= (begin + delay)))
+ wfi();
+
+ end = csr_read(CSR_TIME);
+ report(timer_work, "timer interrupt received");
+
+ install_irq_handler(IRQ_SUPERVISOR_TIMER, NULL);
+ __time_sbi_ecall(SBI_EXT_TIME_SET_TIMER, -1);
+
+ duration = end - begin;
+ if (timer_work)
+ report((duration >= delay) && (duration <= (delay + delay)), "timer delay honored");
+
+ report_prefix_pop();
+
+ report_prefix_pop();
+}
+
int main(int argc, char **argv)
{
@@ -122,6 +208,7 @@ int main(int argc, char **argv)
report_prefix_push("sbi");
check_base();
+ check_time();
return report_summary();
}
--
2.43.0
next prev parent reply other threads:[~2024-06-18 17:32 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-18 17:30 [kvm-unit-tests PATCH 0/4] riscv: sbi: Add support to test timer extension James Raphael Tiovalen
2024-06-18 17:30 ` [kvm-unit-tests PATCH 1/4] riscv: Extend exception handling support for interrupts James Raphael Tiovalen
2024-06-18 17:30 ` [kvm-unit-tests PATCH 2/4] riscv: Update exception cause list James Raphael Tiovalen
2024-06-19 8:30 ` Andrew Jones
2024-06-19 13:35 ` James R T
2024-06-18 17:30 ` [kvm-unit-tests PATCH 3/4] riscv: Add methods to toggle interrupt enable bits James Raphael Tiovalen
2024-06-19 8:39 ` Andrew Jones
2024-06-19 13:40 ` James R T
2024-06-18 17:30 ` James Raphael Tiovalen [this message]
2024-07-04 16:06 ` [kvm-unit-tests PATCH 4/4] riscv: sbi: Add test for timer extension Andrew Jones
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240618173053.364776-5-jamestiotio@gmail.com \
--to=jamestiotio@gmail.com \
--cc=andrew.jones@linux.dev \
--cc=atishp@rivosinc.com \
--cc=cade.richard@berkeley.edu \
--cc=kvm-riscv@lists.infradead.org \
--cc=kvm@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox