1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2023 MediaTek Inc.
4 */
5
6 #include <linux/arm-smccc.h>
7 #include <linux/err.h>
8 #include <linux/uaccess.h>
9
10 #include <linux/gzvm.h>
11 #include <linux/soc/mediatek/gzvm_drv.h>
12 #include "gzvm_arch_common.h"
13
gzvm_vcpu_arch_get_timer_delay_ns(struct gzvm_vcpu * vcpu)14 u64 gzvm_vcpu_arch_get_timer_delay_ns(struct gzvm_vcpu *vcpu)
15 {
16 u64 ns;
17
18 if (vcpu->hwstate->vtimer_migrate) {
19 ns = clocksource_cyc2ns(le64_to_cpu(vcpu->hwstate->vtimer_delay),
20 gzvm_vtimer_get_clock_mult(),
21 gzvm_vtimer_get_clock_shift());
22 } else {
23 ns = 0;
24 }
25
26 /* 0: no migrate, otherwise: migrate */
27 return ns;
28 }
29
gzvm_arch_vcpu_update_one_reg(struct gzvm_vcpu * vcpu,__u64 reg_id,bool is_write,__u64 * data)30 int gzvm_arch_vcpu_update_one_reg(struct gzvm_vcpu *vcpu, __u64 reg_id,
31 bool is_write, __u64 *data)
32 {
33 struct arm_smccc_res res;
34 unsigned long a1;
35 int ret;
36
37 a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid);
38 if (!is_write) {
39 ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_GET_ONE_REG,
40 a1, reg_id, 0, 0, 0, 0, 0, &res);
41 if (ret == 0)
42 *data = res.a1;
43 } else {
44 ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_SET_ONE_REG,
45 a1, reg_id, *data, 0, 0, 0, 0, &res);
46 }
47
48 return ret;
49 }
50
gzvm_arch_vcpu_run(struct gzvm_vcpu * vcpu,__u64 * exit_reason)51 int gzvm_arch_vcpu_run(struct gzvm_vcpu *vcpu, __u64 *exit_reason)
52 {
53 struct arm_smccc_res res;
54 unsigned long a1;
55 int ret;
56
57 a1 = assemble_vm_vcpu_tuple(vcpu->gzvm->vm_id, vcpu->vcpuid);
58 ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_RUN, a1, 0, 0, 0, 0, 0,
59 0, &res);
60 *exit_reason = res.a1;
61 return ret;
62 }
63
gzvm_arch_destroy_vcpu(u16 vm_id,int vcpuid)64 int gzvm_arch_destroy_vcpu(u16 vm_id, int vcpuid)
65 {
66 struct arm_smccc_res res;
67 unsigned long a1;
68
69 a1 = assemble_vm_vcpu_tuple(vm_id, vcpuid);
70 gzvm_hypcall_wrapper(MT_HVC_GZVM_DESTROY_VCPU, a1, 0, 0, 0, 0, 0, 0,
71 &res);
72
73 return 0;
74 }
75
76 /**
77 * gzvm_arch_create_vcpu() - Call smc to gz hypervisor to create vcpu
78 * @vm_id: vm id
79 * @vcpuid: vcpu id
80 * @run: Virtual address of vcpu->run
81 *
82 * Return: The wrapper helps caller to convert geniezone errno to Linux errno.
83 */
gzvm_arch_create_vcpu(u16 vm_id,int vcpuid,void * run)84 int gzvm_arch_create_vcpu(u16 vm_id, int vcpuid, void *run)
85 {
86 struct arm_smccc_res res;
87 unsigned long a1, a2;
88 int ret;
89
90 a1 = assemble_vm_vcpu_tuple(vm_id, vcpuid);
91 a2 = (__u64)virt_to_phys(run);
92 ret = gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_VCPU, a1, a2, 0, 0, 0, 0,
93 0, &res);
94
95 return ret;
96 }
97