[v2,06/29] LoongArch: KVM: Implement vcpu create and destroy interface

Message ID 20230220065735.1282809-7-zhaotianrui@loongson.cn
State New
Headers
Series Add KVM LoongArch support |

Commit Message

zhaotianrui Feb. 20, 2023, 6:57 a.m. UTC
  Implement vcpu create and destroy interface, saving some info
into vcpu arch structure such as vcpu exception entrance, vcpu
enter guest pointer, etc. Init vcpu timer and set address
translation mode when vcpu create.

Signed-off-by: Tianrui Zhao <zhaotianrui@loongson.cn>
---
 arch/loongarch/kvm/vcpu.c | 94 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 arch/loongarch/kvm/vcpu.c
  

Comments

Paolo Bonzini Feb. 20, 2023, 5:53 p.m. UTC | #1
On 2/20/23 07:57, Tianrui Zhao wrote:
> +	vcpu->arch.guest_eentry = (unsigned long)kvm_context->kvm_eentry;
> +	vcpu->arch.vcpu_run = kvm_context->kvm_enter_guest;
> +	vcpu->arch.handle_exit = _kvm_handle_exit;

Here as well, whatever is constant must not be stored in struct 
kvm_arch_vcpu.

Paolo
  
zhaotianrui Feb. 22, 2023, 1:52 a.m. UTC | #2
在 2023年02月21日 01:53, Paolo Bonzini 写道:
> On 2/20/23 07:57, Tianrui Zhao wrote:
>> +    vcpu->arch.guest_eentry = (unsigned long)kvm_context->kvm_eentry;
>> +    vcpu->arch.vcpu_run = kvm_context->kvm_enter_guest;
>> +    vcpu->arch.handle_exit = _kvm_handle_exit;
>
> Here as well, whatever is constant must not be stored in struct 
> kvm_arch_vcpu.
>
> Paolo

Thanks,  we use this in vcpu_arch because the vcpu_arch is used as 
argument in switch.S' methods, we can quickly access the guest_eentry 
and handle_exit by using the  KVM_ARCH_GEENTRY, KVM_ARCH_HANDLE_EXIT 
offsets. If we change to global variable ,  we should relocate it in 
switch.S and may lead  to lower accessing speed.
  
Paolo Bonzini Feb. 22, 2023, 12:17 p.m. UTC | #3
On 2/22/23 02:52, Tianrui Zhao wrote:
>>
>>> +    vcpu->arch.guest_eentry = (unsigned long)kvm_context->kvm_eentry;
>>> +    vcpu->arch.vcpu_run = kvm_context->kvm_enter_guest;
>>> +    vcpu->arch.handle_exit = _kvm_handle_exit;
>>
>> Here as well, whatever is constant must not be stored in struct 
>> kvm_arch_vcpu.
>>
>> Paolo
> 
> Thanks,  we use this in vcpu_arch because the vcpu_arch is used as 
> argument in switch.S' methods, we can quickly access the guest_eentry 
> and handle_exit by using the  KVM_ARCH_GEENTRY, KVM_ARCH_HANDLE_EXIT 
> offsets. If we change to global variable ,  we should relocate it in 
> switch.S and may lead  to lower accessing speed.

For guest_eentry and handle_exit this is correct so you can add a 
comment in kvm_host.h, like

	/* Pointers stored here for easy access from assembly code.  */

However, vcpu->arch.vcpu_run is not used in switch.S so there is no need 
to store it in struct kvm_arch_vcpu.  Since you're already going to move 
kvm_enter_guest out of kvm_context and into a global variable, please 
give it the right pointer-to-function type instead of using unsigned long.

Paolo
  
