162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2022 Ventana Micro Systems Inc.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/bitmap.h>
762306a36Sopenharmony_ci#include <linux/cpumask.h>
862306a36Sopenharmony_ci#include <linux/errno.h>
962306a36Sopenharmony_ci#include <linux/err.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/smp.h>
1262306a36Sopenharmony_ci#include <linux/kvm_host.h>
1362306a36Sopenharmony_ci#include <asm/cacheflush.h>
1462306a36Sopenharmony_ci#include <asm/csr.h>
1562306a36Sopenharmony_ci#include <asm/hwcap.h>
1662306a36Sopenharmony_ci#include <asm/insn-def.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define has_svinval()	riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_civoid kvm_riscv_local_hfence_gvma_vmid_gpa(unsigned long vmid,
2162306a36Sopenharmony_ci					  gpa_t gpa, gpa_t gpsz,
2262306a36Sopenharmony_ci					  unsigned long order)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	gpa_t pos;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	if (PTRS_PER_PTE < (gpsz >> order)) {
2762306a36Sopenharmony_ci		kvm_riscv_local_hfence_gvma_vmid_all(vmid);
2862306a36Sopenharmony_ci		return;
2962306a36Sopenharmony_ci	}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	if (has_svinval()) {
3262306a36Sopenharmony_ci		asm volatile (SFENCE_W_INVAL() ::: "memory");
3362306a36Sopenharmony_ci		for (pos = gpa; pos < (gpa + gpsz); pos += BIT(order))
3462306a36Sopenharmony_ci			asm volatile (HINVAL_GVMA(%0, %1)
3562306a36Sopenharmony_ci			: : "r" (pos >> 2), "r" (vmid) : "memory");
3662306a36Sopenharmony_ci		asm volatile (SFENCE_INVAL_IR() ::: "memory");
3762306a36Sopenharmony_ci	} else {
3862306a36Sopenharmony_ci		for (pos = gpa; pos < (gpa + gpsz); pos += BIT(order))
3962306a36Sopenharmony_ci			asm volatile (HFENCE_GVMA(%0, %1)
4062306a36Sopenharmony_ci			: : "r" (pos >> 2), "r" (vmid) : "memory");
4162306a36Sopenharmony_ci	}
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_civoid kvm_riscv_local_hfence_gvma_vmid_all(unsigned long vmid)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	asm volatile(HFENCE_GVMA(zero, %0) : : "r" (vmid) : "memory");
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_civoid kvm_riscv_local_hfence_gvma_gpa(gpa_t gpa, gpa_t gpsz,
5062306a36Sopenharmony_ci				     unsigned long order)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	gpa_t pos;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	if (PTRS_PER_PTE < (gpsz >> order)) {
5562306a36Sopenharmony_ci		kvm_riscv_local_hfence_gvma_all();
5662306a36Sopenharmony_ci		return;
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	if (has_svinval()) {
6062306a36Sopenharmony_ci		asm volatile (SFENCE_W_INVAL() ::: "memory");
6162306a36Sopenharmony_ci		for (pos = gpa; pos < (gpa + gpsz); pos += BIT(order))
6262306a36Sopenharmony_ci			asm volatile(HINVAL_GVMA(%0, zero)
6362306a36Sopenharmony_ci			: : "r" (pos >> 2) : "memory");
6462306a36Sopenharmony_ci		asm volatile (SFENCE_INVAL_IR() ::: "memory");
6562306a36Sopenharmony_ci	} else {
6662306a36Sopenharmony_ci		for (pos = gpa; pos < (gpa + gpsz); pos += BIT(order))
6762306a36Sopenharmony_ci			asm volatile(HFENCE_GVMA(%0, zero)
6862306a36Sopenharmony_ci			: : "r" (pos >> 2) : "memory");
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_civoid kvm_riscv_local_hfence_gvma_all(void)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	asm volatile(HFENCE_GVMA(zero, zero) : : : "memory");
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_civoid kvm_riscv_local_hfence_vvma_asid_gva(unsigned long vmid,
7862306a36Sopenharmony_ci					  unsigned long asid,
7962306a36Sopenharmony_ci					  unsigned long gva,
8062306a36Sopenharmony_ci					  unsigned long gvsz,
8162306a36Sopenharmony_ci					  unsigned long order)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	unsigned long pos, hgatp;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	if (PTRS_PER_PTE < (gvsz >> order)) {
8662306a36Sopenharmony_ci		kvm_riscv_local_hfence_vvma_asid_all(vmid, asid);
8762306a36Sopenharmony_ci		return;
8862306a36Sopenharmony_ci	}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	hgatp = csr_swap(CSR_HGATP, vmid << HGATP_VMID_SHIFT);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	if (has_svinval()) {
9362306a36Sopenharmony_ci		asm volatile (SFENCE_W_INVAL() ::: "memory");
9462306a36Sopenharmony_ci		for (pos = gva; pos < (gva + gvsz); pos += BIT(order))
9562306a36Sopenharmony_ci			asm volatile(HINVAL_VVMA(%0, %1)
9662306a36Sopenharmony_ci			: : "r" (pos), "r" (asid) : "memory");
9762306a36Sopenharmony_ci		asm volatile (SFENCE_INVAL_IR() ::: "memory");
9862306a36Sopenharmony_ci	} else {
9962306a36Sopenharmony_ci		for (pos = gva; pos < (gva + gvsz); pos += BIT(order))
10062306a36Sopenharmony_ci			asm volatile(HFENCE_VVMA(%0, %1)
10162306a36Sopenharmony_ci			: : "r" (pos), "r" (asid) : "memory");
10262306a36Sopenharmony_ci	}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	csr_write(CSR_HGATP, hgatp);
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_civoid kvm_riscv_local_hfence_vvma_asid_all(unsigned long vmid,
10862306a36Sopenharmony_ci					  unsigned long asid)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	unsigned long hgatp;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	hgatp = csr_swap(CSR_HGATP, vmid << HGATP_VMID_SHIFT);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	asm volatile(HFENCE_VVMA(zero, %0) : : "r" (asid) : "memory");
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	csr_write(CSR_HGATP, hgatp);
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_civoid kvm_riscv_local_hfence_vvma_gva(unsigned long vmid,
12062306a36Sopenharmony_ci				     unsigned long gva, unsigned long gvsz,
12162306a36Sopenharmony_ci				     unsigned long order)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	unsigned long pos, hgatp;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	if (PTRS_PER_PTE < (gvsz >> order)) {
12662306a36Sopenharmony_ci		kvm_riscv_local_hfence_vvma_all(vmid);
12762306a36Sopenharmony_ci		return;
12862306a36Sopenharmony_ci	}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	hgatp = csr_swap(CSR_HGATP, vmid << HGATP_VMID_SHIFT);
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	if (has_svinval()) {
13362306a36Sopenharmony_ci		asm volatile (SFENCE_W_INVAL() ::: "memory");
13462306a36Sopenharmony_ci		for (pos = gva; pos < (gva + gvsz); pos += BIT(order))
13562306a36Sopenharmony_ci			asm volatile(HINVAL_VVMA(%0, zero)
13662306a36Sopenharmony_ci			: : "r" (pos) : "memory");
13762306a36Sopenharmony_ci		asm volatile (SFENCE_INVAL_IR() ::: "memory");
13862306a36Sopenharmony_ci	} else {
13962306a36Sopenharmony_ci		for (pos = gva; pos < (gva + gvsz); pos += BIT(order))
14062306a36Sopenharmony_ci			asm volatile(HFENCE_VVMA(%0, zero)
14162306a36Sopenharmony_ci			: : "r" (pos) : "memory");
14262306a36Sopenharmony_ci	}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	csr_write(CSR_HGATP, hgatp);
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_civoid kvm_riscv_local_hfence_vvma_all(unsigned long vmid)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	unsigned long hgatp;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	hgatp = csr_swap(CSR_HGATP, vmid << HGATP_VMID_SHIFT);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	asm volatile(HFENCE_VVMA(zero, zero) : : : "memory");
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	csr_write(CSR_HGATP, hgatp);
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_civoid kvm_riscv_local_tlb_sanitize(struct kvm_vcpu *vcpu)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	unsigned long vmid;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	if (!kvm_riscv_gstage_vmid_bits() ||
16362306a36Sopenharmony_ci	    vcpu->arch.last_exit_cpu == vcpu->cpu)
16462306a36Sopenharmony_ci		return;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	/*
16762306a36Sopenharmony_ci	 * On RISC-V platforms with hardware VMID support, we share same
16862306a36Sopenharmony_ci	 * VMID for all VCPUs of a particular Guest/VM. This means we might
16962306a36Sopenharmony_ci	 * have stale G-stage TLB entries on the current Host CPU due to
17062306a36Sopenharmony_ci	 * some other VCPU of the same Guest which ran previously on the
17162306a36Sopenharmony_ci	 * current Host CPU.
17262306a36Sopenharmony_ci	 *
17362306a36Sopenharmony_ci	 * To cleanup stale TLB entries, we simply flush all G-stage TLB
17462306a36Sopenharmony_ci	 * entries by VMID whenever underlying Host CPU changes for a VCPU.
17562306a36Sopenharmony_ci	 */
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
17862306a36Sopenharmony_ci	kvm_riscv_local_hfence_gvma_vmid_all(vmid);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_civoid kvm_riscv_fence_i_process(struct kvm_vcpu *vcpu)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_FENCE_I_RCVD);
18462306a36Sopenharmony_ci	local_flush_icache_all();
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_civoid kvm_riscv_hfence_gvma_vmid_all_process(struct kvm_vcpu *vcpu)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	struct kvm_vmid *vmid;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	vmid = &vcpu->kvm->arch.vmid;
19262306a36Sopenharmony_ci	kvm_riscv_local_hfence_gvma_vmid_all(READ_ONCE(vmid->vmid));
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_civoid kvm_riscv_hfence_vvma_all_process(struct kvm_vcpu *vcpu)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	struct kvm_vmid *vmid;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	vmid = &vcpu->kvm->arch.vmid;
20062306a36Sopenharmony_ci	kvm_riscv_local_hfence_vvma_all(READ_ONCE(vmid->vmid));
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cistatic bool vcpu_hfence_dequeue(struct kvm_vcpu *vcpu,
20462306a36Sopenharmony_ci				struct kvm_riscv_hfence *out_data)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	bool ret = false;
20762306a36Sopenharmony_ci	struct kvm_vcpu_arch *varch = &vcpu->arch;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	spin_lock(&varch->hfence_lock);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	if (varch->hfence_queue[varch->hfence_head].type) {
21262306a36Sopenharmony_ci		memcpy(out_data, &varch->hfence_queue[varch->hfence_head],
21362306a36Sopenharmony_ci		       sizeof(*out_data));
21462306a36Sopenharmony_ci		varch->hfence_queue[varch->hfence_head].type = 0;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci		varch->hfence_head++;
21762306a36Sopenharmony_ci		if (varch->hfence_head == KVM_RISCV_VCPU_MAX_HFENCE)
21862306a36Sopenharmony_ci			varch->hfence_head = 0;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci		ret = true;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	spin_unlock(&varch->hfence_lock);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	return ret;
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic bool vcpu_hfence_enqueue(struct kvm_vcpu *vcpu,
22962306a36Sopenharmony_ci				const struct kvm_riscv_hfence *data)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	bool ret = false;
23262306a36Sopenharmony_ci	struct kvm_vcpu_arch *varch = &vcpu->arch;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	spin_lock(&varch->hfence_lock);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	if (!varch->hfence_queue[varch->hfence_tail].type) {
23762306a36Sopenharmony_ci		memcpy(&varch->hfence_queue[varch->hfence_tail],
23862306a36Sopenharmony_ci		       data, sizeof(*data));
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		varch->hfence_tail++;
24162306a36Sopenharmony_ci		if (varch->hfence_tail == KVM_RISCV_VCPU_MAX_HFENCE)
24262306a36Sopenharmony_ci			varch->hfence_tail = 0;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci		ret = true;
24562306a36Sopenharmony_ci	}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	spin_unlock(&varch->hfence_lock);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return ret;
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_civoid kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	struct kvm_riscv_hfence d = { 0 };
25562306a36Sopenharmony_ci	struct kvm_vmid *v = &vcpu->kvm->arch.vmid;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	while (vcpu_hfence_dequeue(vcpu, &d)) {
25862306a36Sopenharmony_ci		switch (d.type) {
25962306a36Sopenharmony_ci		case KVM_RISCV_HFENCE_UNKNOWN:
26062306a36Sopenharmony_ci			break;
26162306a36Sopenharmony_ci		case KVM_RISCV_HFENCE_GVMA_VMID_GPA:
26262306a36Sopenharmony_ci			kvm_riscv_local_hfence_gvma_vmid_gpa(
26362306a36Sopenharmony_ci						READ_ONCE(v->vmid),
26462306a36Sopenharmony_ci						d.addr, d.size, d.order);
26562306a36Sopenharmony_ci			break;
26662306a36Sopenharmony_ci		case KVM_RISCV_HFENCE_VVMA_ASID_GVA:
26762306a36Sopenharmony_ci			kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD);
26862306a36Sopenharmony_ci			kvm_riscv_local_hfence_vvma_asid_gva(
26962306a36Sopenharmony_ci						READ_ONCE(v->vmid), d.asid,
27062306a36Sopenharmony_ci						d.addr, d.size, d.order);
27162306a36Sopenharmony_ci			break;
27262306a36Sopenharmony_ci		case KVM_RISCV_HFENCE_VVMA_ASID_ALL:
27362306a36Sopenharmony_ci			kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD);
27462306a36Sopenharmony_ci			kvm_riscv_local_hfence_vvma_asid_all(
27562306a36Sopenharmony_ci						READ_ONCE(v->vmid), d.asid);
27662306a36Sopenharmony_ci			break;
27762306a36Sopenharmony_ci		case KVM_RISCV_HFENCE_VVMA_GVA:
27862306a36Sopenharmony_ci			kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_RCVD);
27962306a36Sopenharmony_ci			kvm_riscv_local_hfence_vvma_gva(
28062306a36Sopenharmony_ci						READ_ONCE(v->vmid),
28162306a36Sopenharmony_ci						d.addr, d.size, d.order);
28262306a36Sopenharmony_ci			break;
28362306a36Sopenharmony_ci		default:
28462306a36Sopenharmony_ci			break;
28562306a36Sopenharmony_ci		}
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic void make_xfence_request(struct kvm *kvm,
29062306a36Sopenharmony_ci				unsigned long hbase, unsigned long hmask,
29162306a36Sopenharmony_ci				unsigned int req, unsigned int fallback_req,
29262306a36Sopenharmony_ci				const struct kvm_riscv_hfence *data)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	unsigned long i;
29562306a36Sopenharmony_ci	struct kvm_vcpu *vcpu;
29662306a36Sopenharmony_ci	unsigned int actual_req = req;
29762306a36Sopenharmony_ci	DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	bitmap_zero(vcpu_mask, KVM_MAX_VCPUS);
30062306a36Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
30162306a36Sopenharmony_ci		if (hbase != -1UL) {
30262306a36Sopenharmony_ci			if (vcpu->vcpu_id < hbase)
30362306a36Sopenharmony_ci				continue;
30462306a36Sopenharmony_ci			if (!(hmask & (1UL << (vcpu->vcpu_id - hbase))))
30562306a36Sopenharmony_ci				continue;
30662306a36Sopenharmony_ci		}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		bitmap_set(vcpu_mask, i, 1);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci		if (!data || !data->type)
31162306a36Sopenharmony_ci			continue;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci		/*
31462306a36Sopenharmony_ci		 * Enqueue hfence data to VCPU hfence queue. If we don't
31562306a36Sopenharmony_ci		 * have space in the VCPU hfence queue then fallback to
31662306a36Sopenharmony_ci		 * a more conservative hfence request.
31762306a36Sopenharmony_ci		 */
31862306a36Sopenharmony_ci		if (!vcpu_hfence_enqueue(vcpu, data))
31962306a36Sopenharmony_ci			actual_req = fallback_req;
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	kvm_make_vcpus_request_mask(kvm, actual_req, vcpu_mask);
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_civoid kvm_riscv_fence_i(struct kvm *kvm,
32662306a36Sopenharmony_ci		       unsigned long hbase, unsigned long hmask)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	make_xfence_request(kvm, hbase, hmask, KVM_REQ_FENCE_I,
32962306a36Sopenharmony_ci			    KVM_REQ_FENCE_I, NULL);
33062306a36Sopenharmony_ci}
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_civoid kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm,
33362306a36Sopenharmony_ci				    unsigned long hbase, unsigned long hmask,
33462306a36Sopenharmony_ci				    gpa_t gpa, gpa_t gpsz,
33562306a36Sopenharmony_ci				    unsigned long order)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	struct kvm_riscv_hfence data;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	data.type = KVM_RISCV_HFENCE_GVMA_VMID_GPA;
34062306a36Sopenharmony_ci	data.asid = 0;
34162306a36Sopenharmony_ci	data.addr = gpa;
34262306a36Sopenharmony_ci	data.size = gpsz;
34362306a36Sopenharmony_ci	data.order = order;
34462306a36Sopenharmony_ci	make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE,
34562306a36Sopenharmony_ci			    KVM_REQ_HFENCE_GVMA_VMID_ALL, &data);
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_civoid kvm_riscv_hfence_gvma_vmid_all(struct kvm *kvm,
34962306a36Sopenharmony_ci				    unsigned long hbase, unsigned long hmask)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE_GVMA_VMID_ALL,
35262306a36Sopenharmony_ci			    KVM_REQ_HFENCE_GVMA_VMID_ALL, NULL);
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_civoid kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm,
35662306a36Sopenharmony_ci				    unsigned long hbase, unsigned long hmask,
35762306a36Sopenharmony_ci				    unsigned long gva, unsigned long gvsz,
35862306a36Sopenharmony_ci				    unsigned long order, unsigned long asid)
35962306a36Sopenharmony_ci{
36062306a36Sopenharmony_ci	struct kvm_riscv_hfence data;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	data.type = KVM_RISCV_HFENCE_VVMA_ASID_GVA;
36362306a36Sopenharmony_ci	data.asid = asid;
36462306a36Sopenharmony_ci	data.addr = gva;
36562306a36Sopenharmony_ci	data.size = gvsz;
36662306a36Sopenharmony_ci	data.order = order;
36762306a36Sopenharmony_ci	make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE,
36862306a36Sopenharmony_ci			    KVM_REQ_HFENCE_VVMA_ALL, &data);
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_civoid kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm,
37262306a36Sopenharmony_ci				    unsigned long hbase, unsigned long hmask,
37362306a36Sopenharmony_ci				    unsigned long asid)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	struct kvm_riscv_hfence data;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	data.type = KVM_RISCV_HFENCE_VVMA_ASID_ALL;
37862306a36Sopenharmony_ci	data.asid = asid;
37962306a36Sopenharmony_ci	data.addr = data.size = data.order = 0;
38062306a36Sopenharmony_ci	make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE,
38162306a36Sopenharmony_ci			    KVM_REQ_HFENCE_VVMA_ALL, &data);
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_civoid kvm_riscv_hfence_vvma_gva(struct kvm *kvm,
38562306a36Sopenharmony_ci			       unsigned long hbase, unsigned long hmask,
38662306a36Sopenharmony_ci			       unsigned long gva, unsigned long gvsz,
38762306a36Sopenharmony_ci			       unsigned long order)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	struct kvm_riscv_hfence data;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	data.type = KVM_RISCV_HFENCE_VVMA_GVA;
39262306a36Sopenharmony_ci	data.asid = 0;
39362306a36Sopenharmony_ci	data.addr = gva;
39462306a36Sopenharmony_ci	data.size = gvsz;
39562306a36Sopenharmony_ci	data.order = order;
39662306a36Sopenharmony_ci	make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE,
39762306a36Sopenharmony_ci			    KVM_REQ_HFENCE_VVMA_ALL, &data);
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_civoid kvm_riscv_hfence_vvma_all(struct kvm *kvm,
40162306a36Sopenharmony_ci			       unsigned long hbase, unsigned long hmask)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE_VVMA_ALL,
40462306a36Sopenharmony_ci			    KVM_REQ_HFENCE_VVMA_ALL, NULL);
40562306a36Sopenharmony_ci}
406