[PATCH v2 07/29] LoongArch: KVM: Implement vcpu run interface

From: Tianrui Zhao
Date: Mon Feb 20 2023 - 01:58:21 EST


Implement vcpu run interface, handling mmio, iocsr reading fault
and deliver interrupt, lose fpu before vcpu enter guest.

Signed-off-by: Tianrui Zhao <zhaotianrui@xxxxxxxxxxx>
---
arch/loongarch/kvm/vcpu.c | 81 +++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)

diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index 4d355bcff..571ac8b9d 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -18,6 +18,26 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
return 0;
}

+/* Returns 1 if the guest TLB may be clobbered */
+static int _kvm_check_requests(struct kvm_vcpu *vcpu, int cpu)
+{
+ int ret = 0;
+ int i;
+
+ if (!kvm_request_pending(vcpu))
+ return 0;
+
+ if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu)) {
+ /* Drop all vpids for this VCPU */
+ for_each_possible_cpu(i)
+ vcpu->arch.vpid[i] = 0;
+ /* This will clobber guest TLB contents too */
+ ret = 1;
+ }
+
+ return ret;
+}
+
int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
{
int i;
@@ -92,3 +112,64 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
context->last_vcpu = NULL;
}
}
+
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
+{
+ int r = -EINTR;
+ int cpu;
+ struct kvm_run *run = vcpu->run;
+
+ vcpu_load(vcpu);
+
+ kvm_sigset_activate(vcpu);
+
+ if (vcpu->mmio_needed) {
+ if (!vcpu->mmio_is_write)
+ _kvm_complete_mmio_read(vcpu, run);
+ vcpu->mmio_needed = 0;
+ }
+
+ if (run->exit_reason == KVM_EXIT_LOONGARCH_IOCSR) {
+ if (!run->iocsr_io.is_write)
+ _kvm_complete_iocsr_read(vcpu, run);
+ }
+
+ /* clear exit_reason */
+ run->exit_reason = KVM_EXIT_UNKNOWN;
+ if (run->immediate_exit)
+ goto out;
+
+ lose_fpu(1);
+
+ local_irq_disable();
+ guest_enter_irqoff();
+ trace_kvm_enter(vcpu);
+
+ /*
+ * Make sure the read of VCPU requests in vcpu_run() callback is not
+ * reordered ahead of the write to vcpu->mode, or we could miss a TLB
+ * flush request while the requester sees the VCPU as outside of guest
+ * mode and not needing an IPI.
+ */
+ smp_store_mb(vcpu->mode, IN_GUEST_MODE);
+
+ cpu = smp_processor_id();
+ kvm_acquire_timer(vcpu);
+ /* Check if we have any exceptions/interrupts pending */
+ _kvm_deliver_intr(vcpu);
+
+ _kvm_check_requests(vcpu, cpu);
+ _kvm_check_vmid(vcpu, cpu);
+ vcpu->arch.host_eentry = csr_read64(LOONGARCH_CSR_EENTRY);
+ r = vcpu->arch.vcpu_run(run, vcpu);
+
+ trace_kvm_out(vcpu);
+ guest_exit_irqoff();
+ local_irq_enable();
+
+out:
+ kvm_sigset_deactivate(vcpu);
+
+ vcpu_put(vcpu);
+ return r;
+}
--
2.31.1