• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)26 static 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)60 bool 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