Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6764553
riscv: kvm: Use SYM_*() assembly macros instead of deprecated ones
clementleger Oct 24, 2023
d872160
riscv: kvm: use ".L" local labels in assembly when applicable
clementleger Oct 24, 2023
977a943
riscv: stacktrace: Add USER_STACKTRACE support
ruanjinjie-eng Jul 8, 2024
9e88bc6
riscv: perf: add guest vs host distinction
zcxGGmu Oct 15, 2024
a6c8a2d
riscv: KVM: add basic support for host vs guest profiling
zcxGGmu Oct 15, 2024
185f6f9
RISC-V: KVM: Order the object files alphabetically
avpatel Oct 20, 2024
e473574
RISC-V: KVM: Save/restore HSTATUS in C source
avpatel Oct 20, 2024
cfa9263
RISC-V: KVM: Save/restore SCOUNTEREN in C source
avpatel Oct 20, 2024
bd33756
RISC-V: KVM: Break down the __kvm_riscv_switch_to() into macros
avpatel Oct 20, 2024
ea117aa
RISC-V: KVM: Replace aia_set_hvictl() with aia_hvictl_value()
avpatel Oct 20, 2024
28eff53
RISC-V: KVM: Don't setup SGEI for zero guest external interrupts
avpatel Oct 20, 2024
cc0e01b
RISC-V: Add defines for the SBI nested acceleration extension
avpatel Oct 20, 2024
b35f382
RISC-V: KVM: Add common nested acceleration support
avpatel Oct 20, 2024
ea2d7d4
RISC-V: KVM: Use nacl_csr_xyz() for accessing H-extension CSRs
avpatel Oct 20, 2024
ea732f1
RISC-V: KVM: Use nacl_csr_xyz() for accessing AIA CSRs
avpatel Oct 20, 2024
0686565
RISC-V: KVM: Use SBI sync SRET call when available
avpatel Oct 20, 2024
328a6b5
RISC-V: KVM: Save trap CSRs in kvm_riscv_vcpu_enter_exit()
avpatel Oct 20, 2024
c7ea89b
RISC-V: KVM: Use NACL HFENCEs for KVM request based HFENCEs
avpatel Oct 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ config RISCV
select THREAD_INFO_IN_TASK
select TRACE_IRQFLAGS_SUPPORT
select UACCESS_MEMCPY if !MMU
select USER_STACKTRACE_SUPPORT
select ZONE_DMA32 if 64BIT
select HAVE_LIVEPATCH_WO_FTRACE
select ARCH_SUPPORTS_MEMORY_FAILURE
Expand Down
10 changes: 10 additions & 0 deletions arch/riscv/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,16 @@ struct kvm_vcpu_arch {
} sta;
};

/*
* Returns true if a Performance Monitoring Interrupt (PMI), a.k.a. perf event,
* arrived in guest context. For riscv, any event that arrives while a vCPU is
* loaded is considered to be "in guest".
*/
static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)
{
return IS_ENABLED(CONFIG_GUEST_PERF_EVENTS) && !!vcpu;
}

static inline void kvm_arch_sync_events(struct kvm *kvm) {}
static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}

Expand Down
245 changes: 245 additions & 0 deletions arch/riscv/include/asm/kvm_nacl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*/

#ifndef __KVM_NACL_H
#define __KVM_NACL_H

#include <linux/jump_label.h>
#include <linux/percpu.h>
#include <asm/byteorder.h>
#include <asm/csr.h>
#include <asm/sbi.h>

struct kvm_vcpu_arch;

DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_available);
#define kvm_riscv_nacl_available() \
static_branch_unlikely(&kvm_riscv_nacl_available)

DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_csr_available);
#define kvm_riscv_nacl_sync_csr_available() \
static_branch_unlikely(&kvm_riscv_nacl_sync_csr_available)

DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_hfence_available);
#define kvm_riscv_nacl_sync_hfence_available() \
static_branch_unlikely(&kvm_riscv_nacl_sync_hfence_available)

DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_sync_sret_available);
#define kvm_riscv_nacl_sync_sret_available() \
static_branch_unlikely(&kvm_riscv_nacl_sync_sret_available)

DECLARE_STATIC_KEY_FALSE(kvm_riscv_nacl_autoswap_csr_available);
#define kvm_riscv_nacl_autoswap_csr_available() \
static_branch_unlikely(&kvm_riscv_nacl_autoswap_csr_available)

struct kvm_riscv_nacl {
void *shmem;
phys_addr_t shmem_phys;
};
DECLARE_PER_CPU(struct kvm_riscv_nacl, kvm_riscv_nacl);

