From nobody Tue Jan 21 10:35:48 2025
X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1])
by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4YckBX5bjzz5ktjS;
Tue, 21 Jan 2025 10:35:48 +0000 (UTC)
(envelope-from git@FreeBSD.org)
Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256
client-signature RSA-PSS (4096 bits) client-digest SHA256)
(Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK))
by mx1.freebsd.org (Postfix) with ESMTPS id 4YckBX5Lhtz3X1J;
Tue, 21 Jan 2025 10:35:48 +0000 (UTC)
(envelope-from git@FreeBSD.org)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim;
t=1737455748;
h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding;
bh=mVEJ7qdt/MQPOkRHTcVtTewKCgjottrTxa/Y7uL8oc0=;
b=aNS5SDlfJBO11VOrbUE9h6rIIV6QpWGEcUtlAmFTi7atWi8LbdVFMZQZDyf0qPAsDyovtT
+JGyTvHxfWctdFb4bKE/rvQHsQeF1d3MApr3tfIEtfJWjzwd/+a81DWVEftpvx17Pe79sh
FPhAgrVZYOlzSxu4bZtVb1E7R4jAqAEdhhyfSKQd2Mxnt/FhH/VjjOGB7t2TBJ9k5atxkF
aspQI6VTSNfMa6Ll9a2xLsxxI3nKLJihTg01dMRv6a+syoF60nXANxGNPh87DCkwZJ8vzH
SfN70RMWLcwx36VTXtn90+pwpY46JWGrbUjxdvpHu4x8jJUyP8CL0gmesuVRjg==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org;
s=dkim; t=1737455748;
h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding;
bh=mVEJ7qdt/MQPOkRHTcVtTewKCgjottrTxa/Y7uL8oc0=;
b=tojjjoEStOhBovfDxnFbJcpPLIQmRvvfzQHuAkmWYViYIhEzTV4plM3URyQyFqOpMhCsn3
A5P852zYtPDLQ6UlKnoAANM3yhU7qS7MkLZ0uLsT5e8zB1chSUfNuZbOnQezzf6SIzyqCy
rDPeEorFqypuvvahZmmuy82VImkrI7WOTZn3rqhkSQ+aIn+lfAz8TSdbS7MROD5U6yk2fH
/M4UWTYAj1SPAwkA55CB2kFwc99eTqu3jlmmODJophBuESMTNtIjXWhedabARn8qLZdTFd
IpbKs3wGMCoSrB6s3KhQsAmIzMwSdRIjPecYHIb5PwX0uQdM6jCBk5dA9Q8HxA==
ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1737455748; a=rsa-sha256; cv=none;
b=JGRq3NP9ACSgAZLecb/t6b5m1yuCz2Bf6TU91PqOr4g8LfYjn+hyxS0QUQ/L32uvL1NYCz
D0hDiKgZTg32Z/jdUzHm4M8/PTmQbD9xJeupcqn1+g0ldvUz0KlymBKWBfhRCJiwpzW75r
B3vqxyx7z099GaS9f2lQzYqUPHtxZyc6hq1tdblJX8YaHS+fS04YM+MvIDGUAX7Z4HsEr1
F6j0NLeWGAluJGyGbRqwRqkZdND0LExw156bEPP6++a/7ujsvqxeLtIfxWdAb5k4xb6AKE
wUEVVdQ923TiQ8oBdE5bipXxBtDehlZSPbw/pEAFyPjbeEzJHsHjdWos1USfjw==
ARC-Authentication-Results: i=1;
mx1.freebsd.org;
none
Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256)
(Client did not present a certificate)
by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YckBX4kV6z12lg;
Tue, 21 Jan 2025 10:35:48 +0000 (UTC)
(envelope-from git@FreeBSD.org)
Received: from gitrepo.freebsd.org ([127.0.1.44])
by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 50LAZmxJ054836;
Tue, 21 Jan 2025 10:35:48 GMT
(envelope-from git@gitrepo.freebsd.org)
Received: (from git@localhost)
by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 50LAZmoH054833;
Tue, 21 Jan 2025 10:35:48 GMT
(envelope-from git)
Date: Tue, 21 Jan 2025 10:35:48 GMT
Message-Id: <202501211035.50LAZmoH054833@gitrepo.freebsd.org>
To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org,
dev-commits-src-main@FreeBSD.org
From: Ruslan Bukin
Subject: git: 8f6b66a9d3f2 - main - riscv vmm: implement SBI RFNC
extension.
List-Id: Commit messages for all branches of the src repository
List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all
List-Help:
List-Post:
List-Subscribe:
List-Unsubscribe:
X-BeenThere: dev-commits-src-all@freebsd.org
Sender: owner-dev-commits-src-all@FreeBSD.org
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
X-Git-Committer: br
X-Git-Repository: src
X-Git-Refname: refs/heads/main
X-Git-Reftype: branch
X-Git-Commit: 8f6b66a9d3f20d9f32259a7a83fbfb4364c4fafa
Auto-Submitted: auto-generated
The branch main has been updated by br:
URL: https://cgit.FreeBSD.org/src/commit/?id=8f6b66a9d3f20d9f32259a7a83fbfb4364c4fafa
commit 8f6b66a9d3f20d9f32259a7a83fbfb4364c4fafa
Author: Ruslan Bukin
AuthorDate: 2025-01-21 10:15:43 +0000
Commit: Ruslan Bukin
CommitDate: 2025-01-21 10:35:19 +0000
riscv vmm: implement SBI RFNC extension.
The RISC-V SBI (Supervisor Binary Interface) RFNC (fence) extension is used
to provide a standardized mechanism for enforcing memory and I/O ordering
between different execution contexts or cores in a system. Specifically, it
allows supervisors (such as an operating system kernel) to request certain
synchronization operations across CPUs or harts (hardware threads) via the
SBI.
Differential Revision: https://reviews.freebsd.org/D48441
---
sys/conf/files.riscv | 1 +
sys/riscv/include/cpufunc.h | 15 ++++
sys/riscv/vmm/riscv.h | 22 +++++
sys/riscv/vmm/vmm_fence.c | 208 ++++++++++++++++++++++++++++++++++++++++++++
sys/riscv/vmm/vmm_fence.h | 43 +++++++++
sys/riscv/vmm/vmm_riscv.c | 9 ++
sys/riscv/vmm/vmm_sbi.c | 54 +++++++++---
7 files changed, 339 insertions(+), 13 deletions(-)
diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv
index 36eea03f29a1..e84f1367680f 100644
--- a/sys/conf/files.riscv
+++ b/sys/conf/files.riscv
@@ -86,6 +86,7 @@ riscv/riscv/vm_machdep.c standard
riscv/vmm/vmm.c optional vmm
riscv/vmm/vmm_aplic.c optional vmm
riscv/vmm/vmm_dev_machdep.c optional vmm
+riscv/vmm/vmm_fence.c optional vmm
riscv/vmm/vmm_instruction_emul.c optional vmm
riscv/vmm/vmm_riscv.c optional vmm
riscv/vmm/vmm_sbi.c optional vmm
diff --git a/sys/riscv/include/cpufunc.h b/sys/riscv/include/cpufunc.h
index 8f5b87d24ce3..75b22632c546 100644
--- a/sys/riscv/include/cpufunc.h
+++ b/sys/riscv/include/cpufunc.h
@@ -104,6 +104,21 @@ sfence_vma_page(uintptr_t addr)
__asm __volatile("sfence.vma %0" :: "r" (addr) : "memory");
}
+static __inline void
+sfence_vma_asid(uint64_t asid)
+{
+
+ __asm __volatile("sfence.vma x0, %0" :: "r" (asid) : "memory");
+}
+
+static __inline void
+sfence_vma_asid_page(uint64_t asid, uintptr_t addr)
+{
+
+ __asm __volatile("sfence.vma %0, %1" :: "r" (addr), "r" (asid)
+ : "memory");
+}
+
#define rdcycle() csr_read64(cycle)
#define rdtime() csr_read64(time)
#define rdinstret() csr_read64(instret)
diff --git a/sys/riscv/vmm/riscv.h b/sys/riscv/vmm/riscv.h
index f3665d33a386..793c61534cee 100644
--- a/sys/riscv/vmm/riscv.h
+++ b/sys/riscv/vmm/riscv.h
@@ -67,6 +67,20 @@ struct hypcsr {
uint64_t senvcfg;
};
+enum vmm_fence_type {
+ VMM_RISCV_FENCE_INVALID = 0,
+ VMM_RISCV_FENCE_I,
+ VMM_RISCV_FENCE_VMA,
+ VMM_RISCV_FENCE_VMA_ASID,
+};
+
+struct vmm_fence {
+ enum vmm_fence_type type;
+ size_t start;
+ size_t size;
+ uint64_t asid;
+};
+
struct hypctx {
struct hypregs host_regs;
struct hypregs guest_regs;
@@ -82,6 +96,14 @@ struct hypctx {
int ipi_pending;
int interrupts_pending;
struct vtimer vtimer;
+
+ struct vmm_fence *fence_queue;
+ struct mtx fence_queue_mtx;
+ int fence_queue_head;
+ int fence_queue_tail;
+#define FENCE_REQ_I (1 << 0)
+#define FENCE_REQ_VMA (1 << 1)
+ int fence_req;
};
struct hyp {
diff --git a/sys/riscv/vmm/vmm_fence.c b/sys/riscv/vmm/vmm_fence.c
new file mode 100644
index 000000000000..6bba3f4b5dfe
--- /dev/null
+++ b/sys/riscv/vmm/vmm_fence.c
@@ -0,0 +1,208 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Ruslan Bukin
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory (Department of Computer Science and Technology) under Innovate
+ * UK project 105694, "Digital Security by Design (DSbD) Technology Platform
+ * Prototype".
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "riscv.h"
+#include "vmm_fence.h"
+
+static bool
+vmm_fence_dequeue(struct hypctx *hypctx, struct vmm_fence *new_fence)
+{
+ struct vmm_fence *queue;
+ struct vmm_fence *fence;
+
+ mtx_lock_spin(&hypctx->fence_queue_mtx);
+ queue = hypctx->fence_queue;
+ fence = &queue[hypctx->fence_queue_head];
+ if (fence->type != VMM_RISCV_FENCE_INVALID) {
+ *new_fence = *fence;
+ fence->type = VMM_RISCV_FENCE_INVALID;
+ hypctx->fence_queue_head =
+ (hypctx->fence_queue_head + 1) % VMM_FENCE_QUEUE_SIZE;
+ } else {
+ mtx_unlock_spin(&hypctx->fence_queue_mtx);
+ return (false);
+ }
+ mtx_unlock_spin(&hypctx->fence_queue_mtx);
+
+ return (true);
+}
+
+static bool
+vmm_fence_enqueue(struct hypctx *hypctx, struct vmm_fence *new_fence)
+{
+ struct vmm_fence *queue;
+ struct vmm_fence *fence;
+
+ mtx_lock_spin(&hypctx->fence_queue_mtx);
+ queue = hypctx->fence_queue;
+ fence = &queue[hypctx->fence_queue_tail];
+ if (fence->type == VMM_RISCV_FENCE_INVALID) {
+ *fence = *new_fence;
+ hypctx->fence_queue_tail =
+ (hypctx->fence_queue_tail + 1) % VMM_FENCE_QUEUE_SIZE;
+ } else {
+ mtx_unlock_spin(&hypctx->fence_queue_mtx);
+ return (false);
+ }
+ mtx_unlock_spin(&hypctx->fence_queue_mtx);
+
+ return (true);
+}
+
+static void
+vmm_fence_process_one(struct vmm_fence *fence)
+{
+ uint64_t va;
+
+ KASSERT(fence->type == VMM_RISCV_FENCE_VMA ||
+ fence->type == VMM_RISCV_FENCE_VMA_ASID,
+ ("%s: wrong fence type %d", __func__, fence->type));
+
+ switch (fence->type) {
+ case VMM_RISCV_FENCE_VMA:
+ for (va = fence->start; va < fence->start + fence->size;
+ va += PAGE_SIZE)
+ sfence_vma_page(va);
+ break;
+ case VMM_RISCV_FENCE_VMA_ASID:
+ if (fence->start == 0 && fence->size == 0)
+ sfence_vma_asid(fence->asid);
+ else
+ for (va = fence->start; va < fence->start + fence->size;
+ va += PAGE_SIZE)
+ sfence_vma_asid_page(fence->asid, va);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+vmm_fence_process(struct hypctx *hypctx)
+{
+ struct vmm_fence fence;
+ int pending;
+
+ pending = atomic_readandclear_32(&hypctx->fence_req);
+
+ KASSERT((pending & ~(FENCE_REQ_I | FENCE_REQ_VMA)) == 0,
+ ("wrong fence bit mask"));
+
+ if (pending & FENCE_REQ_I)
+ fence_i();
+
+ if (pending & FENCE_REQ_VMA)
+ sfence_vma();
+
+ while (vmm_fence_dequeue(hypctx, &fence) == true)
+ vmm_fence_process_one(&fence);
+}
+
+void
+vmm_fence_add(struct vm *vm, cpuset_t *cpus, struct vmm_fence *fence)
+{
+ struct hypctx *hypctx;
+ cpuset_t running_cpus;
+ struct vcpu *vcpu;
+ uint16_t maxcpus;
+ int hostcpu;
+ int state;
+ bool enq;
+ int i;
+
+ CPU_ZERO(&running_cpus);
+
+ maxcpus = vm_get_maxcpus(vm);
+ for (i = 0; i < maxcpus; i++) {
+ if (!CPU_ISSET(i, cpus))
+ continue;
+ vcpu = vm_vcpu(vm, i);
+ hypctx = vcpu_get_cookie(vcpu);
+
+ enq = false;
+
+ /* No need to enqueue fences i and vma global. */
+ switch (fence->type) {
+ case VMM_RISCV_FENCE_I:
+ atomic_set_32(&hypctx->fence_req, FENCE_REQ_I);
+ break;
+ case VMM_RISCV_FENCE_VMA:
+ if (fence->start == 0 && fence->size == 0)
+ atomic_set_32(&hypctx->fence_req,
+ FENCE_REQ_VMA);
+ else
+ enq = true;
+ break;
+ case VMM_RISCV_FENCE_VMA_ASID:
+ enq = true;
+ break;
+ default:
+ KASSERT(0, ("%s: wrong fence type %d", __func__,
+ fence->type));
+ break;
+ }
+
+ /*
+ * Try to enqueue. In case of failure use more conservative
+ * request.
+ */
+ if (enq)
+ if (vmm_fence_enqueue(hypctx, fence) == false)
+ atomic_set_32(&hypctx->fence_req,
+ FENCE_REQ_VMA);
+
+ mb();
+
+ state = vcpu_get_state(vcpu, &hostcpu);
+ if (state == VCPU_RUNNING)
+ CPU_SET(hostcpu, &running_cpus);
+ }
+
+ /*
+ * Interrupt other cores. On reception of IPI they will leave guest.
+ * On entry back to the guest they will process fence request.
+ *
+ * If vcpu migrates to another cpu right here, it should process
+ * all fences on entry to the guest as well.
+ */
+ if (!CPU_EMPTY(&running_cpus))
+ smp_rendezvous_cpus(running_cpus, NULL, NULL, NULL, NULL);
+}
diff --git a/sys/riscv/vmm/vmm_fence.h b/sys/riscv/vmm/vmm_fence.h
new file mode 100644
index 000000000000..05d4466fd634
--- /dev/null
+++ b/sys/riscv/vmm/vmm_fence.h
@@ -0,0 +1,43 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Ruslan Bukin
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory (Department of Computer Science and Technology) under Innovate
+ * UK project 105694, "Digital Security by Design (DSbD) Technology Platform
+ * Prototype".
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _VMM_FENCE_H_
+#define _VMM_FENCE_H_
+
+struct hypctx;
+
+#define VMM_FENCE_QUEUE_SIZE 128
+
+void vmm_fence_process(struct hypctx *hypctx);
+void vmm_fence_add(struct vm *vm, cpuset_t *cpus, struct vmm_fence *fence);
+
+#endif /* !_VMM_FENCE_H_ */
diff --git a/sys/riscv/vmm/vmm_riscv.c b/sys/riscv/vmm/vmm_riscv.c
index 6ac945dfa1d0..78250ae7c440 100644
--- a/sys/riscv/vmm/vmm_riscv.c
+++ b/sys/riscv/vmm/vmm_riscv.c
@@ -68,6 +68,7 @@
#include "riscv.h"
#include "vmm_aplic.h"
+#include "vmm_fence.h"
#include "vmm_stat.h"
MALLOC_DEFINE(M_HYP, "RISC-V VMM HYP", "RISC-V VMM HYP");
@@ -212,6 +213,11 @@ vmmops_vcpu_init(void *vmi, struct vcpu *vcpu1, int vcpuid)
hypctx->vcpu = vcpu1;
hypctx->guest_scounteren = HCOUNTEREN_CY | HCOUNTEREN_TM;
+ /* Fence queue. */
+ hypctx->fence_queue = mallocarray(VMM_FENCE_QUEUE_SIZE,
+ sizeof(struct vmm_fence), M_HYP, M_WAITOK | M_ZERO);
+ mtx_init(&hypctx->fence_queue_mtx, "fence queue", NULL, MTX_SPIN);
+
/* sstatus */
hypctx->guest_regs.hyp_sstatus = SSTATUS_SPP | SSTATUS_SPIE;
hypctx->guest_regs.hyp_sstatus |= SSTATUS_FS_INITIAL;
@@ -659,6 +665,7 @@ vmmops_run(void *vcpui, register_t pc, pmap_t pmap, struct vm_eventinfo *evinfo)
riscv_set_active_vcpu(hypctx);
aplic_flush_hwstate(hypctx);
riscv_sync_interrupts(hypctx);
+ vmm_fence_process(hypctx);
dprintf("%s: Entering guest VM, vsatp %lx, ss %lx hs %lx\n",
__func__, csr_read(vsatp), hypctx->guest_regs.hyp_sstatus,
@@ -740,6 +747,8 @@ vmmops_vcpu_cleanup(void *vcpui)
aplic_cpucleanup(hypctx);
+ mtx_destroy(&hypctx->fence_queue_mtx);
+ free(hypctx->fence_queue, M_HYP);
free(hypctx, M_HYP);
}
diff --git a/sys/riscv/vmm/vmm_sbi.c b/sys/riscv/vmm/vmm_sbi.c
index 63dcf9b4a7ae..586eb7c4d41c 100644
--- a/sys/riscv/vmm/vmm_sbi.c
+++ b/sys/riscv/vmm/vmm_sbi.c
@@ -58,39 +58,65 @@
#include
#include "riscv.h"
+#include "vmm_fence.h"
static int
vmm_sbi_handle_rfnc(struct vcpu *vcpu, struct hypctx *hypctx)
{
- uint64_t hart_mask __unused;
- uint64_t start __unused;
- uint64_t size __unused;
- uint64_t asid __unused;
+ struct vmm_fence fence;
+ uint64_t hart_mask;
+ uint64_t hart_mask_base;
uint64_t func_id;
+ struct hyp *hyp;
+ uint16_t maxcpus;
+ cpuset_t cpus;
+ int vcpu_id;
+ int i;
func_id = hypctx->guest_regs.hyp_a[6];
hart_mask = hypctx->guest_regs.hyp_a[0];
- start = hypctx->guest_regs.hyp_a[2];
- size = hypctx->guest_regs.hyp_a[3];
- asid = hypctx->guest_regs.hyp_a[4];
+ hart_mask_base = hypctx->guest_regs.hyp_a[1];
- dprintf("%s: %ld hart_mask %lx start %lx size %lx\n", __func__,
- func_id, hart_mask, start, size);
+ /* Construct vma_fence. */
- /* TODO: implement remote sfence. */
+ fence.start = hypctx->guest_regs.hyp_a[2];
+ fence.size = hypctx->guest_regs.hyp_a[3];
+ fence.asid = hypctx->guest_regs.hyp_a[4];
switch (func_id) {
case SBI_RFNC_REMOTE_FENCE_I:
+ fence.type = VMM_RISCV_FENCE_I;
break;
case SBI_RFNC_REMOTE_SFENCE_VMA:
+ fence.type = VMM_RISCV_FENCE_VMA;
break;
case SBI_RFNC_REMOTE_SFENCE_VMA_ASID:
+ fence.type = VMM_RISCV_FENCE_VMA_ASID;
break;
default:
- break;
+ return (-1);
+ }
+
+ /* Construct cpuset_t from the mask supplied. */
+
+ CPU_ZERO(&cpus);
+ hyp = hypctx->hyp;
+ maxcpus = vm_get_maxcpus(hyp->vm);
+ for (i = 0; i < maxcpus; i++) {
+ vcpu = vm_vcpu(hyp->vm, i);
+ if (vcpu == NULL)
+ continue;
+ vcpu_id = vcpu_vcpuid(vcpu);
+ if (hart_mask_base != -1UL) {
+ if (vcpu_id < hart_mask_base)
+ continue;
+ if (!(hart_mask & (1UL << (vcpu_id - hart_mask_base))))
+ continue;
+ }
+ CPU_SET(i, &cpus);
}
- hypctx->guest_regs.hyp_a[0] = 0;
+ vmm_fence_add(hyp->vm, &cpus, &fence);
return (0);
}
@@ -172,6 +198,7 @@ vmm_sbi_ecall(struct vcpu *vcpu, bool *retu)
{
int sbi_extension_id __unused;
struct hypctx *hypctx;
+ int error;
hypctx = riscv_get_active_vcpu();
sbi_extension_id = hypctx->guest_regs.hyp_a[7];
@@ -188,7 +215,8 @@ vmm_sbi_ecall(struct vcpu *vcpu, bool *retu)
switch (sbi_extension_id) {
case SBI_EXT_ID_RFNC:
- vmm_sbi_handle_rfnc(vcpu, hypctx);
+ error = vmm_sbi_handle_rfnc(vcpu, hypctx);
+ hypctx->guest_regs.hyp_a[0] = error;
break;
case SBI_EXT_ID_TIME:
vmm_sbi_handle_time(vcpu, hypctx);