From patchwork Sun Jul 21 07:06:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Raphael Tiovalen X-Patchwork-Id: 1962857 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=nKrO+tkf; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=gagRmpRn; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WRZFv1dn0z1xrQ for ; Sun, 21 Jul 2024 17:06:27 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=rs4Wb4vVq1aur/dPcCPYubOpwYcvhM8qrOcR4Lg8q6c=; b=nKrO+tkfsARgdn 4oEPlHON2No0FsiO/RgC4f5XvNt2SGtbhN2HQitHxcaFWs3TBn2iHnNghE1M0sIVwt55S087Buiwi SCiww+FLU5//14JqOzmr+2WipAbHm99sRj+vh/vVPtxkZV3UqQ+h+bRQmkJrgaGLHxQCZxabNBF3K lVwlQZ8Bv2h+hSrKjjHv72+1NKbSoUDuyR4c2uyn7/5Tdhq4kZaqY9f/O4LY5N6yUjYxN0eJb4Y9N 8eqaFXFbQmUkpaZtS+/ArJ+clJ0QXOWTqYIZiVeHi/71COh//DyJjbCB6pkeaiHD9AVjLuy5bpvHK cG0ywRc/orMcM3DNDAxg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sVQeH-00000006Lq6-3xeN; Sun, 21 Jul 2024 07:06:25 +0000 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sVQeD-00000006LnS-471g for kvm-riscv@lists.infradead.org; Sun, 21 Jul 2024 07:06:24 +0000 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-70d23caf8ddso132333b3a.0 for ; Sun, 21 Jul 2024 00:06:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1721545581; x=1722150381; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BBE6A/bNNTAy6FniqPADMXl7o6XMR7KLE4bnhlWkgK4=; b=gagRmpRnU72LZtMg/G4gFu+pUWgPVeO+gfxsg5qQf0iYbRygZKvQO2KUUA/QheTyMR V2wdCH0gfOAIQPLXP6/Max4Jyb5NYj/gd0n4hvdxYwNE9jQcpB+rwE0bznZBnQTQevtq GqrwshtFx4pGcJsNB+ckdnHgmZ7S5JBiGBwQSMb4hmXYPmtbvFe0eb/PbdAcMrEPjdaR ixusFPPAiCl74AAg7FSzWEVL55jfy6KrXqTwLE45PuesZz7voKotI6LKeGZG8qHkWncr hb5soI+9ScbkRIwKlpsHQqs+RdlNMCouRRd/rk+BDJTAFIPtvkJAZRQSAG1CD6X1LsAH s4jQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721545581; x=1722150381; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BBE6A/bNNTAy6FniqPADMXl7o6XMR7KLE4bnhlWkgK4=; b=BlxRKu1tFT5uoEgnRekCSKDPi/5pRTr+CcQpxIASj+RzkKReN98JncKBpExyzv+Xx2 W0Xa1GxlB+0esJiUNMpgB92EcK+ftIskvOGyBY18nDQ7RdPtbxF9+3oqYDLqwMu5bjvi dMGdYzlWy2R9+WasaTnxzCa+o2TVasaz1A04wS1Cygpjo2+9yIKhCJma2ZVdh+t10rVh ek9OdfDTGBAZmJGD8ouIjaLtYEBXd3WBNu0NyF16fzLWSevqEVHJfnBvJltFkVEoNf2o mo7GRxQHRHtr94ItpRe9zsCfNc2qSGip1URGsyLwBKW1w+lRqdE5QX0VtpSLAL/zjSDs GHzg== X-Forwarded-Encrypted: i=1; AJvYcCV8cn+YEKwxHP8LORWcesguSFVCtT6PfznIeIrhqIYsOAyrUGCVvlqEsrELo7cyS1duwRNaHXq1UJJSWtMDK7htXRTgCOuYwmARS/yNnw== X-Gm-Message-State: AOJu0YzOWvJ6C2axmwywnidGSz5Qhmj1W2slBOLXSaB5yc9WivVqaS+K T/8uOK8SlI8Q5uhuxG4aX8SqHflo6Sb/UKpODRCI41uy4EMX9eLF X-Google-Smtp-Source: AGHT+IFLtXv3i3p8jfevPC2wvq0SjkTMoC845xtDvLoXQgWuVrCSGCrbi5aw1SstRh3N/CYv3N0OfA== X-Received: by 2002:a05:6a21:c8a:b0:1c3:ce0f:bfb2 with SMTP id adf61e73a8af0-1c4285d55a7mr4598852637.23.1721545580432; Sun, 21 Jul 2024 00:06:20 -0700 (PDT) Received: from JRT-PC.. ([180.255.73.78]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2cb77492bc6sm4891461a91.1.2024.07.21.00.06.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 21 Jul 2024 00:06:19 -0700 (PDT) From: James Raphael Tiovalen 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 Subject: [kvm-unit-tests PATCH v4 5/5] riscv: sbi: Add test for timer extension Date: Sun, 21 Jul 2024 15:06:00 +0800 Message-ID: <20240721070601.88639-6-jamestiotio@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240721070601.88639-1-jamestiotio@gmail.com> References: <20240721070601.88639-1-jamestiotio@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240721_000622_060636_791FD526 X-CRM114-Status: GOOD ( 19.29 ) X-Spam-Score: -2.1 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Add a test for the set_timer function of the time extension. The test checks that: - The time extension is available - The installed timer interrupt handler is called - The timer interrupt is received [...] Content analysis details: (-2.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:429 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [jamestiotio(at)gmail.com] X-BeenThere: kvm-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "kvm-riscv" Errors-To: kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add a test for the set_timer function of the time extension. The test checks that: - The time extension is available - The installed timer interrupt handler is called - The timer interrupt is received within a reasonable time interval - The timer interrupt pending bit is cleared after the set_timer SBI call is made - The timer interrupt can be cleared either by requesting a timer interrupt infinitely far into the future or by masking the timer interrupt The timer interrupt delay can be set using the TIMER_DELAY environment variable in microseconds. The default delay value is 200 milliseconds. Since the interrupt can arrive a little later than the specified delay, allow some margin of error. This margin of error can be specified via the TIMER_MARGIN environment variable in microseconds. The default margin of error is 200 milliseconds. Signed-off-by: James Raphael Tiovalen --- lib/riscv/asm/csr.h | 8 +++ lib/riscv/asm/sbi.h | 5 ++ lib/riscv/asm/timer.h | 10 ++++ riscv/sbi.c | 132 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+) diff --git a/lib/riscv/asm/csr.h b/lib/riscv/asm/csr.h index a9b1bd42..24b333e0 100644 --- a/lib/riscv/asm/csr.h +++ b/lib/riscv/asm/csr.h @@ -4,11 +4,15 @@ #include #define CSR_SSTATUS 0x100 +#define CSR_SIE 0x104 #define CSR_STVEC 0x105 #define CSR_SSCRATCH 0x140 #define CSR_SEPC 0x141 #define CSR_SCAUSE 0x142 #define CSR_STVAL 0x143 +#define CSR_SIP 0x144 +#define CSR_STIMECMP 0x14d +#define CSR_STIMECMPH 0x15d #define CSR_SATP 0x180 #define CSR_TIME 0xc01 @@ -47,6 +51,10 @@ #define IRQ_S_GEXT 12 #define IRQ_PMU_OVF 13 +#define IE_TIE (_AC(0x1, UL) << IRQ_S_TIMER) + +#define IP_TIP IE_TIE + #ifndef __ASSEMBLY__ #define csr_swap(csr, val) \ diff --git a/lib/riscv/asm/sbi.h b/lib/riscv/asm/sbi.h index 5e1a674a..73ab5438 100644 --- a/lib/riscv/asm/sbi.h +++ b/lib/riscv/asm/sbi.h @@ -16,6 +16,7 @@ enum sbi_ext_id { SBI_EXT_BASE = 0x10, + SBI_EXT_TIME = 0x54494d45, SBI_EXT_HSM = 0x48534d, SBI_EXT_SRST = 0x53525354, }; @@ -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/lib/riscv/asm/timer.h b/lib/riscv/asm/timer.h index f7504f84..b3514d3f 100644 --- a/lib/riscv/asm/timer.h +++ b/lib/riscv/asm/timer.h @@ -11,4 +11,14 @@ static inline uint64_t timer_get_cycles(void) return csr_read(CSR_TIME); } +static inline void timer_irq_enable(void) +{ + csr_set(CSR_SIE, IE_TIE); +} + +static inline void timer_irq_disable(void) +{ + csr_clear(CSR_SIE, IE_TIE); +} + #endif /* _ASMRISCV_TIMER_H_ */ diff --git a/riscv/sbi.c b/riscv/sbi.c index 762e9711..fe2fe771 100644 --- a/riscv/sbi.c +++ b/riscv/sbi.c @@ -6,7 +6,21 @@ */ #include #include +#include +#include +#include +#include +#include +#include #include +#include +#include + +static bool timer_works; +static bool mask_timer_irq; +static bool timer_irq_set; +static bool timer_irq_cleared; +static unsigned long timer_irq_count; static void help(void) { @@ -19,6 +33,34 @@ 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(unsigned long stime_value) +{ + return sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0, 0, 0, 0, 0); +} + +static inline bool timer_irq_pending(void) +{ + return csr_read(CSR_SIP) & IP_TIP; +} + +static void timer_irq_handler(struct pt_regs *regs) +{ + if (timer_irq_count < ULONG_MAX) + ++timer_irq_count; + + timer_works = true; + if (timer_irq_pending()) + timer_irq_set = true; + + if (mask_timer_irq) { + timer_irq_disable(); + } else { + __time_sbi_ecall(ULONG_MAX); + if (!timer_irq_pending()) + timer_irq_cleared = true; + } +} + static bool env_or_skip(const char *env) { if (!getenv(env)) { @@ -112,6 +154,95 @@ static void check_base(void) report_prefix_pop(); } +static void check_time(void) +{ + struct sbiret ret; + unsigned long begin, end, duration; + unsigned long d = getenv("TIMER_DELAY") ? strtol(getenv("TIMER_DELAY"), NULL, 0) + : 200000; + unsigned long margin = getenv("TIMER_MARGIN") ? strtol(getenv("TIMER_MARGIN"), NULL, 0) + : 200000; + + d = usec_to_cycles(d); + margin = usec_to_cycles(margin); + + report_prefix_push("time"); + + if (!sbi_probe(SBI_EXT_TIME)) { + report_skip("time extension not available"); + report_prefix_pop(); + return; + } + + report_prefix_push("set_timer"); + + install_irq_handler(IRQ_S_TIMER, timer_irq_handler); + local_irq_enable(); + if (cpu_has_extension(smp_processor_id(), ISA_SSTC)) { + csr_write(CSR_STIMECMP, ULONG_MAX); +#if __riscv_xlen == 32 + csr_write(CSR_STIMECMPH, ULONG_MAX); +#endif + } + timer_irq_enable(); + + begin = timer_get_cycles(); + ret = __time_sbi_ecall(begin + d); + + report(!ret.error, "set timer"); + if (ret.error) + report_info("set timer failed with %ld\n", ret.error); + + report(!timer_irq_pending(), "pending timer interrupt bit cleared"); + + while ((end = timer_get_cycles()) <= (begin + d + margin) && !timer_works) + cpu_relax(); + + report(timer_works, "timer interrupt received"); + report(timer_irq_set, "pending timer interrupt bit set in irq handler"); + report(timer_irq_cleared, "pending timer interrupt bit cleared by setting timer to -1"); + + if (timer_works) { + duration = end - begin; + report(duration >= d && duration <= (d + margin), "timer delay honored"); + } + + if (timer_irq_count > 1) + report_fail("timer interrupt received multiple times"); + + timer_works = false; + timer_irq_set = false; + timer_irq_count = 0; + mask_timer_irq = true; + begin = timer_get_cycles(); + ret = __time_sbi_ecall(begin + d); + + report(!ret.error, "set timer for mask irq test"); + if (ret.error) + report_info("set timer for mask irq test failed with %ld\n", ret.error); + + while ((end = timer_get_cycles()) <= (begin + d + margin) && !timer_works) + cpu_relax(); + + report(timer_works, "timer interrupt received for mask irq test"); + report(timer_irq_set, "pending timer interrupt bit set in irq handler for mask irq test"); + + if (timer_works) { + duration = end - begin; + report(duration >= d && duration <= (d + margin), + "timer delay honored for mask irq test"); + } + + if (timer_irq_count > 1) + report_fail("timer interrupt received multiple times for mask irq test"); + + local_irq_disable(); + install_irq_handler(IRQ_S_TIMER, NULL); + + report_prefix_pop(); + report_prefix_pop(); +} + int main(int argc, char **argv) { @@ -122,6 +253,7 @@ int main(int argc, char **argv) report_prefix_push("sbi"); check_base(); + check_time(); return report_summary(); }