From nobody Mon Jan 26 09:21:38 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1769100500; cv=none; d=zohomail.com; s=zohoarc; b=Cpat1yhHrpzYz+ZcFB5MmtVCpTJqWNRHOf+i4TW8kOKFq/pe8YGHPmqAS+IET8CI8bhw3A3oNIy4nFLoN74VHTtltkEy1UdbWIZXp4OO1Gr1AwEY10jo30kf8uU5udy+3QlI6oPgiaH4q9o/kmMKl76UsKWv5Ei6yrN4M7btRXA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769100500; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=5c7RQ6OyPVY512X4e6H+NfNdqywFVdT5uOFctDjaxTg=; b=XnT3us4iqzUXU7ZwW/HPl+/ltQDXHUzMTFUQFKtlsgo/bqooxKEcP66XVM7Q+1uf1pMB9vuXPLGwufweaeRs27/9Zwsi8Rh2q13lbmaUxMUzv/MqcIMdUeGS1ihlOWDZeLndfQb11OiWg5KHEOq1c6yuzq8tgYETTUfplYiWEpU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1769100500485738.5259397219461; Thu, 22 Jan 2026 08:48:20 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1211351.1522943 (Exim 4.92) (envelope-from ) id 1vixqb-0000Ql-8E; Thu, 22 Jan 2026 16:47:53 +0000 Received: by outflank-mailman (output) from mailman id 1211351.1522943; Thu, 22 Jan 2026 16:47:53 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vixqa-0000QD-Rw; Thu, 22 Jan 2026 16:47:52 +0000 Received: by outflank-mailman (input) for mailman id 1211351; Thu, 22 Jan 2026 16:47:51 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1vixqZ-0007Ij-2k for xen-devel@lists.xenproject.org; Thu, 22 Jan 2026 16:47:51 +0000 Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [2a00:1450:4864:20::634]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 15ab09f6-f7b2-11f0-9ccf-f158ae23cfc8; Thu, 22 Jan 2026 17:47:49 +0100 (CET) Received: by mail-ej1-x634.google.com with SMTP id a640c23a62f3a-b87cc82fd85so200576466b.2 for ; Thu, 22 Jan 2026 08:47:48 -0800 (PST) Received: from fedora (user-109-243-67-101.play-internet.pl. [109.243.67.101]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b879513e951sm1686014966b.7.2026.01.22.08.47.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Jan 2026 08:47:47 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 15ab09f6-f7b2-11f0-9ccf-f158ae23cfc8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769100468; x=1769705268; darn=lists.xenproject.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=5c7RQ6OyPVY512X4e6H+NfNdqywFVdT5uOFctDjaxTg=; b=VooXe8WAyLXjDW+yhJ90+guS+IIAI6WBzr+WJVtYthd6oo0CaZjPvp+aE29zOxq9nk U2t17X45KKW2Vob85B+1UKjMKQvIFb6pZGrlprUdeJWuw5wyeJzf7490EGmCefD9hBp1 vj/4tSuP83SgDnkeDrCaMm0Th9JW/pAztWGGef35foCBz/wdmvQ9iTgslvZq2isCl7hz 0kzp9ybZYrYrEGvcbIru85WipIXA6zcyIx83A3AEF5uLf4jXmqjGaqOODInchLQkHWqf Yf2wvJbKzy04sQnllC9oDaWDOLVzkEY7AorKY3STraE46ydxK3M0W/Zq+Tt2eBmlimyU NhrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769100468; x=1769705268; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=5c7RQ6OyPVY512X4e6H+NfNdqywFVdT5uOFctDjaxTg=; b=SEKuRwcieNk3RGx70o2jV5jGkZaXZYyz5B9ihvl+IakNNQM03nbLafmhWb+0q1BljP Se6e367DMz0fYJ0kobcwu1kXCsMqc/N4iWTcdVojjgITZYeW0Z2ph+dq97bheHfk2hHK 6Vo6Rme03f4W3Cizii/pyvzljIU3xinBE9B4XFXdyDYc+P2lZGxsISK7VOak2BKWn3mM 29rldNYetS2pcFldJrfSs1zc9FVH4up5tOWelRyq4kFVUgOuLkTk1+b3w0Py2qXJNTkk cJ4zXw+V8Rl7zkrcSeOIwv2FBK4wH6gFLDehQd2K4G3/SZWOO/Rxjiwyhs4gGoK7l+Px lBPA== X-Gm-Message-State: AOJu0YytG2NH1KylYuLmIvIHNrMtdGU48LUq4+iJBeSd0yFVWkdLsCjD CBduFHZv/tsiYY6uibpEuZIDgOGN43qVLN502Xlr6Wy9JE5fqsFWxzAcFCy5Ig== X-Gm-Gg: AZuq6aJDd84EQWQYuin9Hk3m36/e/bxvvmKSikyQNOxDoXiyhDJzJSLe+luaNXwuk/3 qFOwqNYA0MhW09OA+XCl1QRYvCmC8G+vSiC3YUCW/x2yALP67a/zeua0vcG3LhbLjM2ES8zyZqB kTgEZIuw8109MYbxFURH52W2RL9HrGLmxgfF8B+OwVWx5vNRx5ZHePQXjXiZXU6Uk07x+je6fCY p+Zm7ud4dAe/y8dHjOmnYtR3emevA7GQfID03hFIxKNVWQxP/EZJ0XzhsMo2jog4XgP1zDUObWi aB6PfxGpA4wPan1jqo6tTtSvDlV0LX0Z29yAEJr1HGo3H7/cYuzHtgBUjWck+XUVwa52eDpYtMt hHeMvYRJlWpvNgxJF8VYR5tXYeRwPUfCok0tBqX4XUYImq9YBRyhiPvk1xRkaXOqMxTz/Z0CBEj cFSkxlsa9mGLauPvRngbual//U9Usj21QM0pIGNcA3ZD49rPWVTHfgXA== X-Received: by 2002:a17:906:f584:b0:b73:278a:a499 with SMTP id a640c23a62f3a-b879690c3ccmr1747464466b.15.1769100467976; Thu, 22 Jan 2026 08:47:47 -0800 (PST) From: Oleksii Kurochko To: xen-devel@lists.xenproject.org Cc: Oleksii Kurochko , Alistair Francis , Connor Davis , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini , Romain Caritey Subject: [PATCH v2 07/16] xen/riscv: introduce basic vtimer infrastructure for guests Date: Thu, 22 Jan 2026 17:47:22 +0100 Message-ID: <381c200edaff013d999c6314c20e8cc8bdb5b041.1769099885.git.oleksii.kurochko@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1769100501558154100 Lay the groundwork for guest timer support by introducing a per-vCPU virtual timer backed by Xen=E2=80=99s common timer infrastructure. The virtual timer is programmed in response to the guest SBI sbi_set_timer() call and injects a virtual supervisor timer interrupt into the vCPU when it expires. While a dedicated struct vtimer is not strictly required at present, it is expected to become necessary once SSTC support is introduced. In particular, it will need to carry additional state such as whether SSTC is enabled, the next compare value (e.g. for the VSTIMECMP CSR) to be saved and restored across context switches, and time delta state (e.g. HTIMEDELTA) required for use cases such as migration. Introducing struct vtimer now avoids a later refactoring. Signed-off-by: Oleksii Kurochko --- Changes in v2: - Drop domain_vtimer_init() as it does nothing. - Drop "struct vcpu *v;" from struct vtimer as it could be taken from arch_vcpu using container_of(). - Drop vtimer_initialized, use t->status =3D=3D TIMER_STATUS_invalid instead to understand if timer was or wasn't initialized. - Drop inclusion of xen/domain.h as xen/sched.h already includes it. - s/ xen/time.h/ xen.timer.h in vtimer.c. - Drop ULL in if-conidtion in vtimer_set_timer() as with the cast it isn't necessary to have suffix ULL. - Add migrate timer to vtimer_set_timer() to be sure that vtimer will occur on pCPU it was ran, so the signalling to that vCPU will (commonly) be cheaper. - Check if the timeout has already expired and just inject the event in vtimer_vtimer_set_timer(). - Drop const for ticks argument of vtimer_set_timer(). - Merge two patches to one: - xen/riscv: introduce vtimer - xen/riscv: introduce vtimer_set_timer() and vtimer_expired() --- xen/arch/riscv/Makefile | 1 + xen/arch/riscv/domain.c | 8 +++- xen/arch/riscv/include/asm/domain.h | 3 ++ xen/arch/riscv/include/asm/vtimer.h | 20 ++++++++ xen/arch/riscv/vtimer.c | 73 +++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 xen/arch/riscv/include/asm/vtimer.h create mode 100644 xen/arch/riscv/vtimer.c diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index 8863d4b15605..5bd180130165 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -22,6 +22,7 @@ obj-y +=3D traps.o obj-y +=3D vmid.o obj-y +=3D vm_event.o obj-y +=3D vsbi/ +obj-y +=3D vtimer.o =20 $(TARGET): $(TARGET)-syms $(OBJCOPY) -O binary -S $< $@ diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index c078d595df9c..e38c0db62cac 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -9,6 +9,7 @@ #include #include #include +#include =20 #define HEDELEG_DEFAULT (BIT(CAUSE_MISALIGNED_FETCH, U) | \ BIT(CAUSE_FETCH_ACCESS, U) | \ @@ -111,11 +112,14 @@ int arch_vcpu_create(struct vcpu *v) if ( is_idle_vcpu(v) ) return rc; =20 + if ( (rc =3D vcpu_vtimer_init(v)) ) + goto fail; + /* - * As the vtimer and interrupt controller (IC) are not yet implemented, + * As interrupt controller (IC) is not yet implemented, * return an error. * - * TODO: Drop this once the vtimer and IC are implemented. + * TODO: Drop this once IC is implemented. */ rc =3D -EOPNOTSUPP; goto fail; diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/a= sm/domain.h index fa083094b43e..482429d4ef33 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -8,6 +8,7 @@ #include =20 #include +#include =20 struct vcpu_vmid { uint64_t generation; @@ -51,6 +52,8 @@ struct arch_vcpu =20 struct cpu_info *cpu_info; =20 + struct vtimer vtimer; + /* CSRs */ register_t hedeleg; register_t hideleg; diff --git a/xen/arch/riscv/include/asm/vtimer.h b/xen/arch/riscv/include/a= sm/vtimer.h new file mode 100644 index 000000000000..0d1555511755 --- /dev/null +++ b/xen/arch/riscv/include/asm/vtimer.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * (c) 2023-2024 Vates + */ + +#ifndef ASM__RISCV__VTIMER_H +#define ASM__RISCV__VTIMER_H + +#include + +struct vtimer { + struct timer timer; +}; + +int vcpu_vtimer_init(struct vcpu *v); +void vcpu_timer_destroy(struct vcpu *v); + +void vtimer_set_timer(struct vtimer *t, uint64_t ticks); + +#endif /* ASM__RISCV__VTIMER_H */ diff --git a/xen/arch/riscv/vtimer.c b/xen/arch/riscv/vtimer.c new file mode 100644 index 000000000000..b6599fa383b8 --- /dev/null +++ b/xen/arch/riscv/vtimer.c @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include + +#include + +static void vtimer_expired(void *data) +{ + struct vtimer *t =3D data; + struct arch_vcpu *avcpu =3D container_of(t, struct arch_vcpu, vtimer); + struct vcpu *v =3D container_of(avcpu, struct vcpu, arch); + + vcpu_set_interrupt(v, IRQ_VS_TIMER); +} + +int vcpu_vtimer_init(struct vcpu *v) +{ + struct vtimer *t =3D &v->arch.vtimer; + + init_timer(&t->timer, vtimer_expired, t, v->processor); + + return 0; +} + +void vcpu_timer_destroy(struct vcpu *v) +{ + struct vtimer *t =3D &v->arch.vtimer; + + if ( t->timer.status =3D=3D TIMER_STATUS_invalid ) + return; + + kill_timer(&v->arch.vtimer.timer); +} + +void vtimer_set_timer(struct vtimer *t, const uint64_t ticks) +{ + struct arch_vcpu *avcpu =3D container_of(t, struct arch_vcpu, vtimer); + struct vcpu *v =3D container_of(avcpu, struct vcpu, arch); + s_time_t expires =3D ticks_to_ns(ticks - boot_clock_cycles); + + vcpu_unset_interrupt(v, IRQ_VS_TIMER); + + /* + * According to the RISC-V sbi spec: + * If the supervisor wishes to clear the timer interrupt without + * scheduling the next timer event, it can either request a timer + * interrupt infinitely far into the future (i.e., (uint64_t)-1), + * or it can instead mask the timer interrupt by clearing sie.STIE C= SR + * bit. + */ + if ( ticks =3D=3D ((uint64_t)~0) ) + { + stop_timer(&t->timer); + + return; + } + + if ( expires < NOW() ) + { + /* + * Simplify the logic if the timeout has already expired and just + * inject the event. + */ + stop_timer(&t->timer); + vcpu_set_interrupt(v, IRQ_VS_TIMER); + + return; + } + + migrate_timer(&t->timer, smp_processor_id()); + set_timer(&t->timer, expires); +} --=20 2.52.0