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