1 | /* |
---|
2 | * Freescale hypervisor call interface |
---|
3 | * |
---|
4 | * Copyright 2008-2010 Freescale Semiconductor, Inc. |
---|
5 | * |
---|
6 | * Author: Timur Tabi <timur@freescale.com> |
---|
7 | * |
---|
8 | * This file is provided under a dual BSD/GPL license. When using or |
---|
9 | * redistributing this file, you may do so under either license. |
---|
10 | * |
---|
11 | * Redistribution and use in source and binary forms, with or without |
---|
12 | * modification, are permitted provided that the following conditions are met: |
---|
13 | * * Redistributions of source code must retain the above copyright |
---|
14 | * notice, this list of conditions and the following disclaimer. |
---|
15 | * * Redistributions in binary form must reproduce the above copyright |
---|
16 | * notice, this list of conditions and the following disclaimer in the |
---|
17 | * documentation and/or other materials provided with the distribution. |
---|
18 | * * Neither the name of Freescale Semiconductor nor the |
---|
19 | * names of its contributors may be used to endorse or promote products |
---|
20 | * derived from this software without specific prior written permission. |
---|
21 | * |
---|
22 | * |
---|
23 | * ALTERNATIVELY, this software may be distributed under the terms of the |
---|
24 | * GNU General Public License ("GPL") as published by the Free Software |
---|
25 | * Foundation, either version 2 of that License or (at your option) any |
---|
26 | * later version. |
---|
27 | * |
---|
28 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY |
---|
29 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
---|
30 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
---|
31 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY |
---|
32 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
---|
33 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
---|
34 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
---|
35 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
---|
36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
---|
37 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
38 | */ |
---|
39 | |
---|
40 | #ifndef _FSL_HCALLS_H |
---|
41 | #define _FSL_HCALLS_H |
---|
42 | |
---|
43 | #include <stdint.h> |
---|
44 | #include <asm/epapr_hcalls.h> |
---|
45 | |
---|
46 | #define FH_API_VERSION 1 |
---|
47 | |
---|
48 | #define FH_ERR_GET_INFO 1 |
---|
49 | #define FH_PARTITION_GET_DTPROP 2 |
---|
50 | #define FH_PARTITION_SET_DTPROP 3 |
---|
51 | #define FH_PARTITION_RESTART 4 |
---|
52 | #define FH_PARTITION_GET_STATUS 5 |
---|
53 | #define FH_PARTITION_START 6 |
---|
54 | #define FH_PARTITION_STOP 7 |
---|
55 | #define FH_PARTITION_MEMCPY 8 |
---|
56 | #define FH_DMA_ENABLE 9 |
---|
57 | #define FH_DMA_DISABLE 10 |
---|
58 | #define FH_SEND_NMI 11 |
---|
59 | #define FH_VMPIC_GET_MSIR 12 |
---|
60 | #define FH_SYSTEM_RESET 13 |
---|
61 | #define FH_GET_CORE_STATE 14 |
---|
62 | #define FH_ENTER_NAP 15 |
---|
63 | #define FH_EXIT_NAP 16 |
---|
64 | #define FH_CLAIM_DEVICE 17 |
---|
65 | #define FH_PARTITION_STOP_DMA 18 |
---|
66 | |
---|
67 | /* vendor ID: Freescale Semiconductor */ |
---|
68 | #define FH_HCALL_TOKEN(num) _EV_HCALL_TOKEN(EV_FSL_VENDOR_ID, num) |
---|
69 | |
---|
70 | /* |
---|
71 | * We use "uintptr_t" to define a register because it's guaranteed to be a |
---|
72 | * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit |
---|
73 | * platform. |
---|
74 | * |
---|
75 | * All registers are either input/output or output only. Registers that are |
---|
76 | * initialized before making the hypercall are input/output. All |
---|
77 | * input/output registers are represented with "+r". Output-only registers |
---|
78 | * are represented with "=r". Do not specify any unused registers. The |
---|
79 | * clobber list will tell the compiler that the hypercall modifies those |
---|
80 | * registers, which is good enough. |
---|
81 | */ |
---|
82 | |
---|
83 | /** |
---|
84 | * fh_send_nmi - send NMI to virtual cpu(s). |
---|
85 | * @vcpu_mask: send NMI to virtual cpu(s) specified by this mask. |
---|
86 | * |
---|
87 | * Returns 0 for success, or EINVAL for invalid vcpu_mask. |
---|
88 | */ |
---|
89 | static inline unsigned int fh_send_nmi(unsigned int vcpu_mask) |
---|
90 | { |
---|
91 | register uintptr_t r11 __asm__("r11"); |
---|
92 | register uintptr_t r3 __asm__("r3"); |
---|
93 | |
---|
94 | r11 = FH_HCALL_TOKEN(FH_SEND_NMI); |
---|
95 | r3 = vcpu_mask; |
---|
96 | |
---|
97 | asm volatile("bl epapr_hypercall_start" |
---|
98 | : "+r" (r11), "+r" (r3) |
---|
99 | : : EV_HCALL_CLOBBERS1 |
---|
100 | ); |
---|
101 | |
---|
102 | return r3; |
---|
103 | } |
---|
104 | |
---|
105 | /* Arbitrary limits to avoid excessive memory allocation in hypervisor */ |
---|
106 | #define FH_DTPROP_MAX_PATHLEN 4096 |
---|
107 | #define FH_DTPROP_MAX_PROPLEN 32768 |
---|
108 | |
---|
109 | /** |
---|
110 | * fh_partition_get_dtprop - get a property from a guest device tree. |
---|
111 | * @handle: handle of partition whose device tree is to be accessed |
---|
112 | * @dtpath_addr: physical address of device tree path to access |
---|
113 | * @propname_addr: physical address of name of property |
---|
114 | * @propvalue_addr: physical address of property value buffer |
---|
115 | * @propvalue_len: length of buffer on entry, length of property on return |
---|
116 | * |
---|
117 | * Returns zero on success, non-zero on error. |
---|
118 | */ |
---|
119 | static inline unsigned int fh_partition_get_dtprop(int handle, |
---|
120 | uint64_t dtpath_addr, |
---|
121 | uint64_t propname_addr, |
---|
122 | uint64_t propvalue_addr, |
---|
123 | uint32_t *propvalue_len) |
---|
124 | { |
---|
125 | register uintptr_t r11 __asm__("r11"); |
---|
126 | register uintptr_t r3 __asm__("r3"); |
---|
127 | register uintptr_t r4 __asm__("r4"); |
---|
128 | register uintptr_t r5 __asm__("r5"); |
---|
129 | register uintptr_t r6 __asm__("r6"); |
---|
130 | register uintptr_t r7 __asm__("r7"); |
---|
131 | register uintptr_t r8 __asm__("r8"); |
---|
132 | register uintptr_t r9 __asm__("r9"); |
---|
133 | register uintptr_t r10 __asm__("r10"); |
---|
134 | |
---|
135 | r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_DTPROP); |
---|
136 | r3 = handle; |
---|
137 | |
---|
138 | #ifdef CONFIG_PHYS_64BIT |
---|
139 | r4 = dtpath_addr >> 32; |
---|
140 | r6 = propname_addr >> 32; |
---|
141 | r8 = propvalue_addr >> 32; |
---|
142 | #else |
---|
143 | r4 = 0; |
---|
144 | r6 = 0; |
---|
145 | r8 = 0; |
---|
146 | #endif |
---|
147 | r5 = (uint32_t)dtpath_addr; |
---|
148 | r7 = (uint32_t)propname_addr; |
---|
149 | r9 = (uint32_t)propvalue_addr; |
---|
150 | r10 = *propvalue_len; |
---|
151 | |
---|
152 | asm volatile("bl epapr_hypercall_start" |
---|
153 | : "+r" (r11), |
---|
154 | "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), |
---|
155 | "+r" (r8), "+r" (r9), "+r" (r10) |
---|
156 | : : EV_HCALL_CLOBBERS8 |
---|
157 | ); |
---|
158 | |
---|
159 | *propvalue_len = r4; |
---|
160 | return r3; |
---|
161 | } |
---|
162 | |
---|
163 | /** |
---|
164 | * Set a property in a guest device tree. |
---|
165 | * @handle: handle of partition whose device tree is to be accessed |
---|
166 | * @dtpath_addr: physical address of device tree path to access |
---|
167 | * @propname_addr: physical address of name of property |
---|
168 | * @propvalue_addr: physical address of property value |
---|
169 | * @propvalue_len: length of property |
---|
170 | * |
---|
171 | * Returns zero on success, non-zero on error. |
---|
172 | */ |
---|
173 | static inline unsigned int fh_partition_set_dtprop(int handle, |
---|
174 | uint64_t dtpath_addr, |
---|
175 | uint64_t propname_addr, |
---|
176 | uint64_t propvalue_addr, |
---|
177 | uint32_t propvalue_len) |
---|
178 | { |
---|
179 | register uintptr_t r11 __asm__("r11"); |
---|
180 | register uintptr_t r3 __asm__("r3"); |
---|
181 | register uintptr_t r4 __asm__("r4"); |
---|
182 | register uintptr_t r6 __asm__("r6"); |
---|
183 | register uintptr_t r8 __asm__("r8"); |
---|
184 | register uintptr_t r5 __asm__("r5"); |
---|
185 | register uintptr_t r7 __asm__("r7"); |
---|
186 | register uintptr_t r9 __asm__("r9"); |
---|
187 | register uintptr_t r10 __asm__("r10"); |
---|
188 | |
---|
189 | r11 = FH_HCALL_TOKEN(FH_PARTITION_SET_DTPROP); |
---|
190 | r3 = handle; |
---|
191 | |
---|
192 | #ifdef CONFIG_PHYS_64BIT |
---|
193 | r4 = dtpath_addr >> 32; |
---|
194 | r6 = propname_addr >> 32; |
---|
195 | r8 = propvalue_addr >> 32; |
---|
196 | #else |
---|
197 | r4 = 0; |
---|
198 | r6 = 0; |
---|
199 | r8 = 0; |
---|
200 | #endif |
---|
201 | r5 = (uint32_t)dtpath_addr; |
---|
202 | r7 = (uint32_t)propname_addr; |
---|
203 | r9 = (uint32_t)propvalue_addr; |
---|
204 | r10 = propvalue_len; |
---|
205 | |
---|
206 | asm volatile("bl epapr_hypercall_start" |
---|
207 | : "+r" (r11), |
---|
208 | "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), |
---|
209 | "+r" (r8), "+r" (r9), "+r" (r10) |
---|
210 | : : EV_HCALL_CLOBBERS8 |
---|
211 | ); |
---|
212 | |
---|
213 | return r3; |
---|
214 | } |
---|
215 | |
---|
216 | /** |
---|
217 | * fh_partition_restart - reboot the current partition |
---|
218 | * @partition: partition ID |
---|
219 | * |
---|
220 | * Returns an error code if reboot failed. Does not return if it succeeds. |
---|
221 | */ |
---|
222 | static inline unsigned int fh_partition_restart(unsigned int partition) |
---|
223 | { |
---|
224 | register uintptr_t r11 __asm__("r11"); |
---|
225 | register uintptr_t r3 __asm__("r3"); |
---|
226 | |
---|
227 | r11 = FH_HCALL_TOKEN(FH_PARTITION_RESTART); |
---|
228 | r3 = partition; |
---|
229 | |
---|
230 | asm volatile("bl epapr_hypercall_start" |
---|
231 | : "+r" (r11), "+r" (r3) |
---|
232 | : : EV_HCALL_CLOBBERS1 |
---|
233 | ); |
---|
234 | |
---|
235 | return r3; |
---|
236 | } |
---|
237 | |
---|
238 | #define FH_PARTITION_STOPPED 0 |
---|
239 | #define FH_PARTITION_RUNNING 1 |
---|
240 | #define FH_PARTITION_STARTING 2 |
---|
241 | #define FH_PARTITION_STOPPING 3 |
---|
242 | #define FH_PARTITION_PAUSING 4 |
---|
243 | #define FH_PARTITION_PAUSED 5 |
---|
244 | #define FH_PARTITION_RESUMING 6 |
---|
245 | |
---|
246 | /** |
---|
247 | * fh_partition_get_status - gets the status of a partition |
---|
248 | * @partition: partition ID |
---|
249 | * @status: returned status code |
---|
250 | * |
---|
251 | * Returns 0 for success, or an error code. |
---|
252 | */ |
---|
253 | static inline unsigned int fh_partition_get_status(unsigned int partition, |
---|
254 | unsigned int *status) |
---|
255 | { |
---|
256 | register uintptr_t r11 __asm__("r11"); |
---|
257 | register uintptr_t r3 __asm__("r3"); |
---|
258 | register uintptr_t r4 __asm__("r4"); |
---|
259 | |
---|
260 | r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_STATUS); |
---|
261 | r3 = partition; |
---|
262 | |
---|
263 | asm volatile("bl epapr_hypercall_start" |
---|
264 | : "+r" (r11), "+r" (r3), "=r" (r4) |
---|
265 | : : EV_HCALL_CLOBBERS2 |
---|
266 | ); |
---|
267 | |
---|
268 | *status = r4; |
---|
269 | |
---|
270 | return r3; |
---|
271 | } |
---|
272 | |
---|
273 | /** |
---|
274 | * fh_partition_start - boots and starts execution of the specified partition |
---|
275 | * @partition: partition ID |
---|
276 | * @entry_point: guest physical address to start execution |
---|
277 | * |
---|
278 | * The hypervisor creates a 1-to-1 virtual/physical IMA mapping, so at boot |
---|
279 | * time, guest physical address are the same as guest virtual addresses. |
---|
280 | * |
---|
281 | * Returns 0 for success, or an error code. |
---|
282 | */ |
---|
283 | static inline unsigned int fh_partition_start(unsigned int partition, |
---|
284 | uint32_t entry_point, int load) |
---|
285 | { |
---|
286 | register uintptr_t r11 __asm__("r11"); |
---|
287 | register uintptr_t r3 __asm__("r3"); |
---|
288 | register uintptr_t r4 __asm__("r4"); |
---|
289 | register uintptr_t r5 __asm__("r5"); |
---|
290 | |
---|
291 | r11 = FH_HCALL_TOKEN(FH_PARTITION_START); |
---|
292 | r3 = partition; |
---|
293 | r4 = entry_point; |
---|
294 | r5 = load; |
---|
295 | |
---|
296 | asm volatile("bl epapr_hypercall_start" |
---|
297 | : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5) |
---|
298 | : : EV_HCALL_CLOBBERS3 |
---|
299 | ); |
---|
300 | |
---|
301 | return r3; |
---|
302 | } |
---|
303 | |
---|
304 | /** |
---|
305 | * fh_partition_stop - stops another partition |
---|
306 | * @partition: partition ID |
---|
307 | * |
---|
308 | * Returns 0 for success, or an error code. |
---|
309 | */ |
---|
310 | static inline unsigned int fh_partition_stop(unsigned int partition) |
---|
311 | { |
---|
312 | register uintptr_t r11 __asm__("r11"); |
---|
313 | register uintptr_t r3 __asm__("r3"); |
---|
314 | |
---|
315 | r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP); |
---|
316 | r3 = partition; |
---|
317 | |
---|
318 | asm volatile("bl epapr_hypercall_start" |
---|
319 | : "+r" (r11), "+r" (r3) |
---|
320 | : : EV_HCALL_CLOBBERS1 |
---|
321 | ); |
---|
322 | |
---|
323 | return r3; |
---|
324 | } |
---|
325 | |
---|
326 | /** |
---|
327 | * struct fh_sg_list: definition of the fh_partition_memcpy S/G list |
---|
328 | * @source: guest physical address to copy from |
---|
329 | * @target: guest physical address to copy to |
---|
330 | * @size: number of bytes to copy |
---|
331 | * @reserved: reserved, must be zero |
---|
332 | * |
---|
333 | * The scatter/gather list for fh_partition_memcpy() is an array of these |
---|
334 | * structures. The array must be guest physically contiguous. |
---|
335 | * |
---|
336 | * This structure must be aligned on 32-byte boundary, so that no single |
---|
337 | * strucuture can span two pages. |
---|
338 | */ |
---|
339 | struct fh_sg_list { |
---|
340 | uint64_t source; /**< guest physical address to copy from */ |
---|
341 | uint64_t target; /**< guest physical address to copy to */ |
---|
342 | uint64_t size; /**< number of bytes to copy */ |
---|
343 | uint64_t reserved; /**< reserved, must be zero */ |
---|
344 | } __attribute__ ((aligned(32))); |
---|
345 | |
---|
346 | /** |
---|
347 | * fh_partition_memcpy - copies data from one guest to another |
---|
348 | * @source: the ID of the partition to copy from |
---|
349 | * @target: the ID of the partition to copy to |
---|
350 | * @sg_list: guest physical address of an array of &fh_sg_list structures |
---|
351 | * @count: the number of entries in @sg_list |
---|
352 | * |
---|
353 | * Returns 0 for success, or an error code. |
---|
354 | */ |
---|
355 | static inline unsigned int fh_partition_memcpy(unsigned int source, |
---|
356 | unsigned int target, uint64_t sg_list, unsigned int count) |
---|
357 | { |
---|
358 | register uintptr_t r11 __asm__("r11"); |
---|
359 | register uintptr_t r3 __asm__("r3"); |
---|
360 | register uintptr_t r4 __asm__("r4"); |
---|
361 | register uintptr_t r5 __asm__("r5"); |
---|
362 | register uintptr_t r6 __asm__("r6"); |
---|
363 | register uintptr_t r7 __asm__("r7"); |
---|
364 | |
---|
365 | r11 = FH_HCALL_TOKEN(FH_PARTITION_MEMCPY); |
---|
366 | r3 = source; |
---|
367 | r4 = target; |
---|
368 | r5 = (uint32_t) sg_list; |
---|
369 | |
---|
370 | #ifdef CONFIG_PHYS_64BIT |
---|
371 | r6 = sg_list >> 32; |
---|
372 | #else |
---|
373 | r6 = 0; |
---|
374 | #endif |
---|
375 | r7 = count; |
---|
376 | |
---|
377 | asm volatile("bl epapr_hypercall_start" |
---|
378 | : "+r" (r11), |
---|
379 | "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7) |
---|
380 | : : EV_HCALL_CLOBBERS5 |
---|
381 | ); |
---|
382 | |
---|
383 | return r3; |
---|
384 | } |
---|
385 | |
---|
386 | /** |
---|
387 | * fh_dma_enable - enable DMA for the specified device |
---|
388 | * @liodn: the LIODN of the I/O device for which to enable DMA |
---|
389 | * |
---|
390 | * Returns 0 for success, or an error code. |
---|
391 | */ |
---|
392 | static inline unsigned int fh_dma_enable(unsigned int liodn) |
---|
393 | { |
---|
394 | register uintptr_t r11 __asm__("r11"); |
---|
395 | register uintptr_t r3 __asm__("r3"); |
---|
396 | |
---|
397 | r11 = FH_HCALL_TOKEN(FH_DMA_ENABLE); |
---|
398 | r3 = liodn; |
---|
399 | |
---|
400 | asm volatile("bl epapr_hypercall_start" |
---|
401 | : "+r" (r11), "+r" (r3) |
---|
402 | : : EV_HCALL_CLOBBERS1 |
---|
403 | ); |
---|
404 | |
---|
405 | return r3; |
---|
406 | } |
---|
407 | |
---|
408 | /** |
---|
409 | * fh_dma_disable - disable DMA for the specified device |
---|
410 | * @liodn: the LIODN of the I/O device for which to disable DMA |
---|
411 | * |
---|
412 | * Returns 0 for success, or an error code. |
---|
413 | */ |
---|
414 | static inline unsigned int fh_dma_disable(unsigned int liodn) |
---|
415 | { |
---|
416 | register uintptr_t r11 __asm__("r11"); |
---|
417 | register uintptr_t r3 __asm__("r3"); |
---|
418 | |
---|
419 | r11 = FH_HCALL_TOKEN(FH_DMA_DISABLE); |
---|
420 | r3 = liodn; |
---|
421 | |
---|
422 | asm volatile("bl epapr_hypercall_start" |
---|
423 | : "+r" (r11), "+r" (r3) |
---|
424 | : : EV_HCALL_CLOBBERS1 |
---|
425 | ); |
---|
426 | |
---|
427 | return r3; |
---|
428 | } |
---|
429 | |
---|
430 | |
---|
431 | /** |
---|
432 | * fh_vmpic_get_msir - returns the MPIC-MSI register value |
---|
433 | * @interrupt: the interrupt number |
---|
434 | * @msir_val: returned MPIC-MSI register value |
---|
435 | * |
---|
436 | * Returns 0 for success, or an error code. |
---|
437 | */ |
---|
438 | static inline unsigned int fh_vmpic_get_msir(unsigned int interrupt, |
---|
439 | unsigned int *msir_val) |
---|
440 | { |
---|
441 | register uintptr_t r11 __asm__("r11"); |
---|
442 | register uintptr_t r3 __asm__("r3"); |
---|
443 | register uintptr_t r4 __asm__("r4"); |
---|
444 | |
---|
445 | r11 = FH_HCALL_TOKEN(FH_VMPIC_GET_MSIR); |
---|
446 | r3 = interrupt; |
---|
447 | |
---|
448 | asm volatile("bl epapr_hypercall_start" |
---|
449 | : "+r" (r11), "+r" (r3), "=r" (r4) |
---|
450 | : : EV_HCALL_CLOBBERS2 |
---|
451 | ); |
---|
452 | |
---|
453 | *msir_val = r4; |
---|
454 | |
---|
455 | return r3; |
---|
456 | } |
---|
457 | |
---|
458 | /** |
---|
459 | * fh_system_reset - reset the system |
---|
460 | * |
---|
461 | * Returns 0 for success, or an error code. |
---|
462 | */ |
---|
463 | static inline unsigned int fh_system_reset(void) |
---|
464 | { |
---|
465 | register uintptr_t r11 __asm__("r11"); |
---|
466 | register uintptr_t r3 __asm__("r3"); |
---|
467 | |
---|
468 | r11 = FH_HCALL_TOKEN(FH_SYSTEM_RESET); |
---|
469 | |
---|
470 | asm volatile("bl epapr_hypercall_start" |
---|
471 | : "+r" (r11), "=r" (r3) |
---|
472 | : : EV_HCALL_CLOBBERS1 |
---|
473 | ); |
---|
474 | |
---|
475 | return r3; |
---|
476 | } |
---|
477 | |
---|
478 | |
---|
479 | /** |
---|
480 | * fh_err_get_info - get platform error information |
---|
481 | * @queue id: |
---|
482 | * 0 for guest error event queue |
---|
483 | * 1 for global error event queue |
---|
484 | * |
---|
485 | * @pointer to store the platform error data: |
---|
486 | * platform error data is returned in registers r4 - r11 |
---|
487 | * |
---|
488 | * Returns 0 for success, or an error code. |
---|
489 | */ |
---|
490 | static inline unsigned int fh_err_get_info(int queue, uint32_t *bufsize, |
---|
491 | uint32_t addr_hi, uint32_t addr_lo, int peek) |
---|
492 | { |
---|
493 | register uintptr_t r11 __asm__("r11"); |
---|
494 | register uintptr_t r3 __asm__("r3"); |
---|
495 | register uintptr_t r4 __asm__("r4"); |
---|
496 | register uintptr_t r5 __asm__("r5"); |
---|
497 | register uintptr_t r6 __asm__("r6"); |
---|
498 | register uintptr_t r7 __asm__("r7"); |
---|
499 | |
---|
500 | r11 = FH_HCALL_TOKEN(FH_ERR_GET_INFO); |
---|
501 | r3 = queue; |
---|
502 | r4 = *bufsize; |
---|
503 | r5 = addr_hi; |
---|
504 | r6 = addr_lo; |
---|
505 | r7 = peek; |
---|
506 | |
---|
507 | asm volatile("bl epapr_hypercall_start" |
---|
508 | : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), |
---|
509 | "+r" (r7) |
---|
510 | : : EV_HCALL_CLOBBERS5 |
---|
511 | ); |
---|
512 | |
---|
513 | *bufsize = r4; |
---|
514 | |
---|
515 | return r3; |
---|
516 | } |
---|
517 | |
---|
518 | |
---|
519 | #define FH_VCPU_RUN 0 |
---|
520 | #define FH_VCPU_IDLE 1 |
---|
521 | #define FH_VCPU_NAP 2 |
---|
522 | |
---|
523 | /** |
---|
524 | * fh_get_core_state - get the state of a vcpu |
---|
525 | * |
---|
526 | * @handle: handle of partition containing the vcpu |
---|
527 | * @vcpu: vcpu number within the partition |
---|
528 | * @state:the current state of the vcpu, see FH_VCPU_* |
---|
529 | * |
---|
530 | * Returns 0 for success, or an error code. |
---|
531 | */ |
---|
532 | static inline unsigned int fh_get_core_state(unsigned int handle, |
---|
533 | unsigned int vcpu, unsigned int *state) |
---|
534 | { |
---|
535 | register uintptr_t r11 __asm__("r11"); |
---|
536 | register uintptr_t r3 __asm__("r3"); |
---|
537 | register uintptr_t r4 __asm__("r4"); |
---|
538 | |
---|
539 | r11 = FH_HCALL_TOKEN(FH_GET_CORE_STATE); |
---|
540 | r3 = handle; |
---|
541 | r4 = vcpu; |
---|
542 | |
---|
543 | asm volatile("bl epapr_hypercall_start" |
---|
544 | : "+r" (r11), "+r" (r3), "+r" (r4) |
---|
545 | : : EV_HCALL_CLOBBERS2 |
---|
546 | ); |
---|
547 | |
---|
548 | *state = r4; |
---|
549 | return r3; |
---|
550 | } |
---|
551 | |
---|
552 | /** |
---|
553 | * fh_enter_nap - enter nap on a vcpu |
---|
554 | * |
---|
555 | * Note that though the API supports entering nap on a vcpu other |
---|
556 | * than the caller, this may not be implmented and may return EINVAL. |
---|
557 | * |
---|
558 | * @handle: handle of partition containing the vcpu |
---|
559 | * @vcpu: vcpu number within the partition |
---|
560 | * |
---|
561 | * Returns 0 for success, or an error code. |
---|
562 | */ |
---|
563 | static inline unsigned int fh_enter_nap(unsigned int handle, unsigned int vcpu) |
---|
564 | { |
---|
565 | register uintptr_t r11 __asm__("r11"); |
---|
566 | register uintptr_t r3 __asm__("r3"); |
---|
567 | register uintptr_t r4 __asm__("r4"); |
---|
568 | |
---|
569 | r11 = FH_HCALL_TOKEN(FH_ENTER_NAP); |
---|
570 | r3 = handle; |
---|
571 | r4 = vcpu; |
---|
572 | |
---|
573 | asm volatile("bl epapr_hypercall_start" |
---|
574 | : "+r" (r11), "+r" (r3), "+r" (r4) |
---|
575 | : : EV_HCALL_CLOBBERS2 |
---|
576 | ); |
---|
577 | |
---|
578 | return r3; |
---|
579 | } |
---|
580 | |
---|
581 | /** |
---|
582 | * fh_exit_nap - exit nap on a vcpu |
---|
583 | * @handle: handle of partition containing the vcpu |
---|
584 | * @vcpu: vcpu number within the partition |
---|
585 | * |
---|
586 | * Returns 0 for success, or an error code. |
---|
587 | */ |
---|
588 | static inline unsigned int fh_exit_nap(unsigned int handle, unsigned int vcpu) |
---|
589 | { |
---|
590 | register uintptr_t r11 __asm__("r11"); |
---|
591 | register uintptr_t r3 __asm__("r3"); |
---|
592 | register uintptr_t r4 __asm__("r4"); |
---|
593 | |
---|
594 | r11 = FH_HCALL_TOKEN(FH_EXIT_NAP); |
---|
595 | r3 = handle; |
---|
596 | r4 = vcpu; |
---|
597 | |
---|
598 | asm volatile("bl epapr_hypercall_start" |
---|
599 | : "+r" (r11), "+r" (r3), "+r" (r4) |
---|
600 | : : EV_HCALL_CLOBBERS2 |
---|
601 | ); |
---|
602 | |
---|
603 | return r3; |
---|
604 | } |
---|
605 | /** |
---|
606 | * fh_claim_device - claim a "claimable" shared device |
---|
607 | * @handle: fsl,hv-device-handle of node to claim |
---|
608 | * |
---|
609 | * Returns 0 for success, or an error code. |
---|
610 | */ |
---|
611 | static inline unsigned int fh_claim_device(unsigned int handle) |
---|
612 | { |
---|
613 | register uintptr_t r11 __asm__("r11"); |
---|
614 | register uintptr_t r3 __asm__("r3"); |
---|
615 | |
---|
616 | r11 = FH_HCALL_TOKEN(FH_CLAIM_DEVICE); |
---|
617 | r3 = handle; |
---|
618 | |
---|
619 | asm volatile("bl epapr_hypercall_start" |
---|
620 | : "+r" (r11), "+r" (r3) |
---|
621 | : : EV_HCALL_CLOBBERS1 |
---|
622 | ); |
---|
623 | |
---|
624 | return r3; |
---|
625 | } |
---|
626 | |
---|
627 | /** |
---|
628 | * Run deferred DMA disabling on a partition's private devices |
---|
629 | * |
---|
630 | * This applies to devices which a partition owns either privately, |
---|
631 | * or which are claimable and still actively owned by that partition, |
---|
632 | * and which do not have the no-dma-disable property. |
---|
633 | * |
---|
634 | * @handle: partition (must be stopped) whose DMA is to be disabled |
---|
635 | * |
---|
636 | * Returns 0 for success, or an error code. |
---|
637 | */ |
---|
638 | static inline unsigned int fh_partition_stop_dma(unsigned int handle) |
---|
639 | { |
---|
640 | register uintptr_t r11 __asm__("r11"); |
---|
641 | register uintptr_t r3 __asm__("r3"); |
---|
642 | |
---|
643 | r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP_DMA); |
---|
644 | r3 = handle; |
---|
645 | |
---|
646 | asm volatile("bl epapr_hypercall_start" |
---|
647 | : "+r" (r11), "+r" (r3) |
---|
648 | : : EV_HCALL_CLOBBERS1 |
---|
649 | ); |
---|
650 | |
---|
651 | return r3; |
---|
652 | } |
---|
653 | #endif |
---|