Commit dab55604 authored by Anup Patel's avatar Anup Patel Committed by Anup Patel
Browse files

RISC-V: KVM: Use nacl_csr_xyz() for accessing AIA CSRs



When running under some other hypervisor, prefer nacl_csr_xyz()
for accessing AIA CSRs in the run-loop. This makes CSR access
faster whenever SBI nested acceleration is available.

Signed-off-by: default avatarAnup Patel <apatel@ventanamicro.com>
Reviewed-by: default avatarAtish Patra <atishp@rivosinc.com>
Link: https://lore.kernel.org/r/20241020194734.58686-11-apatel@ventanamicro.com


Signed-off-by: default avatarAnup Patel <anup@brainfault.org>
parent e28e6b69
Loading
Loading
Loading
Loading
+63 −34
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/percpu.h>
#include <linux/spinlock.h>
#include <asm/cpufeature.h>
#include <asm/kvm_nacl.h>

struct aia_hgei_control {
	raw_spinlock_t lock;
@@ -88,7 +89,7 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;

	if (kvm_riscv_aia_available())
		csr->vsieh = csr_read(CSR_VSIEH);
		csr->vsieh = ncsr_read(CSR_VSIEH);
}
#endif

@@ -115,7 +116,7 @@ bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)

	hgei = aia_find_hgei(vcpu);
	if (hgei > 0)
		return !!(csr_read(CSR_HGEIP) & BIT(hgei));
		return !!(ncsr_read(CSR_HGEIP) & BIT(hgei));

	return false;
}
@@ -128,18 +129,31 @@ void kvm_riscv_vcpu_aia_update_hvip(struct kvm_vcpu *vcpu)
		return;

#ifdef CONFIG_32BIT
	csr_write(CSR_HVIPH, vcpu->arch.aia_context.guest_csr.hviph);
	ncsr_write(CSR_HVIPH, vcpu->arch.aia_context.guest_csr.hviph);
#endif
	csr_write(CSR_HVICTL, aia_hvictl_value(!!(csr->hvip & BIT(IRQ_VS_EXT))));
	ncsr_write(CSR_HVICTL, aia_hvictl_value(!!(csr->hvip & BIT(IRQ_VS_EXT))));
}

void kvm_riscv_vcpu_aia_load(struct kvm_vcpu *vcpu, int cpu)
{
	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
	void *nsh;

	if (!kvm_riscv_aia_available())
		return;

	if (kvm_riscv_nacl_sync_csr_available()) {
		nsh = nacl_shmem();
		nacl_csr_write(nsh, CSR_VSISELECT, csr->vsiselect);
		nacl_csr_write(nsh, CSR_HVIPRIO1, csr->hviprio1);
		nacl_csr_write(nsh, CSR_HVIPRIO2, csr->hviprio2);
#ifdef CONFIG_32BIT
		nacl_csr_write(nsh, CSR_VSIEH, csr->vsieh);
		nacl_csr_write(nsh, CSR_HVIPH, csr->hviph);
		nacl_csr_write(nsh, CSR_HVIPRIO1H, csr->hviprio1h);
		nacl_csr_write(nsh, CSR_HVIPRIO2H, csr->hviprio2h);
#endif
	} else {
		csr_write(CSR_VSISELECT, csr->vsiselect);
		csr_write(CSR_HVIPRIO1, csr->hviprio1);
		csr_write(CSR_HVIPRIO2, csr->hviprio2);
@@ -150,14 +164,28 @@ void kvm_riscv_vcpu_aia_load(struct kvm_vcpu *vcpu, int cpu)
		csr_write(CSR_HVIPRIO2H, csr->hviprio2h);
#endif
	}
}

void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu)
{
	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
	void *nsh;

	if (!kvm_riscv_aia_available())
		return;

	if (kvm_riscv_nacl_available()) {
		nsh = nacl_shmem();
		csr->vsiselect = nacl_csr_read(nsh, CSR_VSISELECT);
		csr->hviprio1 = nacl_csr_read(nsh, CSR_HVIPRIO1);
		csr->hviprio2 = nacl_csr_read(nsh, CSR_HVIPRIO2);
#ifdef CONFIG_32BIT
		csr->vsieh = nacl_csr_read(nsh, CSR_VSIEH);
		csr->hviph = nacl_csr_read(nsh, CSR_HVIPH);
		csr->hviprio1h = nacl_csr_read(nsh, CSR_HVIPRIO1H);
		csr->hviprio2h = nacl_csr_read(nsh, CSR_HVIPRIO2H);
#endif
	} else {
		csr->vsiselect = csr_read(CSR_VSISELECT);
		csr->hviprio1 = csr_read(CSR_HVIPRIO1);
		csr->hviprio2 = csr_read(CSR_HVIPRIO2);
@@ -168,6 +196,7 @@ void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu)
		csr->hviprio2h = csr_read(CSR_HVIPRIO2H);
#endif
	}
}

