mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Liju-clr Chen <liju-clr.chen@mediatek.com>
To: Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Jonathan Corbet <corbet@lwn.net>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Masami Hiramatsu <mhiramat@kernel.org>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
	Richard Cochran <richardcochran@gmail.com>,
	Matthias Brugger <matthias.bgg@gmail.com>,
	AngeloGioacchino Del Regno
	<angelogioacchino.delregno@collabora.com>,
	Liju-clr Chen <Liju-clr.Chen@mediatek.com>,
	Yingshiuan Pan <Yingshiuan.Pan@mediatek.com>,
	Ze-yu Wang <Ze-yu.Wang@mediatek.com>
Cc: <devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linux-doc@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-trace-kernel@vger.kernel.org>, <netdev@vger.kernel.org>,
	<linux-mediatek@lists.infradead.org>,
	Shawn Hsiao <shawn.hsiao@mediatek.com>,
	PeiLun Suei <PeiLun.Suei@mediatek.com>,
	Chi-shen Yeh <Chi-shen.Yeh@mediatek.com>,
	Kevenny Hsieh <Kevenny.Hsieh@mediatek.com>
Subject: [PATCH v13 22/25] virt: geniezone: Add support for virtual timer migration
Date: Thu, 14 Nov 2024 18:07:59 +0800	[thread overview]
Message-ID: <20241114100802.4116-23-liju-clr.chen@mediatek.com> (raw)
In-Reply-To: <20241114100802.4116-1-liju-clr.chen@mediatek.com>

From: Willix Yeh <chi-shen.yeh@mediatek.com>

Introduce a mechanism to migrate the ARM64 virtual timer from the
guest VM to the host Linux system when the execution context switches
from the guest VM to the host. Ensure that the guest VM's virtual
timer continues to operate seamlessly after the context switch, given
that ARM64 has only one virtual timer.

Translate the remaining time before the VM timer expires into the host
Linux system by setting the remaining time on an hrtimer. This allows
the guest VM to maintain its timer operations without interruption.

Enable seamless timer operation during idle states. When a VM enters
an idle state and the execution context returns to the host Linux,
ensure that the timer continues to operate seamlessly, preventing
disruption to the guest VM's timing operations.

Signed-off-by: Willix Yeh <chi-shen.yeh@mediatek.com>
Co-developed-by: Kevenny Hsieh <kevenny.hsieh@mediatek.com>
Signed-off-by: Kevenny Hsieh <kevenny.hsieh@mediatek.com>
Signed-off-by: Liju Chen <liju-clr.chen@mediatek.com>
---
 arch/arm64/geniezone/gzvm_arch_common.h | 15 +++++++++++++++
 arch/arm64/geniezone/vcpu.c             | 16 ++++++++++++++++
 arch/arm64/geniezone/vm.c               | 24 ++++++++++++++++++++++++
 drivers/virt/geniezone/gzvm_main.c      |  4 ++++
 drivers/virt/geniezone/gzvm_vcpu.c      | 24 ++++++++++++++++++++++++
 include/linux/soc/mediatek/gzvm_drv.h   |  7 +++++++
 6 files changed, 90 insertions(+)

diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h
index 8f5d8528ab96..df16e33f6b74 100644
--- a/arch/arm64/geniezone/gzvm_arch_common.h
+++ b/arch/arm64/geniezone/gzvm_arch_common.h
@@ -7,6 +7,7 @@
 #define __GZVM_ARCH_COMMON_H__
 
 #include <linux/arm-smccc.h>
