]>
Commit | Line | Data |
---|---|---|
eb035b48 PM |
1 | /* |
2 | * QEMU KVM support -- ARM specific functions. | |
3 | * | |
4 | * Copyright (c) 2012 Linaro Limited | |
5 | * | |
6 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
7 | * See the COPYING file in the top-level directory. | |
8 | * | |
9 | */ | |
10 | ||
11 | #ifndef QEMU_KVM_ARM_H | |
12 | #define QEMU_KVM_ARM_H | |
13 | ||
14 | #include "sysemu/kvm.h" | |
15 | #include "exec/memory.h" | |
1b20616f | 16 | #include "qemu/error-report.h" |
eb035b48 | 17 | |
228d5e04 PS |
18 | /** |
19 | * kvm_arm_vcpu_init: | |
20 | * @cs: CPUState | |
21 | * | |
22 | * Initialize (or reinitialize) the VCPU by invoking the | |
23 | * KVM_ARM_VCPU_INIT ioctl with the CPU type and feature | |
24 | * bitmask specified in the CPUState. | |
25 | * | |
26 | * Returns: 0 if success else < 0 error code | |
27 | */ | |
28 | int kvm_arm_vcpu_init(CPUState *cs); | |
29 | ||
eb035b48 PM |
30 | /** |
31 | * kvm_arm_register_device: | |
32 | * @mr: memory region for this device | |
33 | * @devid: the KVM device ID | |
1da41cc1 CD |
34 | * @group: device control API group for setting addresses |
35 | * @attr: device control API address type | |
36 | * @dev_fd: device control device file descriptor (or -1 if not supported) | |
eb035b48 PM |
37 | * |
38 | * Remember the memory region @mr, and when it is mapped by the | |
39 | * machine model, tell the kernel that base address using the | |
1da41cc1 CD |
40 | * KVM_ARM_SET_DEVICE_ADDRESS ioctl or the newer device control API. @devid |
41 | * should be the ID of the device as defined by KVM_ARM_SET_DEVICE_ADDRESS or | |
42 | * the arm-vgic device in the device control API. | |
43 | * The machine model may map | |
44 | * and unmap the device multiple times; the kernel will only be told the final | |
45 | * address at the point where machine init is complete. | |
eb035b48 | 46 | */ |
1da41cc1 CD |
47 | void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, |
48 | uint64_t attr, int dev_fd); | |
eb035b48 | 49 | |
38df27c8 AB |
50 | /** |
51 | * kvm_arm_init_cpreg_list: | |
52 | * @cs: CPUState | |
53 | * | |
54 | * Initialize the CPUState's cpreg list according to the kernel's | |
55 | * definition of what CPU registers it knows about (and throw away | |
56 | * the previous TCG-created cpreg list). | |
57 | * | |
58 | * Returns: 0 if success, else < 0 error code | |
59 | */ | |
60 | int kvm_arm_init_cpreg_list(ARMCPU *cpu); | |
61 | ||
62 | /** | |
63 | * kvm_arm_reg_syncs_via_cpreg_list | |
64 | * regidx: KVM register index | |
65 | * | |
66 | * Return true if this KVM register should be synchronized via the | |
67 | * cpreg list of arbitrary system registers, false if it is synchronized | |
68 | * by hand using code in kvm_arch_get/put_registers(). | |
69 | */ | |
70 | bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx); | |
71 | ||
4b7a6bf4 CD |
72 | /** |
73 | * kvm_arm_cpreg_level | |
74 | * regidx: KVM register index | |
75 | * | |
76 | * Return the level of this coprocessor/system register. Return value is | |
77 | * either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE. | |
78 | */ | |
79 | int kvm_arm_cpreg_level(uint64_t regidx); | |
80 | ||
ff047453 PM |
81 | /** |
82 | * write_list_to_kvmstate: | |
83 | * @cpu: ARMCPU | |
4b7a6bf4 | 84 | * @level: the state level to sync |
ff047453 PM |
85 | * |
86 | * For each register listed in the ARMCPU cpreg_indexes list, write | |
87 | * its value from the cpreg_values list into the kernel (via ioctl). | |
88 | * This updates KVM's working data structures from TCG data or | |
89 | * from incoming migration state. | |
90 | * | |
91 | * Returns: true if all register values were updated correctly, | |
92 | * false if some register was unknown to the kernel or could not | |
93 | * be written (eg constant register with the wrong value). | |
94 | * Note that we do not stop early on failure -- we will attempt | |
95 | * writing all registers in the list. | |
96 | */ | |
4b7a6bf4 | 97 | bool write_list_to_kvmstate(ARMCPU *cpu, int level); |
ff047453 PM |
98 | |
99 | /** | |
100 | * write_kvmstate_to_list: | |
101 | * @cpu: ARMCPU | |
102 | * | |
103 | * For each register listed in the ARMCPU cpreg_indexes list, write | |
104 | * its value from the kernel into the cpreg_values list. This is used to | |
105 | * copy info from KVM's working data structures into TCG or | |
106 | * for outbound migration. | |
107 | * | |
108 | * Returns: true if all register values were read correctly, | |
109 | * false if some register was unknown or could not be read. | |
110 | * Note that we do not stop early on failure -- we will attempt | |
111 | * reading all registers in the list. | |
112 | */ | |
113 | bool write_kvmstate_to_list(ARMCPU *cpu); | |
114 | ||
50a2c6e5 PB |
115 | /** |
116 | * kvm_arm_reset_vcpu: | |
117 | * @cpu: ARMCPU | |
118 | * | |
119 | * Called at reset time to kernel registers to their initial values. | |
120 | */ | |
121 | void kvm_arm_reset_vcpu(ARMCPU *cpu); | |
122 | ||
a96c0514 PM |
123 | #ifdef CONFIG_KVM |
124 | /** | |
125 | * kvm_arm_create_scratch_host_vcpu: | |
126 | * @cpus_to_try: array of QEMU_KVM_ARM_TARGET_* values (terminated with | |
127 | * QEMU_KVM_ARM_TARGET_NONE) to try as fallback if the kernel does not | |
2f340e9c PX |
128 | * know the PREFERRED_TARGET ioctl. Passing NULL is the same as passing |
129 | * an empty array. | |
a96c0514 | 130 | * @fdarray: filled in with kvmfd, vmfd, cpufd file descriptors in that order |
2f340e9c PX |
131 | * @init: filled in with the necessary values for creating a host |
132 | * vcpu. If NULL is provided, will not init the vCPU (though the cpufd | |
133 | * will still be set up). | |
a96c0514 PM |
134 | * |
135 | * Create a scratch vcpu in its own VM of the type preferred by the host | |
136 | * kernel (as would be used for '-cpu host'), for purposes of probing it | |
137 | * for capabilities. | |
138 | * | |
139 | * Returns: true on success (and fdarray and init are filled in), | |
140 | * false on failure (and fdarray and init are not valid). | |
141 | */ | |
142 | bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try, | |
143 | int *fdarray, | |
144 | struct kvm_vcpu_init *init); | |
145 | ||
146 | /** | |
147 | * kvm_arm_destroy_scratch_host_vcpu: | |
148 | * @fdarray: array of fds as set up by kvm_arm_create_scratch_host_vcpu | |
149 | * | |
150 | * Tear down the scratch vcpu created by kvm_arm_create_scratch_host_vcpu. | |
151 | */ | |
152 | void kvm_arm_destroy_scratch_host_vcpu(int *fdarray); | |
153 | ||
154 | #define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU | |
155 | #define ARM_HOST_CPU_CLASS(klass) \ | |
156 | OBJECT_CLASS_CHECK(ARMHostCPUClass, (klass), TYPE_ARM_HOST_CPU) | |
157 | #define ARM_HOST_CPU_GET_CLASS(obj) \ | |
158 | OBJECT_GET_CLASS(ARMHostCPUClass, (obj), TYPE_ARM_HOST_CPU) | |
159 | ||
160 | typedef struct ARMHostCPUClass { | |
161 | /*< private >*/ | |
162 | ARMCPUClass parent_class; | |
163 | /*< public >*/ | |
164 | ||
165 | uint64_t features; | |
166 | uint32_t target; | |
167 | const char *dtb_compatible; | |
168 | } ARMHostCPUClass; | |
169 | ||
170 | /** | |
171 | * kvm_arm_get_host_cpu_features: | |
172 | * @ahcc: ARMHostCPUClass to fill in | |
173 | * | |
174 | * Probe the capabilities of the host kernel's preferred CPU and fill | |
175 | * in the ARMHostCPUClass struct accordingly. | |
176 | */ | |
177 | bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc); | |
178 | ||
1a1753f7 AB |
179 | |
180 | /** | |
181 | * kvm_arm_sync_mpstate_to_kvm | |
182 | * @cpu: ARMCPU | |
183 | * | |
184 | * If supported set the KVM MP_STATE based on QEMU's model. | |
185 | */ | |
186 | int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu); | |
187 | ||
188 | /** | |
189 | * kvm_arm_sync_mpstate_to_qemu | |
190 | * @cpu: ARMCPU | |
191 | * | |
192 | * If supported get the MP_STATE from KVM and store in QEMU's model. | |
193 | */ | |
194 | int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu); | |
195 | ||
34e85cd9 PF |
196 | int kvm_arm_vgic_probe(void); |
197 | ||
b2bfe9f7 AJ |
198 | void kvm_arm_pmu_set_irq(CPUState *cs, int irq); |
199 | void kvm_arm_pmu_init(CPUState *cs); | |
01fe6b60 | 200 | |
34e85cd9 PF |
201 | #else |
202 | ||
203 | static inline int kvm_arm_vgic_probe(void) | |
204 | { | |
205 | return 0; | |
206 | } | |
207 | ||
b2bfe9f7 AJ |
208 | static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {} |
209 | static inline void kvm_arm_pmu_init(CPUState *cs) {} | |
01fe6b60 | 210 | |
a96c0514 PM |
211 | #endif |
212 | ||
e6fbcbc4 PF |
213 | static inline const char *gic_class_name(void) |
214 | { | |
215 | return kvm_irqchip_in_kernel() ? "kvm-arm-gic" : "arm_gic"; | |
216 | } | |
217 | ||
a7bf3034 PF |
218 | /** |
219 | * gicv3_class_name | |
220 | * | |
221 | * Return name of GICv3 class to use depending on whether KVM acceleration is | |
222 | * in use. May throw an error if the chosen implementation is not available. | |
223 | * | |
224 | * Returns: class name to use | |
225 | */ | |
1b20616f EA |
226 | static inline const char *gicv3_class_name(void) |
227 | { | |
228 | if (kvm_irqchip_in_kernel()) { | |
229 | #ifdef TARGET_AARCH64 | |
230 | return "kvm-arm-gicv3"; | |
231 | #else | |
232 | error_report("KVM GICv3 acceleration is not supported on this " | |
233 | "platform"); | |
234 | exit(1); | |
235 | #endif | |
236 | } else { | |
237 | return "arm-gicv3"; | |
238 | } | |
239 | } | |
a7bf3034 | 240 | |
2ecb2027 AB |
241 | /** |
242 | * kvm_arm_handle_debug: | |
243 | * @cs: CPUState | |
244 | * @debug_exit: debug part of the KVM exit structure | |
245 | * | |
246 | * Returns: TRUE if the debug exception was handled. | |
247 | */ | |
248 | bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit); | |
249 | ||
e4482ab7 AB |
250 | /** |
251 | * kvm_arm_hw_debug_active: | |
252 | * @cs: CPU State | |
253 | * | |
254 | * Return: TRUE if any hardware breakpoints in use. | |
255 | */ | |
256 | ||
257 | bool kvm_arm_hw_debug_active(CPUState *cs); | |
258 | ||
259 | /** | |
260 | * kvm_arm_copy_hw_debug_data: | |
261 | * | |
262 | * @ptr: kvm_guest_debug_arch structure | |
263 | * | |
264 | * Copy the architecture specific debug registers into the | |
265 | * kvm_guest_debug ioctl structure. | |
266 | */ | |
267 | struct kvm_guest_debug_arch; | |
268 | ||
269 | void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr); | |
270 | ||
386ce3c7 PF |
271 | /** |
272 | * its_class_name | |
273 | * | |
274 | * Return the ITS class name to use depending on whether KVM acceleration | |
275 | * and KVM CAP_SIGNAL_MSI are supported | |
276 | * | |
277 | * Returns: class name to use or NULL | |
278 | */ | |
279 | static inline const char *its_class_name(void) | |
280 | { | |
281 | if (kvm_irqchip_in_kernel()) { | |
282 | /* KVM implementation requires this capability */ | |
283 | return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL; | |
284 | } else { | |
285 | /* Software emulation is not implemented yet */ | |
286 | return NULL; | |
287 | } | |
288 | } | |
289 | ||
eb035b48 | 290 | #endif |