mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-17 10:26:09 +00:00
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: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Atish Patra <atishp@rivosinc.com> Link: https://lore.kernel.org/r/20241020194734.58686-11-apatel@ventanamicro.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
parent
e28e6b6976
commit
dab55604ae
@ -16,6 +16,7 @@
|
|||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <asm/cpufeature.h>
|
#include <asm/cpufeature.h>
|
||||||
|
#include <asm/kvm_nacl.h>
|
||||||
|
|
||||||
struct aia_hgei_control {
|
struct aia_hgei_control {
|
||||||
raw_spinlock_t lock;
|
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;
|
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
|
||||||
|
|
||||||
if (kvm_riscv_aia_available())
|
if (kvm_riscv_aia_available())
|
||||||
csr->vsieh = csr_read(CSR_VSIEH);
|
csr->vsieh = ncsr_read(CSR_VSIEH);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -115,7 +116,7 @@ bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
|
|||||||
|
|
||||||
hgei = aia_find_hgei(vcpu);
|
hgei = aia_find_hgei(vcpu);
|
||||||
if (hgei > 0)
|
if (hgei > 0)
|
||||||
return !!(csr_read(CSR_HGEIP) & BIT(hgei));
|
return !!(ncsr_read(CSR_HGEIP) & BIT(hgei));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -128,45 +129,73 @@ void kvm_riscv_vcpu_aia_update_hvip(struct kvm_vcpu *vcpu)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef CONFIG_32BIT
|
#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
|
#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)
|
void kvm_riscv_vcpu_aia_load(struct kvm_vcpu *vcpu, int cpu)
|
||||||
{
|
{
|
||||||
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
|
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
|
||||||
|
void *nsh;
|
||||||
|
|
||||||
if (!kvm_riscv_aia_available())
|
if (!kvm_riscv_aia_available())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
csr_write(CSR_VSISELECT, csr->vsiselect);
|
if (kvm_riscv_nacl_sync_csr_available()) {
|
||||||
csr_write(CSR_HVIPRIO1, csr->hviprio1);
|
nsh = nacl_shmem();
|
||||||
csr_write(CSR_HVIPRIO2, csr->hviprio2);
|
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
|
#ifdef CONFIG_32BIT
|
||||||
csr_write(CSR_VSIEH, csr->vsieh);
|
nacl_csr_write(nsh, CSR_VSIEH, csr->vsieh);
|
||||||
csr_write(CSR_HVIPH, csr->hviph);
|
nacl_csr_write(nsh, CSR_HVIPH, csr->hviph);
|
||||||
csr_write(CSR_HVIPRIO1H, csr->hviprio1h);
|
nacl_csr_write(nsh, CSR_HVIPRIO1H, csr->hviprio1h);
|
||||||
csr_write(CSR_HVIPRIO2H, csr->hviprio2h);
|
nacl_csr_write(nsh, CSR_HVIPRIO2H, csr->hviprio2h);
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
|
csr_write(CSR_VSISELECT, csr->vsiselect);
|
||||||
|
csr_write(CSR_HVIPRIO1, csr->hviprio1);
|
||||||
|
csr_write(CSR_HVIPRIO2, csr->hviprio2);
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
|
csr_write(CSR_VSIEH, csr->vsieh);
|
||||||
|
csr_write(CSR_HVIPH, csr->hviph);
|
||||||
|
csr_write(CSR_HVIPRIO1H, csr->hviprio1h);
|
||||||
|
csr_write(CSR_HVIPRIO2H, csr->hviprio2h);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu)
|
void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
|
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
|
||||||
|
void *nsh;
|
||||||
|
|
||||||
if (!kvm_riscv_aia_available())
|
if (!kvm_riscv_aia_available())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
csr->vsiselect = csr_read(CSR_VSISELECT);
|
if (kvm_riscv_nacl_available()) {
|
||||||
csr->hviprio1 = csr_read(CSR_HVIPRIO1);
|
nsh = nacl_shmem();
|
||||||
csr->hviprio2 = csr_read(CSR_HVIPRIO2);
|
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
|
#ifdef CONFIG_32BIT
|
||||||
csr->vsieh = csr_read(CSR_VSIEH);
|
csr->vsieh = nacl_csr_read(nsh, CSR_VSIEH);
|
||||||
csr->hviph = csr_read(CSR_HVIPH);
|
csr->hviph = nacl_csr_read(nsh, CSR_HVIPH);
|
||||||
csr->hviprio1h = csr_read(CSR_HVIPRIO1H);
|
csr->hviprio1h = nacl_csr_read(nsh, CSR_HVIPRIO1H);
|
||||||
csr->hviprio2h = csr_read(CSR_HVIPRIO2H);
|
csr->hviprio2h = nacl_csr_read(nsh, CSR_HVIPRIO2H);
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
|
csr->vsiselect = csr_read(CSR_VSISELECT);
|
||||||
|
csr->hviprio1 = csr_read(CSR_HVIPRIO1);
|
||||||
|
csr->hviprio2 = csr_read(CSR_HVIPRIO2);
|
||||||
|
#ifdef CONFIG_32BIT
|
||||||
|
csr->vsieh = csr_read(CSR_VSIEH);
|
||||||
|
csr->hviph = csr_read(CSR_HVIPH);
|
||||||
|
csr->hviprio1h = csr_read(CSR_HVIPRIO1H);
|
||||||
|
csr->hviprio2h = csr_read(CSR_HVIPRIO2H);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
|
int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
|
||||||
@ -250,20 +279,20 @@ static u8 aia_get_iprio8(struct kvm_vcpu *vcpu, unsigned int irq)
|
|||||||
|
|
||||||
switch (bitpos / BITS_PER_LONG) {
|
switch (bitpos / BITS_PER_LONG) {
|
||||||
case 0:
|
case 0:
|
||||||
hviprio = csr_read(CSR_HVIPRIO1);
|
hviprio = ncsr_read(CSR_HVIPRIO1);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
#ifndef CONFIG_32BIT
|
#ifndef CONFIG_32BIT
|
||||||
hviprio = csr_read(CSR_HVIPRIO2);
|
hviprio = ncsr_read(CSR_HVIPRIO2);
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
hviprio = csr_read(CSR_HVIPRIO1H);
|
hviprio = ncsr_read(CSR_HVIPRIO1H);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
hviprio = csr_read(CSR_HVIPRIO2);
|
hviprio = ncsr_read(CSR_HVIPRIO2);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
hviprio = csr_read(CSR_HVIPRIO2H);
|
hviprio = ncsr_read(CSR_HVIPRIO2H);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
@ -283,20 +312,20 @@ static void aia_set_iprio8(struct kvm_vcpu *vcpu, unsigned int irq, u8 prio)
|
|||||||
|
|
||||||
switch (bitpos / BITS_PER_LONG) {
|
switch (bitpos / BITS_PER_LONG) {
|
||||||
case 0:
|
case 0:
|
||||||
hviprio = csr_read(CSR_HVIPRIO1);
|
hviprio = ncsr_read(CSR_HVIPRIO1);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
#ifndef CONFIG_32BIT
|
#ifndef CONFIG_32BIT
|
||||||
hviprio = csr_read(CSR_HVIPRIO2);
|
hviprio = ncsr_read(CSR_HVIPRIO2);
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
hviprio = csr_read(CSR_HVIPRIO1H);
|
hviprio = ncsr_read(CSR_HVIPRIO1H);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
hviprio = csr_read(CSR_HVIPRIO2);
|
hviprio = ncsr_read(CSR_HVIPRIO2);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
hviprio = csr_read(CSR_HVIPRIO2H);
|
hviprio = ncsr_read(CSR_HVIPRIO2H);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
@ -308,20 +337,20 @@ static void aia_set_iprio8(struct kvm_vcpu *vcpu, unsigned int irq, u8 prio)
|
|||||||
|
|
||||||
switch (bitpos / BITS_PER_LONG) {
|
switch (bitpos / BITS_PER_LONG) {
|
||||||
case 0:
|
case 0:
|
||||||
csr_write(CSR_HVIPRIO1, hviprio);
|
ncsr_write(CSR_HVIPRIO1, hviprio);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
#ifndef CONFIG_32BIT
|
#ifndef CONFIG_32BIT
|
||||||
csr_write(CSR_HVIPRIO2, hviprio);
|
ncsr_write(CSR_HVIPRIO2, hviprio);
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
csr_write(CSR_HVIPRIO1H, hviprio);
|
ncsr_write(CSR_HVIPRIO1H, hviprio);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
csr_write(CSR_HVIPRIO2, hviprio);
|
ncsr_write(CSR_HVIPRIO2, hviprio);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
csr_write(CSR_HVIPRIO2H, hviprio);
|
ncsr_write(CSR_HVIPRIO2H, hviprio);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
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;
|
return KVM_INSN_ILLEGAL_TRAP;
|
||||||
|
|
||||||
/* First try to emulate in kernel space */
|
/* 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)
|
if (isel >= ISELECT_IPRIO0 && isel <= ISELECT_IPRIO15)
|
||||||
return aia_rmw_iprio(vcpu, isel, val, new_val, wr_mask);
|
return aia_rmw_iprio(vcpu, isel, val, new_val, wr_mask);
|
||||||
else if (isel >= IMSIC_FIRST && isel <= IMSIC_LAST &&
|
else if (isel >= IMSIC_FIRST && isel <= IMSIC_LAST &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user