Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[pandora-kernel.git] / arch / powerpc / include / asm / fsl_hcalls.h
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
99         __asm__ __volatile__ ("sc 1"
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 /**
112  * fh_partiton_get_dtprop - get a property from a guest device tree.
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
154         __asm__ __volatile__ ("sc 1"
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
208         __asm__ __volatile__ ("sc 1"
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
232         __asm__ __volatile__ ("sc 1"
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
265         __asm__ __volatile__ ("sc 1"
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
298         __asm__ __volatile__ ("sc 1"
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
320         __asm__ __volatile__ ("sc 1"
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
379         __asm__ __volatile__ ("sc 1"
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
402         __asm__ __volatile__ ("sc 1"
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
424         __asm__ __volatile__ ("sc 1"
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
450         __asm__ __volatile__ ("sc 1"
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
472         __asm__ __volatile__ ("sc 1"
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
509         __asm__ __volatile__ ("sc 1"
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
545         __asm__ __volatile__ ("sc 1"
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
575         __asm__ __volatile__ ("sc 1"
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
600         __asm__ __volatile__ ("sc 1"
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
621         __asm__ __volatile__ ("sc 1"
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
648         __asm__ __volatile__ ("sc 1"
649                 : "+r" (r11), "+r" (r3)
650                 : : EV_HCALL_CLOBBERS1
651         );
652
653         return r3;
654 }
655 #endif