LoongArch KVM changes for v6.15

1. Remove unnecessary header include path.
 2. Remove PGD saving during VM context switch.
 3. Add perf events support for guest VM.
 -----BEGIN PGP SIGNATURE-----
 
 iQJJBAABCAA0FiEEzOlt8mkP+tbeiYy5AoYrw/LiJnoFAmfZNMMWHGNoZW5odWFj
 YWlAa2VybmVsLm9yZwAKCRAChivD8uImejeED/i9AL05s7EQpGhY4Ity2teRHP2R
 OHPlLTjdjXT0XE8L3suqB2ZPTOCjN3m6ywF7AEzyWWt5NhRBLgs7a5+VgXTWKZ1P
 uzVNTfvN5KVDmN39M4IPtDrFrIYAmSZENFK8VxVehI9XSiA2/jnseur3MqrLisxX
 H1biynN7zAfV25UBpveSt/o+8X2McXBIs11f/aioGCfJFcssfLRf8IvxC8gJ5WVL
 jTpm3WtydumRUyV02eotYT1V1tUnXy5nrDMeStstN44RjBkOdzC0gia+mOPF6BfG
 YBqf+orpulSb9xMVepkI2mEdRtyf7YLK3WRU7XsE5SDZMJ4Qvf8zmRrXMrTaQNdB
 FACXWi2RpntmgeGDmgwR6sKMqOM6IS0+MbBktQW+GDtRARe12Y5CnXtLfsvpb7P1
 RKefsgplBekIgqeWmJDxftyrp0ecBWZpDSBNlyF/sM8jXINEUWnI1CFtOL5EsNTs
 wwBoRTOyNyOKLn//qFFlxxraP4r5WSge7oY2vLqeVOkFZujg8Rg5Oll7E93z0Rgx
 KrxajzuaHD0SbZHUpDaFCu2C2DPjaiOpDS8n0oB03zjVmpLb89IskrCL5i0B5X3/
 UoMs85W4b3yzOQqC3HTut/lBowpLmGswHs9ZvGeMO/v5RfXfG0opeAt1kHYNDmXx
 VKvl9suP+6HRjjXN
 =Wrgv
 -----END PGP SIGNATURE-----

Merge tag 'loongarch-kvm-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson into HEAD

LoongArch KVM changes for v6.15

1. Remove unnecessary header include path.
2. Remove PGD saving during VM context switch.
3. Add perf events support for guest VM.
This commit is contained in:
Paolo Bonzini 2025-03-19 09:03:12 -04:00
commit e335300095
7 changed files with 50 additions and 12 deletions

View File

@ -12,6 +12,7 @@
#include <linux/kvm.h>
#include <linux/kvm_types.h>
#include <linux/mutex.h>
#include <linux/perf_event.h>
#include <linux/spinlock.h>
#include <linux/threads.h>
#include <linux/types.h>
@ -176,6 +177,9 @@ struct kvm_vcpu_arch {
/* Pointers stored here for easy accessing from assembly code */
int (*handle_exit)(struct kvm_run *run, struct kvm_vcpu *vcpu);
/* GPA (=HVA) of PGD for secondary mmu */
unsigned long kvm_pgd;
/* Host registers preserved across guest mode execution */
unsigned long host_sp;
unsigned long host_tp;
@ -289,6 +293,8 @@ static inline int kvm_get_pmu_num(struct kvm_vcpu_arch *arch)
return (arch->cpucfg[6] & CPUCFG6_PMNUM) >> CPUCFG6_PMNUM_SHIFT;
}
bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu);
/* Debug: dump vcpu state */
int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu);

View File

