1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2023 MediaTek Inc. 4 */ 5 #include <linux/clocksource.h> 6 #include <linux/kernel.h> 7 #include <linux/timekeeping.h> 8 #include <linux/soc/mediatek/gzvm_drv.h> 9 #include "gzvm_arch_common.h" 10 11 #define GZVM_PTP_VIRT_COUNTER 0 12 #define GZVM_PTP_PHYS_COUNTER 1 13 /** 14 * gzvm_handle_ptp_time() - Sync time between host and guest VM 15 * @vcpu: Pointer to struct gzvm_vcpu_run in userspace 16 * @counter: Counter type from guest VM 17 * Return: Always return 0 because there are no cases of failure 18 * 19 * The following register values will be passed to the guest VM 20 * for time synchronization: 21 * regs->x0 (upper 32 bits) wall clock time 22 * regs->x1 (lower 32 bits) wall clock time 23 * regs->x2 (upper 32 bits) cycles 24 * regs->x3 (lower 32 bits) cycles 25 */ gzvm_handle_ptp_time(struct gzvm_vcpu * vcpu,int counter)26static int gzvm_handle_ptp_time(struct gzvm_vcpu *vcpu, int counter) 27 { 28 struct system_time_snapshot snapshot; 29 u64 cycles = 0; 30 31 ktime_get_snapshot(&snapshot); 32 33 switch (counter) { 34 case GZVM_PTP_VIRT_COUNTER: 35 cycles = snapshot.cycles - 36 le64_to_cpu(vcpu->hwstate->vtimer_offset); 37 break; 38 case GZVM_PTP_PHYS_COUNTER: 39 cycles = snapshot.cycles; 40 break; 41 default: 42 break; 43 } 44 45 vcpu->run->hypercall.args[0] = upper_32_bits(snapshot.real); 46 vcpu->run->hypercall.args[1] = lower_32_bits(snapshot.real); 47 vcpu->run->hypercall.args[2] = upper_32_bits(cycles); 48 vcpu->run->hypercall.args[3] = lower_32_bits(cycles); 49 50 return 0; 51 } 52 53 /** 54 * gzvm_arch_handle_guest_hvc() - Handle architecture-related guest hvc 55 * @vcpu: Pointer to struct gzvm_vcpu_run in userspace 56 * Return: 57 * * true - This hvc has been processed, no need to back to VMM. 58 * * false - This hvc has not been processed, require userspace. 59 */ gzvm_arch_handle_guest_hvc(struct gzvm_vcpu * vcpu)60bool gzvm_arch_handle_guest_hvc(struct gzvm_vcpu *vcpu) 61 { 62 int ret, counter; 63 64 switch (vcpu->run->hypercall.args[0]) { 65 case GZVM_HVC_PTP: 66 counter = vcpu->run->hypercall.args[1]; 67 ret = gzvm_handle_ptp_time(vcpu, counter); 68 return (ret == 0) ? true : false; 69 default: 70 break; 71 } 72 return false; 73 } 74