From: Yi-De Wu <yi-de.wu@mediatek.com>
To: Yingshiuan Pan <yingshiuan.pan@mediatek.com>,
Ze-Yu Wang <ze-yu.wang@mediatek.com>,
Yi-De Wu <yi-de.wu@mediatek.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>, Arnd Bergmann <arnd@arndb.de>,
Matthias Brugger <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com>
Cc: <devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<linux-doc@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-arch@vger.kernel.org>,
<linux-mediatek@lists.infradead.org>,
David Bradil <dbrazdil@google.com>,
Trilok Soni <quic_tsoni@quicinc.com>,
Ivan Tseng <ivan.tseng@mediatek.com>,
Jade Shih <jades.shih@mediatek.com>,
My Chuang <my.chuang@mediatek.com>,
Shawn Hsiao <shawn.hsiao@mediatek.com>,
PeiLun Suei <peilun.suei@mediatek.com>,
Liju Chen <liju-clr.chen@mediatek.com>,
Willix Yeh <chi-shen.yeh@mediatek.com>
Subject: [PATCH v5 10/12] virt: geniezone: Add virtual timer support
Date: Thu, 27 Jul 2023 16:00:03 +0800 [thread overview]
Message-ID: <20230727080005.14474-11-yi-de.wu@mediatek.com> (raw)
In-Reply-To: <20230727080005.14474-1-yi-de.wu@mediatek.com>
From: "Willix Yeh" <chi-shen.yeh@mediatek.com>
Implement vtimer migration handler.
- Using hrtimer for guest vtimer migration
- Identify migrate flag to do register hrtimer
Signed-off-by: Willix Yeh <chi-shen.yeh@mediatek.com>
Signed-off-by: Liju Chen <liju-clr.chen@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
arch/arm64/geniezone/Makefile | 2 +-
arch/arm64/geniezone/driver.c | 26 ++++++++
arch/arm64/geniezone/gzvm_arch_common.h | 18 ++++++
arch/arm64/geniezone/vcpu.c | 83 ++++++++++++++++++++++---
arch/arm64/geniezone/vgic.c | 16 +++++
drivers/virt/geniezone/gzvm_main.c | 5 ++
drivers/virt/geniezone/gzvm_vcpu.c | 4 +-
include/linux/gzvm_drv.h | 8 ++-
8 files changed, 149 insertions(+), 13 deletions(-)
create mode 100644 arch/arm64/geniezone/driver.c
diff --git a/arch/arm64/geniezone/Makefile b/arch/arm64/geniezone/Makefile
index 0e4f1087f9de..59e04cc0a000 100644
--- a/arch/arm64/geniezone/Makefile
+++ b/arch/arm64/geniezone/Makefile
@@ -4,6 +4,6 @@
#
include $(srctree)/drivers/virt/geniezone/Makefile
-gzvm-y += vm.o vcpu.o vgic.o
+gzvm-y += vm.o vcpu.o vgic.o driver.o
obj-$(CONFIG_MTK_GZVM) += gzvm.o
diff --git a/arch/arm64/geniezone/driver.c b/arch/arm64/geniezone/driver.c
new file mode 100644
index 000000000000..fb6ec0fed4d8
--- /dev/null
+++ b/arch/arm64/geniezone/driver.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/gzvm_drv.h>
+#include "gzvm_arch_common.h"
+
+struct timecycle clock_scale_factor;
+
+int gzvm_arch_drv_init(void)
+{
+ /* clock_scale_factor init mult shift */
+ clocks_calc_mult_shift(&clock_scale_factor.mult,
+ &clock_scale_factor.shift,
+ arch_timer_get_cntfrq(),
+ NSEC_PER_SEC,
+ 10);
+
+ return 0;
+}
+
+void gzvm_arch_drv_exit(void)
+{
+}
diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h
index 82d2c44e819b..e51310be2376 100644
--- a/arch/arm64/geniezone/gzvm_arch_common.h
+++ b/arch/arm64/geniezone/gzvm_arch_common.h
@@ -51,6 +51,13 @@ enum {
#define GIC_V3_NR_LRS 16
+struct timecycle {
+ u32 mult;
+ u32 shift;
+};
+
+extern struct timecycle clock_scale_factor;
+
/**
* gzvm_hypcall_wrapper() - the wrapper for hvc calls
* @a0-a7: arguments passed in registers 0 to 7
@@ -84,14 +91,22 @@ static inline u16 get_vcpuid_from_tuple(unsigned int tuple)
* @__pad: add an explicit '__u32 __pad;' in the middle to make it clear
* what the actual layout is.
* @lr: The array of LRs(list registers).
+ * @vtimer_delay: The remaining time until the next tick of guest VM.
+ * @vtimer_migrate: The switch flag used for guest VM to do vtimer migration or not.
+ * @vtimer_irq_num: vtimer irq number.
*
* - Keep the same layout of hypervisor data struct.
* - Sync list registers back for acking virtual device interrupt status.
+ * - Sync timer registers back for migrating timer to host's hwtimer to keep
+ * timer working in background.
*/
struct gzvm_vcpu_hwstate {
__le32 nr_lrs;
__le32 __pad;
__le64 lr[GIC_V3_NR_LRS];
+ __le64 vtimer_delay;
+ __le32 vtimer_migrate;
+ __le32 vtimer_irq_num;
};
static inline unsigned int
@@ -107,4 +122,7 @@ disassemble_vm_vcpu_tuple(unsigned int tuple, u16 *vmid, u16 *vcpuid)
*vcpuid = get_vcpuid_from_tuple(tuple);
}
+int gzvm_vgic_inject_ppi(struct gzvm *gzvm, unsigned int vcpu_idx,
+ u32 irq, bool level);
+
#endif /* __GZVM_ARCH_COMMON_H__ */
diff --git a/arch/arm64/geniezone/vcpu.c b/arch/arm64/geniezone/vcpu.c
index 95681fd66656..b26bbadf10a0 100644
--- a/arch/arm64/geniezone/vcpu.c
+++ b/arch/arm64/geniezone/vcpu.c
@@ -4,6 +4,7 @@
*/
#include <linux/arm-smccc.h>
+#include <linux/clocksource.h>
#include <linux/err.h>
#include <linux/uaccess.h>
@@ -40,25 +41,91 @@ int gzvm_arch_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, __u64 reg_id,
return ret;
}
+static void clear_migrate_state(struct gzvm_vcpu *vcpu)
+{
+ vcpu->hwstate->vtimer_migrate = 0;
+ vcpu->hwstate->vtimer_delay = 0;
+}
+
+static u64 gzvm_mtimer_delay_time(u64 delay)
+{
+ u64 ns;
+
+ ns = clocksource_cyc2ns(delay, clock_scale_factor.mult,
+ clock_scale_factor.shift);
+
+ return ns;
+}
+
+static void gzvm_mtimer_release(struct gzvm_vcpu *vcpu)
+{
+ hrtimer_cancel(&vcpu->gzvm_mtimer);
+
+ clear_migrate_state(vcpu);
+}
+
+static void gzvm_mtimer_catch(struct hrtimer *hrt, u64 delay)
+{
+ u64 ns;
+
+ ns = gzvm_mtimer_delay_time(delay);
+ hrtimer_start(hrt, ktime_add_ns(ktime_get(), ns), HRTIMER_MODE_ABS_HARD);
+}
+
+static void mtimer_irq_forward(struct gzvm_vcpu *vcpu)
+{
+ gzvm_vgic_inject_ppi(vcpu->gzvm, vcpu->vcpuid,
+ vcpu->hwstate->vtimer_irq_num, 1);
+}
+
+static enum hrtimer_restart gzvm_mtimer_expire(struct hrtimer *hrt)
+{
+ struct gzvm_vcpu *vcpu;
+
+ vcpu = container_of(hrt, struct gzvm_vcpu, gzvm_mtimer);
+
+ mtimer_irq_forward(vcpu);
+
+ return HRTIMER_NORESTART;
+}
+
+static void vtimer_init(struct gzvm_vcpu *vcpu)
+{
+ /* gzvm_mtimer init based on hrtimer */
+ hrtimer_init(&vcpu->gzvm_mtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
+ vcpu->gzvm_mtimer.function = gzvm_mtimer_expire;
+}
+
int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason)
{
struct arm_smccc_res res;
unsigned long a1;
int ret;
+ /* hrtimer cancel and clear migrate state */
+ if (vcpu->hwstate->vtimer_migrate)
+ gzvm_mtimer_release(vcpu);
+
a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid);
ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_RUN, a1, 0, 0, 0, 0, 0,
0, &res);
+
+ /* hrtimer register if migration needed */
+ if (vcpu->hwstate->vtimer_migrate)
+ gzvm_mtimer_catch(&vcpu->gzvm_mtimer, vcpu->hwstate->vtimer_delay);
+
*exit_reason = res.a1;
return ret;
}
-int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid)
+int gzvm_arch_destroy_vcpu(struct gzvm_vcpu *vcpu)
{
struct arm_smccc_res res;
unsigned long a1;
- a1 = assemble_vm_vcpu_tuple(vm_id, vcpuid);
+ hrtimer_cancel(&vcpu->gzvm_mtimer);
+
+ a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid);
gzvm_hypcall_wrapper(MT_HVC_GZVM_DESTROY_VCPU, a1, 0, 0, 0, 0, 0, 0,
&res);
@@ -67,20 +134,20 @@ int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid)
/**
* gzvm_arch_create_vcpu() - Call smc to gz hypervisor to create vcpu
- * @vm_id: vm id
- * @vcpuid: vcpu id
- * @run: Virtual address of vcpu->run
+ * @vcpu: Pointer to struct gzvm_vcpu
*
* Return: The wrapper helps caller to convert geniezone errno to Linux errno.
*/
-int gzvm_arch_create_vcpu(u16 vm_id, int vcpuid, void *run)
+int gzvm_arch_create_vcpu(struct gzvm_vcpu *vcpu)
{
struct arm_smccc_res res;
unsigned long a1, a2;
int ret;
- a1 = assemble_vm_vcpu_tuple(vm_id, vcpuid);
- a2 = (__u64)virt_to_phys(run);
+ vtimer_init(vcpu);
+
+ a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid);
+ a2 = (__u64)virt_to_phys(vcpu->run);
ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VCPU, a1, a2, 0, 0, 0, 0,
0, &res);
diff --git a/arch/arm64/geniezone/vgic.c b/arch/arm64/geniezone/vgic.c
index 3746e0c9e247..e24728997b57 100644
--- a/arch/arm64/geniezone/vgic.c
+++ b/arch/arm64/geniezone/vgic.c
@@ -91,6 +91,22 @@ static int gzvm_vgic_inject_spi(struct gzvm *gzvm, unsigned int vcpu_idx,
level);
}
+/**
+ * gzvm_vgic_inject_ppi() - Inject virtual ppi interrupt
+ * @gzvm: Pointer to struct gzvm
+ * @vcpu_idx: vcpu index
+ * @irq: This is spi interrupt number (starts from 0 instead of 32)
+ * @level: 1 if true else 0
+ *
+ * Return:
+ * * 0 if succeed else other negative values indicating each errors
+ */
+int gzvm_vgic_inject_ppi(struct gzvm *gzvm, unsigned int vcpu_idx,
+ u32 irq, bool level)
+{
+ return gzvm_vgic_inject_irq(gzvm, 0, GZVM_IRQ_TYPE_PPI, irq, level);
+}
+
int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev)
{
struct arm_smccc_res res;
diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c
index d4d5d75d3660..a4c235f3ff01 100644
--- a/drivers/virt/geniezone/gzvm_main.c
+++ b/drivers/virt/geniezone/gzvm_main.c
@@ -106,6 +106,10 @@ static int gzvm_drv_probe(struct platform_device *pdev)
return -ENODEV;
}
+ ret = gzvm_arch_drv_init();
+ if (ret)
+ return ret;
+
ret = misc_register(&gzvm_dev);
if (ret)
return ret;
@@ -121,6 +125,7 @@ static int gzvm_drv_remove(struct platform_device *pdev)
gzvm_drv_irqfd_exit();
gzvm_destroy_all_vms();
misc_deregister(&gzvm_dev);
+ gzvm_arch_drv_exit();
return 0;
}
diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c
index 72bd122a8be7..8dac8ba4c0cf 100644
--- a/drivers/virt/geniezone/gzvm_vcpu.c
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -188,7 +188,7 @@ static void gzvm_destroy_vcpu(struct gzvm_vcpu *vcpu)
if (!vcpu)
return;
- gzvm_arch_destroy_vcpu(vcpu->gzvm->vm_id, vcpu->vcpuid);
+ gzvm_arch_destroy_vcpu(vcpu);
/* clean guest's data */
memset(vcpu->run, 0, GZVM_VCPU_RUN_MAP_SIZE);
free_pages_exact(vcpu->run, GZVM_VCPU_RUN_MAP_SIZE);
@@ -257,7 +257,7 @@ int gzvm_vm_ioctl_create_vcpu(struct gzvm *gzvm, u32 cpuid)
vcpu->gzvm = gzvm;
mutex_init(&vcpu->lock);
- ret = gzvm_arch_create_vcpu(gzvm->vm_id, vcpu->vcpuid, vcpu->run);
+ ret = gzvm_arch_create_vcpu(vcpu);
if (ret < 0)
goto free_vcpu_run;
diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h
index 7bc00218dce6..e5b21ac9215b 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -6,6 +6,7 @@
#ifndef __GZVM_DRV_H__
#define __GZVM_DRV_H__
+#include <asm/arch_timer.h>
#include <linux/eventfd.h>
#include <linux/list.h>
#include <linux/mutex.h>
@@ -71,6 +72,7 @@ struct gzvm_vcpu {
struct mutex lock;
struct gzvm_vcpu_run *run;
struct gzvm_vcpu_hwstate *hwstate;
+ struct hrtimer gzvm_mtimer;
};
struct gzvm {
@@ -125,10 +127,12 @@ u64 gzvm_hva_to_pa_arch(u64 hva);
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_create_vcpu(u16 vm_id, int vcpuid, void *run);
+int gzvm_arch_create_vcpu(struct gzvm_vcpu *vcpu);
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_destroy_vcpu(struct gzvm_vcpu *vcpu);
int gzvm_arch_inform_exit(u16 vm_id);
+int gzvm_arch_drv_init(void);
+void gzvm_arch_drv_exit(void);
int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev);
int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
--
2.18.0
WARNING: multiple messages have this Message-ID (diff)
From: Yi-De Wu <yi-de.wu@mediatek.com>
To: Yingshiuan Pan <yingshiuan.pan@mediatek.com>,
Ze-Yu Wang <ze-yu.wang@mediatek.com>,
Yi-De Wu <yi-de.wu@mediatek.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>, Arnd Bergmann <arnd@arndb.de>,
Matthias Brugger <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com>
Cc: <devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<linux-doc@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-arch@vger.kernel.org>,
<linux-mediatek@lists.infradead.org>,
David Bradil <dbrazdil@google.com>,
Trilok Soni <quic_tsoni@quicinc.com>,
Ivan Tseng <ivan.tseng@mediatek.com>,
Jade Shih <jades.shih@mediatek.com>,
My Chuang <my.chuang@mediatek.com>,
Shawn Hsiao <shawn.hsiao@mediatek.com>,
PeiLun Suei <peilun.suei@mediatek.com>,
Liju Chen <liju-clr.chen@mediatek.com>,
Willix Yeh <chi-shen.yeh@mediatek.com>
Subject: [PATCH v5 10/12] virt: geniezone: Add virtual timer support
Date: Thu, 27 Jul 2023 16:00:03 +0800 [thread overview]
Message-ID: <20230727080005.14474-11-yi-de.wu@mediatek.com> (raw)
In-Reply-To: <20230727080005.14474-1-yi-de.wu@mediatek.com>
From: "Willix Yeh" <chi-shen.yeh@mediatek.com>
Implement vtimer migration handler.
- Using hrtimer for guest vtimer migration
- Identify migrate flag to do register hrtimer
Signed-off-by: Willix Yeh <chi-shen.yeh@mediatek.com>
Signed-off-by: Liju Chen <liju-clr.chen@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
---
arch/arm64/geniezone/Makefile | 2 +-
arch/arm64/geniezone/driver.c | 26 ++++++++
arch/arm64/geniezone/gzvm_arch_common.h | 18 ++++++
arch/arm64/geniezone/vcpu.c | 83 ++++++++++++++++++++++---
arch/arm64/geniezone/vgic.c | 16 +++++
drivers/virt/geniezone/gzvm_main.c | 5 ++
drivers/virt/geniezone/gzvm_vcpu.c | 4 +-
include/linux/gzvm_drv.h | 8 ++-
8 files changed, 149 insertions(+), 13 deletions(-)
create mode 100644 arch/arm64/geniezone/driver.c
diff --git a/arch/arm64/geniezone/Makefile b/arch/arm64/geniezone/Makefile
index 0e4f1087f9de..59e04cc0a000 100644
--- a/arch/arm64/geniezone/Makefile
+++ b/arch/arm64/geniezone/Makefile
@@ -4,6 +4,6 @@
#
include $(srctree)/drivers/virt/geniezone/Makefile
-gzvm-y += vm.o vcpu.o vgic.o
+gzvm-y += vm.o vcpu.o vgic.o driver.o
obj-$(CONFIG_MTK_GZVM) += gzvm.o
diff --git a/arch/arm64/geniezone/driver.c b/arch/arm64/geniezone/driver.c
new file mode 100644
index 000000000000..fb6ec0fed4d8
--- /dev/null
+++ b/arch/arm64/geniezone/driver.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 MediaTek Inc.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/gzvm_drv.h>
+#include "gzvm_arch_common.h"
+
+struct timecycle clock_scale_factor;
+
+int gzvm_arch_drv_init(void)
+{
+ /* clock_scale_factor init mult shift */
+ clocks_calc_mult_shift(&clock_scale_factor.mult,
+ &clock_scale_factor.shift,
+ arch_timer_get_cntfrq(),
+ NSEC_PER_SEC,
+ 10);
+
+ return 0;
+}
+
+void gzvm_arch_drv_exit(void)
+{
+}
diff --git a/arch/arm64/geniezone/gzvm_arch_common.h b/arch/arm64/geniezone/gzvm_arch_common.h
index 82d2c44e819b..e51310be2376 100644
--- a/arch/arm64/geniezone/gzvm_arch_common.h
+++ b/arch/arm64/geniezone/gzvm_arch_common.h
@@ -51,6 +51,13 @@ enum {
#define GIC_V3_NR_LRS 16
+struct timecycle {
+ u32 mult;
+ u32 shift;
+};
+
+extern struct timecycle clock_scale_factor;
+
/**
* gzvm_hypcall_wrapper() - the wrapper for hvc calls
* @a0-a7: arguments passed in registers 0 to 7
@@ -84,14 +91,22 @@ static inline u16 get_vcpuid_from_tuple(unsigned int tuple)
* @__pad: add an explicit '__u32 __pad;' in the middle to make it clear
* what the actual layout is.
* @lr: The array of LRs(list registers).
+ * @vtimer_delay: The remaining time until the next tick of guest VM.
+ * @vtimer_migrate: The switch flag used for guest VM to do vtimer migration or not.
+ * @vtimer_irq_num: vtimer irq number.
*
* - Keep the same layout of hypervisor data struct.
* - Sync list registers back for acking virtual device interrupt status.
+ * - Sync timer registers back for migrating timer to host's hwtimer to keep
+ * timer working in background.
*/
struct gzvm_vcpu_hwstate {
__le32 nr_lrs;
__le32 __pad;
__le64 lr[GIC_V3_NR_LRS];
+ __le64 vtimer_delay;
+ __le32 vtimer_migrate;
+ __le32 vtimer_irq_num;
};
static inline unsigned int
@@ -107,4 +122,7 @@ disassemble_vm_vcpu_tuple(unsigned int tuple, u16 *vmid, u16 *vcpuid)
*vcpuid = get_vcpuid_from_tuple(tuple);
}
+int gzvm_vgic_inject_ppi(struct gzvm *gzvm, unsigned int vcpu_idx,
+ u32 irq, bool level);
+
#endif /* __GZVM_ARCH_COMMON_H__ */
diff --git a/arch/arm64/geniezone/vcpu.c b/arch/arm64/geniezone/vcpu.c
index 95681fd66656..b26bbadf10a0 100644
--- a/arch/arm64/geniezone/vcpu.c
+++ b/arch/arm64/geniezone/vcpu.c
@@ -4,6 +4,7 @@
*/
#include <linux/arm-smccc.h>
+#include <linux/clocksource.h>
#include <linux/err.h>
#include <linux/uaccess.h>
@@ -40,25 +41,91 @@ int gzvm_arch_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, __u64 reg_id,
return ret;
}
+static void clear_migrate_state(struct gzvm_vcpu *vcpu)
+{
+ vcpu->hwstate->vtimer_migrate = 0;
+ vcpu->hwstate->vtimer_delay = 0;
+}
+
+static u64 gzvm_mtimer_delay_time(u64 delay)
+{
+ u64 ns;
+
+ ns = clocksource_cyc2ns(delay, clock_scale_factor.mult,
+ clock_scale_factor.shift);
+
+ return ns;
+}
+
+static void gzvm_mtimer_release(struct gzvm_vcpu *vcpu)
+{
+ hrtimer_cancel(&vcpu->gzvm_mtimer);
+
+ clear_migrate_state(vcpu);
+}
+
+static void gzvm_mtimer_catch(struct hrtimer *hrt, u64 delay)
+{
+ u64 ns;
+
+ ns = gzvm_mtimer_delay_time(delay);
+ hrtimer_start(hrt, ktime_add_ns(ktime_get(), ns), HRTIMER_MODE_ABS_HARD);
+}
+
+static void mtimer_irq_forward(struct gzvm_vcpu *vcpu)
+{
+ gzvm_vgic_inject_ppi(vcpu->gzvm, vcpu->vcpuid,
+ vcpu->hwstate->vtimer_irq_num, 1);
+}
+
+static enum hrtimer_restart gzvm_mtimer_expire(struct hrtimer *hrt)
+{
+ struct gzvm_vcpu *vcpu;
+
+ vcpu = container_of(hrt, struct gzvm_vcpu, gzvm_mtimer);
+
+ mtimer_irq_forward(vcpu);
+
+ return HRTIMER_NORESTART;
+}
+
+static void vtimer_init(struct gzvm_vcpu *vcpu)
+{
+ /* gzvm_mtimer init based on hrtimer */
+ hrtimer_init(&vcpu->gzvm_mtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
+ vcpu->gzvm_mtimer.function = gzvm_mtimer_expire;
+}
+
int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason)
{
struct arm_smccc_res res;
unsigned long a1;
int ret;
+ /* hrtimer cancel and clear migrate state */
+ if (vcpu->hwstate->vtimer_migrate)
+ gzvm_mtimer_release(vcpu);
+
a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid);
ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_RUN, a1, 0, 0, 0, 0, 0,
0, &res);
+
+ /* hrtimer register if migration needed */
+ if (vcpu->hwstate->vtimer_migrate)
+ gzvm_mtimer_catch(&vcpu->gzvm_mtimer, vcpu->hwstate->vtimer_delay);
+
*exit_reason = res.a1;
return ret;
}
-int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid)
+int gzvm_arch_destroy_vcpu(struct gzvm_vcpu *vcpu)
{
struct arm_smccc_res res;
unsigned long a1;
- a1 = assemble_vm_vcpu_tuple(vm_id, vcpuid);
+ hrtimer_cancel(&vcpu->gzvm_mtimer);
+
+ a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid);
gzvm_hypcall_wrapper(MT_HVC_GZVM_DESTROY_VCPU, a1, 0, 0, 0, 0, 0, 0,
&res);
@@ -67,20 +134,20 @@ int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid)
/**
* gzvm_arch_create_vcpu() - Call smc to gz hypervisor to create vcpu
- * @vm_id: vm id
- * @vcpuid: vcpu id
- * @run: Virtual address of vcpu->run
+ * @vcpu: Pointer to struct gzvm_vcpu
*
* Return: The wrapper helps caller to convert geniezone errno to Linux errno.
*/
-int gzvm_arch_create_vcpu(u16 vm_id, int vcpuid, void *run)
+int gzvm_arch_create_vcpu(struct gzvm_vcpu *vcpu)
{
struct arm_smccc_res res;
unsigned long a1, a2;
int ret;
- a1 = assemble_vm_vcpu_tuple(vm_id, vcpuid);
- a2 = (__u64)virt_to_phys(run);
+ vtimer_init(vcpu);
+
+ a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid);
+ a2 = (__u64)virt_to_phys(vcpu->run);
ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VCPU, a1, a2, 0, 0, 0, 0,
0, &res);
diff --git a/arch/arm64/geniezone/vgic.c b/arch/arm64/geniezone/vgic.c
index 3746e0c9e247..e24728997b57 100644
--- a/arch/arm64/geniezone/vgic.c
+++ b/arch/arm64/geniezone/vgic.c
@@ -91,6 +91,22 @@ static int gzvm_vgic_inject_spi(struct gzvm *gzvm, unsigned int vcpu_idx,
level);
}
+/**
+ * gzvm_vgic_inject_ppi() - Inject virtual ppi interrupt
+ * @gzvm: Pointer to struct gzvm
+ * @vcpu_idx: vcpu index
+ * @irq: This is spi interrupt number (starts from 0 instead of 32)
+ * @level: 1 if true else 0
+ *
+ * Return:
+ * * 0 if succeed else other negative values indicating each errors
+ */
+int gzvm_vgic_inject_ppi(struct gzvm *gzvm, unsigned int vcpu_idx,
+ u32 irq, bool level)
+{
+ return gzvm_vgic_inject_irq(gzvm, 0, GZVM_IRQ_TYPE_PPI, irq, level);
+}
+
int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev)
{
struct arm_smccc_res res;
diff --git a/drivers/virt/geniezone/gzvm_main.c b/drivers/virt/geniezone/gzvm_main.c
index d4d5d75d3660..a4c235f3ff01 100644
--- a/drivers/virt/geniezone/gzvm_main.c
+++ b/drivers/virt/geniezone/gzvm_main.c
@@ -106,6 +106,10 @@ static int gzvm_drv_probe(struct platform_device *pdev)
return -ENODEV;
}
+ ret = gzvm_arch_drv_init();
+ if (ret)
+ return ret;
+
ret = misc_register(&gzvm_dev);
if (ret)
return ret;
@@ -121,6 +125,7 @@ static int gzvm_drv_remove(struct platform_device *pdev)
gzvm_drv_irqfd_exit();
gzvm_destroy_all_vms();
misc_deregister(&gzvm_dev);
+ gzvm_arch_drv_exit();
return 0;
}
diff --git a/drivers/virt/geniezone/gzvm_vcpu.c b/drivers/virt/geniezone/gzvm_vcpu.c
index 72bd122a8be7..8dac8ba4c0cf 100644
--- a/drivers/virt/geniezone/gzvm_vcpu.c
+++ b/drivers/virt/geniezone/gzvm_vcpu.c
@@ -188,7 +188,7 @@ static void gzvm_destroy_vcpu(struct gzvm_vcpu *vcpu)
if (!vcpu)
return;
- gzvm_arch_destroy_vcpu(vcpu->gzvm->vm_id, vcpu->vcpuid);
+ gzvm_arch_destroy_vcpu(vcpu);
/* clean guest's data */
memset(vcpu->run, 0, GZVM_VCPU_RUN_MAP_SIZE);
free_pages_exact(vcpu->run, GZVM_VCPU_RUN_MAP_SIZE);
@@ -257,7 +257,7 @@ int gzvm_vm_ioctl_create_vcpu(struct gzvm *gzvm, u32 cpuid)
vcpu->gzvm = gzvm;
mutex_init(&vcpu->lock);
- ret = gzvm_arch_create_vcpu(gzvm->vm_id, vcpu->vcpuid, vcpu->run);
+ ret = gzvm_arch_create_vcpu(vcpu);
if (ret < 0)
goto free_vcpu_run;
diff --git a/include/linux/gzvm_drv.h b/include/linux/gzvm_drv.h
index 7bc00218dce6..e5b21ac9215b 100644
--- a/include/linux/gzvm_drv.h
+++ b/include/linux/gzvm_drv.h
@@ -6,6 +6,7 @@
#ifndef __GZVM_DRV_H__
#define __GZVM_DRV_H__
+#include <asm/arch_timer.h>
#include <linux/eventfd.h>
#include <linux/list.h>
#include <linux/mutex.h>
@@ -71,6 +72,7 @@ struct gzvm_vcpu {
struct mutex lock;
struct gzvm_vcpu_run *run;
struct gzvm_vcpu_hwstate *hwstate;
+ struct hrtimer gzvm_mtimer;
};
struct gzvm {
@@ -125,10 +127,12 @@ u64 gzvm_hva_to_pa_arch(u64 hva);
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_create_vcpu(u16 vm_id, int vcpuid, void *run);
+int gzvm_arch_create_vcpu(struct gzvm_vcpu *vcpu);
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_destroy_vcpu(struct gzvm_vcpu *vcpu);
int gzvm_arch_inform_exit(u16 vm_id);
+int gzvm_arch_drv_init(void);
+void gzvm_arch_drv_exit(void);
int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev);
int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-07-27 8:04 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-27 7:59 [PATCH v5 00/12] GenieZone hypervisor drivers Yi-De Wu
2023-07-27 7:59 ` Yi-De Wu
2023-07-27 7:59 ` [PATCH v5 01/12] docs: geniezone: Introduce GenieZone hypervisor Yi-De Wu
2023-07-27 7:59 ` Yi-De Wu
2023-07-27 7:59 ` [PATCH v5 02/12] dt-bindings: hypervisor: Add MediaTek " Yi-De Wu
2023-07-27 7:59 ` Yi-De Wu
2023-07-27 7:59 ` [PATCH v5 03/12] virt: geniezone: Add GenieZone hypervisor support Yi-De Wu
2023-07-27 7:59 ` Yi-De Wu
2023-07-27 8:51 ` Eugen Hristev
2023-07-27 8:51 ` Eugen Hristev
2023-08-01 7:03 ` Yi-De Wu (吳一德)
2023-08-01 7:03 ` Yi-De Wu (吳一德)
2023-07-27 10:08 ` AngeloGioacchino Del Regno
2023-07-27 10:08 ` AngeloGioacchino Del Regno
2023-07-27 7:59 ` [PATCH v5 04/12] virt: geniezone: Add vcpu support Yi-De Wu
2023-07-27 7:59 ` Yi-De Wu
2023-08-11 17:00 ` Rob Herring
2023-08-11 17:00 ` Rob Herring
2023-08-15 9:53 ` Will Deacon
2023-08-15 9:53 ` Will Deacon
2023-08-31 6:54 ` Yi-De Wu (吳一德)
2023-08-31 6:54 ` Yi-De Wu (吳一德)
2023-07-27 7:59 ` [PATCH v5 05/12] virt: geniezone: Add irqchip support for virtual interrupt injection Yi-De Wu
2023-07-27 7:59 ` Yi-De Wu
2023-07-27 7:59 ` [PATCH v5 06/12] virt: geniezone: Add irqfd support Yi-De Wu
2023-07-27 7:59 ` Yi-De Wu
2023-07-27 8:00 ` [PATCH v5 07/12] virt: geniezone: Add ioeventfd support Yi-De Wu
2023-07-27 8:00 ` Yi-De Wu
2023-07-27 8:00 ` [PATCH v5 08/12] virt: geniezone: Add memory region support Yi-De Wu
2023-07-27 8:00 ` Yi-De Wu
2023-07-27 8:00 ` [PATCH v5 09/12] virt: geniezone: Add dtb config support Yi-De Wu
2023-07-27 8:00 ` Yi-De Wu
2023-07-27 8:00 ` Yi-De Wu [this message]
2023-07-27 8:00 ` [PATCH v5 10/12] virt: geniezone: Add virtual timer support Yi-De Wu
2023-07-27 8:00 ` [PATCH v5 11/12] virt: geniezone: Add guest page fault handler Yi-De Wu
2023-07-27 8:00 ` Yi-De Wu
2023-07-27 8:00 ` [PATCH v5 12/12] virt: geniezone: Add memory pin/unpin support Yi-De Wu
2023-07-27 8:00 ` Yi-De Wu
2023-07-27 17:28 ` Elliot Berman
2023-07-27 17:28 ` Elliot Berman
2023-08-11 16:52 ` [PATCH v5 00/12] GenieZone hypervisor drivers Rob Herring
2023-08-11 16:52 ` Rob Herring
2023-08-17 7:31 ` Yi-De Wu (吳一德)
2023-08-17 7:31 ` Yi-De Wu (吳一德)
2023-08-31 8:09 ` Yi-De Wu (吳一德)
2023-08-31 8:09 ` Yi-De Wu (吳一德)
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=20230727080005.14474-11-yi-de.wu@mediatek.com \
--to=yi-de.wu@mediatek.com \
--cc=angelogioacchino.delregno@collabora.com \
--cc=arnd@arndb.de \
--cc=catalin.marinas@arm.com \
--cc=chi-shen.yeh@mediatek.com \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=dbrazdil@google.com \
--cc=devicetree@vger.kernel.org \
--cc=ivan.tseng@mediatek.com \
--cc=jades.shih@mediatek.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=liju-clr.chen@mediatek.com \
--cc=linux-arch@vger.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=matthias.bgg@gmail.com \
--cc=my.chuang@mediatek.com \
--cc=peilun.suei@mediatek.com \
--cc=quic_tsoni@quicinc.com \
--cc=robh+dt@kernel.org \
--cc=shawn.hsiao@mediatek.com \
--cc=will@kernel.org \
--cc=yingshiuan.pan@mediatek.com \
--cc=ze-yu.wang@mediatek.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.