void __kvm_riscv_nacl_hfence(void *shmem,
unsigned long control,
unsigned long page_num,
unsigned long page_count);

void __kvm_riscv_nacl_switch_to(struct kvm_vcpu_arch *vcpu_arch,
unsigned long sbi_ext_id,
unsigned long sbi_func_id);

int kvm_riscv_nacl_enable(void);

void kvm_riscv_nacl_disable(void);

void kvm_riscv_nacl_exit(void);

int kvm_riscv_nacl_init(void);

#ifdef CONFIG_32BIT
#define lelong_to_cpu(__x) le32_to_cpu(__x)
#define cpu_to_lelong(__x) cpu_to_le32(__x)
#else
#define lelong_to_cpu(__x) le64_to_cpu(__x)
#define cpu_to_lelong(__x) cpu_to_le64(__x)
#endif

#define nacl_shmem() \
this_cpu_ptr(&kvm_riscv_nacl)->shmem

#define nacl_scratch_read_long(__shmem, __offset) \
({ \
unsigned long *__p = (__shmem) + \
SBI_NACL_SHMEM_SCRATCH_OFFSET + \
(__offset); \
lelong_to_cpu(*__p); \
})

#define nacl_scratch_write_long(__shmem, __offset, __val) \
do { \
unsigned long *__p = (__shmem) + \
SBI_NACL_SHMEM_SCRATCH_OFFSET + \
(__offset); \
*__p = cpu_to_lelong(__val); \
} while (0)

#define nacl_scratch_write_longs(__shmem, __offset, __array, __count) \
do { \
unsigned int __i; \
unsigned long *__p = (__shmem) + \
SBI_NACL_SHMEM_SCRATCH_OFFSET + \
(__offset); \
for (__i = 0; __i < (__count); __i++) \
__p[__i] = cpu_to_lelong((__array)[__i]); \
} while (0)

#define nacl_sync_hfence(__e) \
sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SYNC_HFENCE, \
(__e), 0, 0, 0, 0, 0)

#define nacl_hfence_mkconfig(__type, __order, __vmid, __asid) \
({ \
unsigned long __c = SBI_NACL_SHMEM_HFENCE_CONFIG_PEND; \
__c |= ((__type) & SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_MASK) \
<< SBI_NACL_SHMEM_HFENCE_CONFIG_TYPE_SHIFT; \
__c |= (((__order) - SBI_NACL_SHMEM_HFENCE_ORDER_BASE) & \
SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_MASK) \
<< SBI_NACL_SHMEM_HFENCE_CONFIG_ORDER_SHIFT; \
__c |= ((__vmid) & SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_MASK) \
<< SBI_NACL_SHMEM_HFENCE_CONFIG_VMID_SHIFT; \
__c |= ((__asid) & SBI_NACL_SHMEM_HFENCE_CONFIG_ASID_MASK); \
__c; \
})

#define nacl_hfence_mkpnum(__order, __addr) \
((__addr) >> (__order))

#define nacl_hfence_mkpcount(__order, __size) \
((__size) >> (__order))

#define nacl_hfence_gvma(__shmem, __gpa, __gpsz, __order) \
__kvm_riscv_nacl_hfence(__shmem, \
nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_GVMA, \
__order, 0, 0), \
nacl_hfence_mkpnum(__order, __gpa), \
nacl_hfence_mkpcount(__order, __gpsz))

#define nacl_hfence_gvma_all(__shmem) \
__kvm_riscv_nacl_hfence(__shmem, \
nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_ALL, \
0, 0, 0), 0, 0)

#define nacl_hfence_gvma_vmid(__shmem, __vmid, __gpa, __gpsz, __order) \
__kvm_riscv_nacl_hfence(__shmem, \
nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_VMID, \
__order, __vmid, 0), \
nacl_hfence_mkpnum(__order, __gpa), \
nacl_hfence_mkpcount(__order, __gpsz))

#define nacl_hfence_gvma_vmid_all(__shmem, __vmid) \
__kvm_riscv_nacl_hfence(__shmem, \
nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_GVMA_VMID_ALL, \
0, __vmid, 0), 0, 0)

#define nacl_hfence_vvma(__shmem, __vmid, __gva, __gvsz, __order) \
__kvm_riscv_nacl_hfence(__shmem, \
nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_VVMA, \
__order, __vmid, 0), \
nacl_hfence_mkpnum(__order, __gva), \
nacl_hfence_mkpcount(__order, __gvsz))

