Skip to content

Commit 68c72a6

Browse files
committed
RISC-V: KVM: Use SBI sync SRET call when available
Implement an optimized KVM world-switch using SBI sync SRET call when SBI nested acceleration extension is available. This improves KVM world-switch when KVM RISC-V is running as a Guest under some other hypervisor. Signed-off-by: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Atish Patra <atishp@rivosinc.com> Link: https://lore.kernel.org/r/20241020194734.58686-12-apatel@ventanamicro.com Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent dab5560 commit 68c72a6

File tree

3 files changed

+79
-4
lines changed

3 files changed

+79
-4
lines changed

arch/riscv/include/asm/kvm_nacl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <asm/csr.h>
1313
#include <asm/sbi.h>
1414

15+
struct kvm_vcpu_arch;
16+
1517
DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_available);
1618
#define kvm_riscv_nacl_available() \
1719
static_branch_unlikely(&kvm_riscv_nacl_available)
@@ -43,6 +45,10 @@ void __kvm_riscv_nacl_hfence(void *shmem,
4345
unsigned long page_num,
4446
unsigned long page_count);
4547

48+
void __kvm_riscv_nacl_switch_to(struct kvm_vcpu_arch *vcpu_arch,
49+
unsigned long sbi_ext_id,
50+
unsigned long sbi_func_id);
51+
4652
int kvm_riscv_nacl_enable(void);
4753

4854
void kvm_riscv_nacl_disable(void);

arch/riscv/kvm/vcpu.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -766,19 +766,59 @@ static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *v
766766
*/
767767
static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu)
768768
{
769+
void *nsh;
769770
struct kvm_cpu_context *gcntx = &vcpu->arch.guest_context;
770771
struct kvm_cpu_context *hcntx = &vcpu->arch.host_context;
771772

772773
kvm_riscv_vcpu_swap_in_guest_state(vcpu);
773774
guest_state_enter_irqoff();
774775

775-
hcntx->hstatus = ncsr_swap(CSR_HSTATUS, gcntx->hstatus);
776+
if (kvm_riscv_nacl_sync_sret_available()) {
777+
nsh = nacl_shmem();
776778

777-
nsync_csr(-1UL);
779+
if (kvm_riscv_nacl_autoswap_csr_available()) {
780+
hcntx->hstatus =
781+
nacl_csr_read(nsh, CSR_HSTATUS);
782+
nacl_scratch_write_long(nsh,
783+
SBI_NACL_SHMEM_AUTOSWAP_OFFSET +
784+
SBI_NACL_SHMEM_AUTOSWAP_HSTATUS,
785+
gcntx->hstatus);
786+
nacl_scratch_write_long(nsh,
787+
SBI_NACL_SHMEM_AUTOSWAP_OFFSET,
788+
SBI_NACL_SHMEM_AUTOSWAP_FLAG_HSTATUS);
789+
} else if (kvm_riscv_nacl_sync_csr_available()) {
790+
hcntx->hstatus = nacl_csr_swap(nsh,
791+
CSR_HSTATUS, gcntx->hstatus);
792+
} else {
793+
hcntx->hstatus = csr_swap(CSR_HSTATUS, gcntx->hstatus);
794+
}
778795

779-
__kvm_riscv_switch_to(&vcpu->arch);
796+
nacl_scratch_write_longs(nsh,
797+
SBI_NACL_SHMEM_SRET_OFFSET +
798+
SBI_NACL_SHMEM_SRET_X(1),
799+
&gcntx->ra,
800+
SBI_NACL_SHMEM_SRET_X_LAST);
801+
802+
__kvm_riscv_nacl_switch_to(&vcpu->arch, SBI_EXT_NACL,
803+
SBI_EXT_NACL_SYNC_SRET);
804+
805+
if (kvm_riscv_nacl_autoswap_csr_available()) {
806+
nacl_scratch_write_long(nsh,
807+
SBI_NACL_SHMEM_AUTOSWAP_OFFSET,
808+
0);
809+
gcntx->hstatus = nacl_scratch_read_long(nsh,
810+
SBI_NACL_SHMEM_AUTOSWAP_OFFSET +
811+
SBI_NACL_SHMEM_AUTOSWAP_HSTATUS);
812+
} else {
813+
gcntx->hstatus = csr_swap(CSR_HSTATUS, hcntx->hstatus);
814+
}
815+
} else {
816+
hcntx->hstatus = csr_swap(CSR_HSTATUS, gcntx->hstatus);
780817

781-
gcntx->hstatus = csr_swap(CSR_HSTATUS, hcntx->hstatus);
818+
__kvm_riscv_switch_to(&vcpu->arch);
819+
820+
gcntx->hstatus = csr_swap(CSR_HSTATUS, hcntx->hstatus);
821+
}
782822

783823
vcpu->arch.last_exit_cpu = vcpu->cpu;
784824
guest_state_exit_irqoff();

arch/riscv/kvm/vcpu_switch.S

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,35 @@ SYM_FUNC_START(__kvm_riscv_switch_to)
218218
ret
219219
SYM_FUNC_END(__kvm_riscv_switch_to)
220220

221+
/*
222+
* Parameters:
223+
* A0 <= Pointer to struct kvm_vcpu_arch
224+
* A1 <= SBI extension ID
225+
* A2 <= SBI function ID
226+
*/
227+
SYM_FUNC_START(__kvm_riscv_nacl_switch_to)
228+
SAVE_HOST_GPRS
229+
230+
SAVE_HOST_AND_RESTORE_GUEST_CSRS .Lkvm_nacl_switch_return
231+
232+
/* Resume Guest using SBI nested acceleration */
233+
add a6, a2, zero
234+
add a7, a1, zero
235+
ecall
236+
237+
/* Back to Host */
238+
.align 2
239+
.Lkvm_nacl_switch_return:
240+
SAVE_GUEST_GPRS
241+
242+
SAVE_GUEST_AND_RESTORE_HOST_CSRS
243+
244+
RESTORE_HOST_GPRS
245+
246+
/* Return to C code */
247+
ret
248+
SYM_FUNC_END(__kvm_riscv_nacl_switch_to)
249+
221250
SYM_CODE_START(__kvm_riscv_unpriv_trap)
222251
/*
223252
* We assume that faulting unpriv load/store instruction is

0 commit comments

Comments
 (0)