FROMLIST: virt: geniezone: Enable PTP for synchronizing time between host and guest VMs
Enabled Precision Time Protocol (PTP) for improved host-guest VM time synchronization, optimizing operations needing precise clock sync in virtual environment. Signed-off-by: Kevenny Hsieh <kevenny.hsieh@mediatek.com> Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com> Signed-off-by: Liju Chen <liju-clr.chen@mediatek.com> Change-Id: Id236519e48e44713b20d75b80524921ddc0abc3f Bug: 379230831 Link: https://lore.kernel.org/lkml/20241114100802.4116-22-liju-clr.chen@mediatek.com/
This commit is contained in:
committed by
Liju-clr Chen
parent
66a0f826f2
commit
76dceb11f2
@@ -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 hvc.o
|
||||
|
||||
obj-$(CONFIG_MTK_GZVM) += gzvm.o
|
||||
|
||||
@@ -83,6 +83,8 @@ int gzvm_hypcall_wrapper(unsigned long a0, unsigned long a1,
|
||||
* @__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_offset: The offset maintained by hypervisor that is host cycle count
|
||||
* when guest VM startup.
|
||||
*
|
||||
* - Keep the same layout of hypervisor data struct.
|
||||
* - Sync list registers back for acking virtual device interrupt status.
|
||||
@@ -91,6 +93,7 @@ struct gzvm_vcpu_hwstate {
|
||||
__le32 nr_lrs;
|
||||
__le32 __pad;
|
||||
__le64 lr[GIC_V3_NR_LRS];
|
||||
__le64 vtimer_offset;
|
||||
};
|
||||
|
||||
static inline unsigned int
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023 MediaTek Inc.
|
||||
*/
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include <linux/soc/mediatek/gzvm_drv.h>
|
||||
#include "gzvm_arch_common.h"
|
||||
|
||||
#define GZVM_PTP_VIRT_COUNTER 0
|
||||
#define GZVM_PTP_PHYS_COUNTER 1
|
||||
/**
|
||||
* gzvm_handle_ptp_time() - Sync time between host and guest VM
|
||||
* @vcpu: Pointer to struct gzvm_vcpu_run in userspace
|
||||
* @counter: Counter type from guest VM
|
||||
* Return: Always return 0 because there are no cases of failure
|
||||
*
|
||||
* The following register values will be passed to the guest VM
|
||||
* for time synchronization:
|
||||
* regs->x0 (upper 32 bits) wall clock time
|
||||
* regs->x1 (lower 32 bits) wall clock time
|
||||
* regs->x2 (upper 32 bits) cycles
|
||||
* regs->x3 (lower 32 bits) cycles
|
||||
*/
|
||||
static int gzvm_handle_ptp_time(struct gzvm_vcpu *vcpu, int counter)
|
||||
{
|
||||
struct system_time_snapshot snapshot;
|
||||
u64 cycles = 0;
|
||||
|
||||
ktime_get_snapshot(&snapshot);
|
||||
|
||||
switch (counter) {
|
||||
case GZVM_PTP_VIRT_COUNTER:
|
||||
cycles = snapshot.cycles -
|
||||
le64_to_cpu(vcpu->hwstate->vtimer_offset);
|
||||
break;
|
||||
case GZVM_PTP_PHYS_COUNTER:
|
||||
cycles = snapshot.cycles;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vcpu->run->hypercall.args[0] = upper_32_bits(snapshot.real);
|
||||
vcpu->run->hypercall.args[1] = lower_32_bits(snapshot.real);
|
||||
vcpu->run->hypercall.args[2] = upper_32_bits(cycles);
|
||||
vcpu->run->hypercall.args[3] = lower_32_bits(cycles);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gzvm_arch_handle_guest_hvc() - Handle architecture-related guest hvc
|
||||
* @vcpu: Pointer to struct gzvm_vcpu_run in userspace
|
||||
* Return:
|
||||
* * true - This hvc has been processed, no need to back to VMM.
|
||||
* * false - This hvc has not been processed, require userspace.
|
||||
*/
|
||||
bool gzvm_arch_handle_guest_hvc(struct gzvm_vcpu *vcpu)
|
||||
{
|
||||
int ret, counter;
|
||||
|
||||
switch (vcpu->run->hypercall.args[0]) {
|
||||
case GZVM_HVC_PTP:
|
||||
counter = vcpu->run->hypercall.args[1];
|
||||
ret = gzvm_handle_ptp_time(vcpu, counter);
|
||||
return (ret == 0) ? true : false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -56,7 +56,6 @@ bool gzvm_handle_guest_hvc(struct gzvm_vcpu *vcpu)
|
||||
ret = gzvm_handle_relinquish(vcpu, ipa);
|
||||
return (ret == 0) ? true : false;
|
||||
default:
|
||||
break;
|
||||
return gzvm_arch_handle_guest_hvc(vcpu);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -252,6 +252,7 @@ int gzvm_handle_page_fault(struct gzvm_vcpu *vcpu);
|
||||
bool gzvm_handle_guest_exception(struct gzvm_vcpu *vcpu);
|
||||
int gzvm_handle_relinquish(struct gzvm_vcpu *vcpu, phys_addr_t ipa);
|
||||
bool gzvm_handle_guest_hvc(struct gzvm_vcpu *vcpu);
|
||||
bool gzvm_arch_handle_guest_hvc(struct gzvm_vcpu *vcpu);
|
||||
|
||||
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,
|
||||
|
||||
@@ -198,6 +198,7 @@ enum {
|
||||
|
||||
/* hypercall definitions of GZVM_EXIT_HYPERCALL */
|
||||
enum {
|
||||
GZVM_HVC_PTP = 0x86000001,
|
||||
GZVM_HVC_MEM_RELINQUISH = 0xc6000009,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user