int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
			       unsigned long reg_num,
@@ -250,20 +279,20 @@ static u8 aia_get_iprio8(struct kvm_vcpu *vcpu, unsigned int irq)

	switch (bitpos / BITS_PER_LONG) {
	case 0:
		hviprio = csr_read(CSR_HVIPRIO1);
		hviprio = ncsr_read(CSR_HVIPRIO1);
		break;
	case 1:
#ifndef CONFIG_32BIT
		hviprio = csr_read(CSR_HVIPRIO2);
		hviprio = ncsr_read(CSR_HVIPRIO2);
		break;
#else
		hviprio = csr_read(CSR_HVIPRIO1H);
		hviprio = ncsr_read(CSR_HVIPRIO1H);
		break;
	case 2:
		hviprio = csr_read(CSR_HVIPRIO2);
		hviprio = ncsr_read(CSR_HVIPRIO2);
		break;
	case 3:
		hviprio = csr_read(CSR_HVIPRIO2H);
		hviprio = ncsr_read(CSR_HVIPRIO2H);
		break;
#endif
	default:
@@ -283,20 +312,20 @@ static void aia_set_iprio8(struct kvm_vcpu *vcpu, unsigned int irq, u8 prio)

	switch (bitpos / BITS_PER_LONG) {
	case 0:
		hviprio = csr_read(CSR_HVIPRIO1);
		hviprio = ncsr_read(CSR_HVIPRIO1);
		break;
	case 1:
#ifndef CONFIG_32BIT
		hviprio = csr_read(CSR_HVIPRIO2);
		hviprio = ncsr_read(CSR_HVIPRIO2);
		break;
#else
		hviprio = csr_read(CSR_HVIPRIO1H);
		hviprio = ncsr_read(CSR_HVIPRIO1H);
		break;
	case 2:
		hviprio = csr_read(CSR_HVIPRIO2);
		hviprio = ncsr_read(CSR_HVIPRIO2);
		break;
	case 3:
		hviprio = csr_read(CSR_HVIPRIO2H);
		hviprio = ncsr_read(CSR_HVIPRIO2H);
		break;
#endif
	default:
@@ -308,20 +337,20 @@ static void aia_set_iprio8(struct kvm_vcpu *vcpu, unsigned int irq, u8 prio)

	switch (bitpos / BITS_PER_LONG) {
	case 0:
		csr_write(CSR_HVIPRIO1, hviprio);
		ncsr_write(CSR_HVIPRIO1, hviprio);
		break;
	case 1:
#ifndef CONFIG_32BIT
		csr_write(CSR_HVIPRIO2, hviprio);
		ncsr_write(CSR_HVIPRIO2, hviprio);
		break;
#else
		csr_write(CSR_HVIPRIO1H, hviprio);
		ncsr_write(CSR_HVIPRIO1H, hviprio);
		break;
	case 2:
		csr_write(CSR_HVIPRIO2, hviprio);
		ncsr_write(CSR_HVIPRIO2, hviprio);
		break;
	case 3:
		csr_write(CSR_HVIPRIO2H, hviprio);
		ncsr_write(CSR_HVIPRIO2H, hviprio);
		break;
#endif
	default:
@@ -377,7 +406,7 @@ int kvm_riscv_vcpu_aia_rmw_ireg(struct kvm_vcpu *vcpu, unsigned int csr_num,
		return KVM_INSN_ILLEGAL_TRAP;

	/* First try to emulate in kernel space */
	isel = csr_read(CSR_VSISELECT) & ISELECT_MASK;
	isel = ncsr_read(CSR_VSISELECT) & ISELECT_MASK;
	if (isel >= ISELECT_IPRIO0 && isel <= ISELECT_IPRIO15)
		return aia_rmw_iprio(vcpu, isel, val, new_val, wr_mask);
	else if (isel >= IMSIC_FIRST && isel <= IMSIC_LAST &&