#define nacl_hfence_vvma_all(__shmem, __vmid) \
__kvm_riscv_nacl_hfence(__shmem, \
nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ALL, \
0, __vmid, 0), 0, 0)

#define nacl_hfence_vvma_asid(__shmem, __vmid, __asid, __gva, __gvsz, __order)\
__kvm_riscv_nacl_hfence(__shmem, \
nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ASID, \
__order, __vmid, __asid), \
nacl_hfence_mkpnum(__order, __gva), \
nacl_hfence_mkpcount(__order, __gvsz))

#define nacl_hfence_vvma_asid_all(__shmem, __vmid, __asid) \
__kvm_riscv_nacl_hfence(__shmem, \
nacl_hfence_mkconfig(SBI_NACL_SHMEM_HFENCE_TYPE_VVMA_ASID_ALL, \
0, __vmid, __asid), 0, 0)

#define nacl_csr_read(__shmem, __csr) \
({ \
unsigned long *__a = (__shmem) + SBI_NACL_SHMEM_CSR_OFFSET; \
lelong_to_cpu(__a[SBI_NACL_SHMEM_CSR_INDEX(__csr)]); \
})

#define nacl_csr_write(__shmem, __csr, __val) \
do { \
void *__s = (__shmem); \
unsigned int __i = SBI_NACL_SHMEM_CSR_INDEX(__csr); \
unsigned long *__a = (__s) + SBI_NACL_SHMEM_CSR_OFFSET; \
u8 *__b = (__s) + SBI_NACL_SHMEM_DBITMAP_OFFSET; \
__a[__i] = cpu_to_lelong(__val); \
__b[__i >> 3] |= 1U << (__i & 0x7); \
} while (0)

#define nacl_csr_swap(__shmem, __csr, __val) \
({ \
void *__s = (__shmem); \
unsigned int __i = SBI_NACL_SHMEM_CSR_INDEX(__csr); \
unsigned long *__a = (__s) + SBI_NACL_SHMEM_CSR_OFFSET; \
u8 *__b = (__s) + SBI_NACL_SHMEM_DBITMAP_OFFSET; \
unsigned long __r = lelong_to_cpu(__a[__i]); \
__a[__i] = cpu_to_lelong(__val); \
__b[__i >> 3] |= 1U << (__i & 0x7); \
__r; \
})

#define nacl_sync_csr(__csr) \
sbi_ecall(SBI_EXT_NACL, SBI_EXT_NACL_SYNC_CSR, \
(__csr), 0, 0, 0, 0, 0)

/*
* Each ncsr_xyz() macro defined below has it's own static-branch so every
* use of ncsr_xyz() macro emits a patchable direct jump. This means multiple
* back-to-back ncsr_xyz() macro usage will emit multiple patchable direct
* jumps which is sub-optimal.
*
* Based on the above, it is recommended to avoid multiple back-to-back
* ncsr_xyz() macro usage.
*/

#define ncsr_read(__csr) \
({ \
unsigned long __r; \
if (kvm_riscv_nacl_available()) \
__r = nacl_csr_read(nacl_shmem(), __csr); \
else \
__r = csr_read(__csr); \
__r; \
})

#define ncsr_write(__csr, __val) \
do { \
if (kvm_riscv_nacl_sync_csr_available()) \
nacl_csr_write(nacl_shmem(), __csr, __val); \
else \
csr_write(__csr, __val); \
} while (0)

#define ncsr_swap(__csr, __val) \
({ \
unsigned long __r; \
if (kvm_riscv_nacl_sync_csr_available()) \
__r = nacl_csr_swap(nacl_shmem(), __csr, __val); \
else \
__r = csr_swap(__csr, __val); \
__r; \
})

#define nsync_csr(__csr) \
do { \
if (kvm_riscv_nacl_sync_csr_available()) \
nacl_sync_csr(__csr); \
} while (0)

#endif
6 changes: 6 additions & 0 deletions arch/riscv/include/asm/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
#ifndef _ASM_RISCV_PERF_EVENT_H
#define _ASM_RISCV_PERF_EVENT_H

#ifdef CONFIG_PERF_EVENTS
#include <linux/perf_event.h>
extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
extern unsigned long perf_misc_flags(struct pt_regs *regs);
#define perf_misc_flags(regs) perf_misc_flags(regs)
#define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs

#define perf_arch_fetch_caller_regs(regs, __ip) { \
Expand All @@ -17,4 +21,6 @@
(regs)->sp = current_stack_pointer; \
(regs)->status = SR_PP; \
}
#endif

#endif /* _ASM_RISCV_PERF_EVENT_H */
Loading
Loading