// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2023 MediaTek Inc. */ #include #include #include #include #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; }