@ -296,6 +296,7 @@ static void __used output_kvm_defines(void)
OFFSET(KVM_ARCH_HSP, kvm_vcpu_arch, host_sp);
OFFSET(KVM_ARCH_HTP, kvm_vcpu_arch, host_tp);
OFFSET(KVM_ARCH_HPGD, kvm_vcpu_arch, host_pgd);
OFFSET(KVM_ARCH_KVMPGD, kvm_vcpu_arch, kvm_pgd);
OFFSET(KVM_ARCH_HANDLE_EXIT, kvm_vcpu_arch, handle_exit);
OFFSET(KVM_ARCH_HEENTRY, kvm_vcpu_arch, host_eentry);
OFFSET(KVM_ARCH_GEENTRY, kvm_vcpu_arch, guest_eentry);

View File

@ -33,6 +33,7 @@ config KVM
select KVM_MMIO
select KVM_XFER_TO_GUEST_WORK
select SCHED_INFO
select GUEST_PERF_EVENTS if PERF_EVENTS
help
Support hosting virtualized guest machines using
hardware virtualization extensions. You will need

View File

@ -3,8 +3,6 @@
# Makefile for LoongArch KVM support
#
ccflags-y += -I $(src)
include $(srctree)/virt/kvm/Makefile.kvm
obj-$(CONFIG_KVM) += kvm.o

View File

@ -394,6 +394,7 @@ static int kvm_loongarch_env_init(void)
}
kvm_init_gcsr_flag();
kvm_register_perf_callbacks(NULL);
/* Register LoongArch IPI interrupt controller interface. */
ret = kvm_loongarch_register_ipi_device();
@ -425,6 +426,8 @@ static void kvm_loongarch_env_exit(void)
}
kfree(kvm_loongarch_ops);
}
kvm_unregister_perf_callbacks();
}
static int kvm_loongarch_init(void)

View File

@ -60,16 +60,8 @@
ld.d t0, a2, KVM_ARCH_GPC
csrwr t0, LOONGARCH_CSR_ERA
/* Save host PGDL */
csrrd t0, LOONGARCH_CSR_PGDL
st.d t0, a2, KVM_ARCH_HPGD
/* Switch to kvm */
ld.d t1, a2, KVM_VCPU_KVM - KVM_VCPU_ARCH
/* Load guest PGDL */
li.w t0, KVM_GPGD
ldx.d t0, t1, t0
/* Load PGD for KVM hypervisor */
ld.d t0, a2, KVM_ARCH_KVMPGD
csrwr t0, LOONGARCH_CSR_PGDL
/* Mix GID and RID */

View File

@ -360,6 +360,34 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
}
bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
{
unsigned long val;
preempt_disable();
val = gcsr_read(LOONGARCH_CSR_CRMD);
preempt_enable();
return (val & CSR_PRMD_PPLV) == PLV_KERN;
}
#ifdef CONFIG_GUEST_PERF_EVENTS
unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu)
{
return vcpu->arch.pc;
}
/*
* Returns true if a Performance Monitoring Interrupt (PMI), a.k.a. perf event,
* arrived in guest context. For LoongArch64, if PMU is not passthrough to VM,
* any event that arrives while a vCPU is loaded is considered to be "in guest".
*/
bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)
{
return (vcpu && !(vcpu->arch.aux_inuse & KVM_LARCH_PMU));
}
#endif
bool kvm_arch_vcpu_preempted_in_kernel(struct kvm_vcpu *vcpu)
{
return false;
}
@ -1462,6 +1490,15 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
hrtimer_init(&vcpu->arch.swtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD);
vcpu->arch.swtimer.function = kvm_swtimer_wakeup;
/* Get GPA (=HVA) of PGD for kvm hypervisor */
vcpu->arch.kvm_pgd = __pa(vcpu->kvm->arch.pgd);
/*
* Get PGD for primary mmu, virtual address is used since there is
* memory access after loading from CSR_PGD in tlb exception fast path.
*/
vcpu->arch.host_pgd = (unsigned long)vcpu->kvm->mm->pgd;
vcpu->arch.handle_exit = kvm_handle_exit;
vcpu->arch.guest_eentry = (unsigned long)kvm_loongarch_ops->exc_entry;
vcpu->arch.csr = kzalloc(sizeof(struct loongarch_csrs), GFP_KERNEL);