zhaotianrui Feb. 23, 2023, 1:23 a.m. UTC | #4
在 2023年02月22日 20:17, Paolo Bonzini 写道:
> On 2/22/23 02:52, Tianrui Zhao wrote:
>>>
>>>> +    vcpu->arch.guest_eentry = (unsigned long)kvm_context->kvm_eentry;
>>>> +    vcpu->arch.vcpu_run = kvm_context->kvm_enter_guest;
>>>> +    vcpu->arch.handle_exit = _kvm_handle_exit;
>>>
>>> Here as well, whatever is constant must not be stored in struct 
>>> kvm_arch_vcpu.
>>>
>>> Paolo
>>
>> Thanks,  we use this in vcpu_arch because the vcpu_arch is used as 
>> argument in switch.S' methods, we can quickly access the guest_eentry 
>> and handle_exit by using the  KVM_ARCH_GEENTRY, KVM_ARCH_HANDLE_EXIT 
>> offsets. If we change to global variable , we should relocate it in 
>> switch.S and may lead  to lower accessing speed.
>
> For guest_eentry and handle_exit this is correct so you can add a 
> comment in kvm_host.h, like
>
>     /* Pointers stored here for easy access from assembly code. */
>
> However, vcpu->arch.vcpu_run is not used in switch.S so there is no 
> need to store it in struct kvm_arch_vcpu.  Since you're already going 
> to move kvm_enter_guest out of kvm_context and into a global variable, 
> please give it the right pointer-to-function type instead of using 
> unsigned long.
>
> Paolo

Thanks, I will remove this vcpu_run and replace it with the new global 
variable, and fix the pointer-to-function type.

Thanks
Tianrui Zhao
  

Patch

diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
new file mode 100644
index 000000000..4d355bcff
--- /dev/null
+++ b/arch/loongarch/kvm/vcpu.c
@@ -0,0 +1,94 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/fpu.h>
+#include <asm/loongarch.h>
+#include <asm/setup.h>
+#include <asm/time.h>
+#include <asm/kvm_host.h>
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
+{
+	return 0;
+}
+
+int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
+{
+	int i;
+	unsigned long timer_hz;
+	struct loongarch_csrs *csr;
+	struct kvm_context *kvm_context = per_cpu_ptr(vcpu->kvm->arch.vmcs, 0);
+
+	for_each_possible_cpu(i)
+		vcpu->arch.vpid[i] = 0;
+
+	hrtimer_init(&vcpu->arch.swtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
+	vcpu->arch.swtimer.function = kvm_swtimer_wakeup;
+	vcpu->arch.fpu_enabled = true;
+	vcpu->kvm->arch.online_vcpus = vcpu->vcpu_id + 1;
+
+	vcpu->arch.guest_eentry = (unsigned long)kvm_context->kvm_eentry;
+	vcpu->arch.vcpu_run = kvm_context->kvm_enter_guest;
+	vcpu->arch.handle_exit = _kvm_handle_exit;
+	vcpu->arch.csr = kzalloc(sizeof(struct loongarch_csrs), GFP_KERNEL);
+	if (!vcpu->arch.csr)
+		return -ENOMEM;
+
+	/*
+	 * kvm all exceptions share one exception entry, and host <-> guest switch
+	 * also switch excfg.VS field, keep host excfg.VS info here
+	 */
+	vcpu->arch.host_ecfg = (read_csr_ecfg() & CSR_ECFG_VS);
+
+	/* Init */
+	vcpu->arch.last_sched_cpu = -1;
+	vcpu->arch.last_exec_cpu = -1;
+
+	/*
+	 * Initialize guest register state to valid architectural reset state.
+	 */
+	timer_hz = calc_const_freq();
+	kvm_init_timer(vcpu, timer_hz);
+
+	/* Set Initialize mode for GUEST */
+	csr = vcpu->arch.csr;
+	kvm_write_sw_gcsr(csr, LOONGARCH_CSR_CRMD, CSR_CRMD_DA);
+
+	/* Set cpuid */
+	kvm_write_sw_gcsr(csr, LOONGARCH_CSR_TMID, vcpu->vcpu_id);
+
+	/* start with no pending virtual guest interrupts */
+	csr->csrs[LOONGARCH_CSR_GINTC] = 0;
+
+	return 0;
+}
+
+void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	int cpu;
+	struct kvm_context *context;
+
+	hrtimer_cancel(&vcpu->arch.swtimer);
+	kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
+	kfree(vcpu->arch.csr);
+
+	/*
+	 * If the VCPU is freed and reused as another VCPU, we don't want the
+	 * matching pointer wrongly hanging around in last_vcpu.
+	 */
+	for_each_possible_cpu(cpu) {
+		context = per_cpu_ptr(vcpu->kvm->arch.vmcs, cpu);
+		if (context->last_vcpu == vcpu)
+			context->last_vcpu = NULL;
+	}
+}