+#include <linux/clocksource.h>
 
 enum {
 	GZVM_FUNC_CREATE_VM = 0,
@@ -85,6 +86,10 @@ int gzvm_hypcall_wrapper(unsigned long a0, unsigned long a1,
  * @lr: The array of LRs(list registers).
  * @vtimer_offset: The offset maintained by hypervisor that is host cycle count
  *                 when guest VM startup.
+ * @vtimer_delay: The remaining time before the next timer tick is triggered
+ *                while the VM is running.
+ * @vtimer_migrate: Indicates whether the guest virtual timer needs to be
+ *                  migrated to the host software timer.
  *
  * - Keep the same layout of hypervisor data struct.
  * - Sync list registers back for acking virtual device interrupt status.
@@ -94,8 +99,18 @@ struct gzvm_vcpu_hwstate {
 	__le32 __pad;
 	__le64 lr[GIC_V3_NR_LRS];
 	__le64 vtimer_offset;
+	__le64 vtimer_delay;
+	__le32 vtimer_migrate;
 };
 
+struct timecycle {
+	u32 mult;
+	u32 shift;
+};
+
+u32 gzvm_vtimer_get_clock_mult(void);
+u32 gzvm_vtimer_get_clock_shift(void);
+
 static inline unsigned int
 assemble_vm_vcpu_tuple(u16 vmid, u16 vcpuid)
 {
diff --git a/arch/arm64/geniezone/vcpu.c b/arch/arm64/geniezone/vcpu.c
index e12ea9cb4941..595f16904b99 100644
--- a/arch/arm64/geniezone/vcpu.c
+++ b/arch/arm64/geniezone/vcpu.c
@@ -11,6 +11,22 @@
 #include <linux/soc/mediatek/gzvm_drv.h>
 #include "gzvm_arch_common.h"
 
+u64 gzvm_vcpu_arch_get_timer_delay_ns(struct gzvm_vcpu *vcpu)
+{
+	u64 ns;
+
+	if (vcpu->hwstate->vtimer_migrate) {
+		ns = clocksource_cyc2ns(le64_to_cpu(vcpu->hwstate->vtimer_delay),
+					gzvm_vtimer_get_clock_mult(),
+					gzvm_vtimer_get_clock_shift());
+	} else {
+		ns = 0;
+	}
+
+	/* 0: no migrate, otherwise: migrate  */
+	return ns;
+}
+
 int gzvm_arch_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, __u64 reg_id,
 				  bool is_write, __u64 *data)
 {
diff --git a/arch/arm64/geniezone/vm.c b/arch/arm64/geniezone/vm.c
index 026c1980d054..fccdcd5b8c75 100644
--- a/arch/arm64/geniezone/vm.c
+++ b/arch/arm64/geniezone/vm.c
@@ -15,6 +15,18 @@
 
 #define PAR_PA47_MASK GENMASK_ULL(47, 12)
 
+static struct timecycle clock_scale_factor;
+
+u32 gzvm_vtimer_get_clock_mult(void)
+{
+	return clock_scale_factor.mult;
+}
+
+u32 gzvm_vtimer_get_clock_shift(void)
+{
+	return clock_scale_factor.shift;
+}
+
 /**
  * gzvm_hypcall_wrapper() - the wrapper for hvc calls
  * @a0: arguments passed in registers 0
@@ -90,6 +102,18 @@ int gzvm_arch_probe(struct gzvm_version drv_version,
 	return 0;
 }
 
+int gzvm_arch_drv_init(void)
+{
+	/* timecycle init mult shift */
+	clocks_calc_mult_shift(&clock_scale_factor.mult,
+			       &clock_scale_factor.shift,
+			       arch_timer_get_cntfrq(),
+			       NSEC_PER_SEC,
+			       30);
+
+	return 0;
+}
+
 int gzvm_arch_set_memregion(u16 vm_id, size_t buf_size,
 			    phys_addr_t region)
 {
diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c
index 1816eecfcefb..0ec15c33111e 100644
--- a/drivers/virt/geniezone/gzvm_main.c
+++ b/drivers/virt/geniezone/gzvm_main.c
@@ -233,6 +233,10 @@ static int gzvm_drv_probe(struct platform_device *pdev)
 		 gzvm_drv.hyp_version.major, gzvm_drv.hyp_version.minor,
 		 gzvm_drv.hyp_version.sub);
 
+	ret = gzvm_arch_drv_init();
+	if (ret)
+		return ret;
+
 	ret = misc_register(&gzvm_dev);
 	if (ret)
 		return ret;
diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c
index 3b146148abf3..ba85a6ae04a0 100644
--- a/drivers/virt/geniezone/gzvm_vcpu.c
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -16,6 +16,28 @@
 /* maximum size needed for holding an integer */
 #define ITOA_MAX_LEN 12
 
+static enum hrtimer_restart gzvm_vtimer_expire(struct hrtimer *hrt)
+{
+	return HRTIMER_NORESTART;
+}
+
+static void gzvm_vtimer_init(struct gzvm_vcpu *vcpu)
+{
+	/* gzvm_vtimer init based on hrtimer */
+	hrtimer_init(&vcpu->gzvm_vtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
+	vcpu->gzvm_vtimer.function = gzvm_vtimer_expire;
+}
+
+void gzvm_vtimer_set(struct gzvm_vcpu *vcpu, u64 ns)
+{
+	hrtimer_start(&vcpu->gzvm_vtimer, ktime_add_ns(ktime_get(), ns), HRTIMER_MODE_ABS_HARD);
+}
+
+void gzvm_vtimer_release(struct gzvm_vcpu *vcpu)
+{
+	hrtimer_cancel(&vcpu->gzvm_vtimer);
+}
+
 static long gzvm_vcpu_update_one_reg(struct gzvm_vcpu *vcpu,
 				     void __user *argp,
 				     bool is_write)
@@ -193,6 +215,7 @@ static void gzvm_destroy_vcpu(struct gzvm_vcpu *vcpu)
 	if (!vcpu)
 		return;
 
+	hrtimer_cancel(&vcpu->gzvm_vtimer);
 	gzvm_arch_destroy_vcpu(vcpu->gzvm->vm_id, vcpu->vcpuid);
 	/* clean guest's data */
 	memset(vcpu->run, 0, GZVM_VCPU_RUN_MAP_SIZE);
@@ -271,6 +294,7 @@ int gzvm_vm_ioctl_create_vcpu(struct gzvm *gzvm, u32 cpuid)
 		goto free_vcpu_run;
 	gzvm->vcpus[cpuid] = vcpu;
 
+	gzvm_vtimer_init(vcpu);
 	return ret;
 
 free_vcpu_run:
diff --git a/include/linux/soc/mediatek/gzvm_drv.h b/include/linux/soc/mediatek/gzvm_drv.h
index 62e00fb06269..901bc2fe28f1 100644
--- a/include/linux/soc/mediatek/gzvm_drv.h
+++ b/include/linux/soc/mediatek/gzvm_drv.h
@@ -129,6 +129,7 @@ struct gzvm_vcpu {
 	struct mutex lock;
 	struct gzvm_vcpu_run *run;
 	struct gzvm_vcpu_hwstate *hwstate;
+	struct hrtimer gzvm_vtimer;
 };
 
 struct gzvm_pinned_page {
@@ -242,11 +243,17 @@ int gzvm_vm_allocate_guest_page(struct gzvm *gzvm, struct gzvm_memslot *slot,
 int gzvm_vm_ioctl_create_vcpu(struct gzvm *gzvm, u32 cpuid);
 int gzvm_arch_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, __u64 reg_id,
 				  bool is_write, __u64 *data);
+int gzvm_arch_drv_init(void);
 int gzvm_arch_create_vcpu(u16 vm_id, int vcpuid, void *run);
 int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason);
 int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid);
 int gzvm_arch_inform_exit(u16 vm_id);
 
+u64 gzvm_vcpu_arch_get_timer_delay_ns(struct gzvm_vcpu *vcpu);
+
+void gzvm_vtimer_set(struct gzvm_vcpu *vcpu, u64 ns);
+void gzvm_vtimer_release(struct gzvm_vcpu *vcpu);
+
 int gzvm_find_memslot(struct gzvm *vm, u64 gpa);
 int gzvm_handle_page_fault(struct gzvm_vcpu *vcpu);
 bool gzvm_handle_guest_exception(struct gzvm_vcpu *vcpu);
-- 
2.18.0


  parent reply	other threads:[~2024-11-14 10:08 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-14 10:07 [PATCH v13 00/25] GenieZone hypervisor drivers Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 01/25] virt: geniezone: enable gzvm-ko in defconfig Liju-clr Chen
2024-12-11  8:38   ` Krzysztof Kozlowski
2024-12-13  5:57     ` Liju-clr Chen (陳麗如)
2024-11-14 10:07 ` [PATCH v13 02/25] docs: geniezone: Introduce GenieZone hypervisor Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 03/25] dt-bindings: hypervisor: Add MediaTek " Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 04/25] virt: geniezone: Add GenieZone hypervisor driver Liju-clr Chen
2024-12-11  8:44   ` Krzysztof Kozlowski
2025-08-12  7:04     ` Liju-clr Chen (陳麗如)
2025-08-12  7:23       ` Krzysztof Kozlowski
2025-08-12  8:39         ` Liju-clr Chen (陳麗如)
2025-08-12  7:32       ` Krzysztof Kozlowski
2025-08-14  3:27         ` Liju-clr Chen (陳麗如)
2024-11-14 10:07 ` [PATCH v13 05/25] virt: geniezone: Add vm support Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 06/25] virt: geniezone: Add set_user_memory_region for vm Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 07/25] virt: geniezone: Add vm capability check Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 08/25] virt: geniezone: Add vcpu support Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 09/25] virt: geniezone: Add irqchip support for virtual interrupt injection Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 10/25] virt: geniezone: Add irqfd support Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 11/25] virt: geniezone: Add ioeventfd support Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 12/25] virt: geniezone: Add memory region purpose for hypervisor Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 13/25] virt: geniezone: Add dtb config support Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 14/25] virt: geniezone: Optimize performance of protected VM memory Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 15/25] virt: geniezone: Add memory pin/unpin support Liju-clr Chen
2024-12-17 10:58   ` Hillf Danton
2024-11-14 10:07 ` [PATCH v13 16/25] virt: geniezone: Add demand paging support Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 17/25] virt: geniezone: Add block-based " Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 18/25] virt: geniezone: Add memory relinquish support Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 19/25] virt: geniezone: Provide individual VM memory statistics within debugfs Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 20/25] virt: geniezone: Add tracing support for hyp call and vcpu exit_reason Liju-clr Chen
2024-11-14 10:07 ` [PATCH v13 21/25] virt: geniezone: Enable PTP for synchronizing time between host and guest VMs Liju-clr Chen
2024-11-14 10:07 ` Liju-clr Chen [this message]
2024-11-14 10:08 ` [PATCH v13 23/25] virt: geniezone: Add support for guest VM CPU idle Liju-clr Chen
2024-12-17 10:45   ` Hillf Danton
2024-11-14 10:08 ` [PATCH v13 24/25] virt: geniezone: Emulate IPI for guest VM Liju-clr Chen
2024-11-14 10:08 ` [PATCH v13 25/25] virt: geniezone: Reduce blocked duration in hypervisor when destroying a VM Liju-clr Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241114100802.4116-23-liju-clr.chen@mediatek.com \
    --to=liju-clr.chen@mediatek.com \
    --cc=Chi-shen.Yeh@mediatek.com \
    --cc=Kevenny.Hsieh@mediatek.com \
    --cc=PeiLun.Suei@mediatek.com \
    --cc=Yingshiuan.Pan@mediatek.com \
    --cc=Ze-yu.Wang@mediatek.com \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=catalin.marinas@arm.com \
    --cc=conor+dt@kernel.org \
    --cc=corbet@lwn.net \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=matthias.bgg@gmail.com \
    --cc=mhiramat@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=richardcochran@gmail.com \
    --cc=robh@kernel.org \
    --cc=rostedt@goodmis.org \
    --cc=shawn.hsiao@mediatek.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®