Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Freescale hypervisor call interface
0003  *
0004  * Copyright 2008-2010 Freescale Semiconductor, Inc.
0005  *
0006  * Author: Timur Tabi <timur@freescale.com>
0007  *
0008  * This file is provided under a dual BSD/GPL license.  When using or
0009  * redistributing this file, you may do so under either license.
0010  *
0011  * Redistribution and use in source and binary forms, with or without
0012  * modification, are permitted provided that the following conditions are met:
0013  *     * Redistributions of source code must retain the above copyright
0014  *       notice, this list of conditions and the following disclaimer.
0015  *     * Redistributions in binary form must reproduce the above copyright
0016  *       notice, this list of conditions and the following disclaimer in the
0017  *       documentation and/or other materials provided with the distribution.
0018  *     * Neither the name of Freescale Semiconductor nor the
0019  *       names of its contributors may be used to endorse or promote products
0020  *       derived from this software without specific prior written permission.
0021  *
0022  *
0023  * ALTERNATIVELY, this software may be distributed under the terms of the
0024  * GNU General Public License ("GPL") as published by the Free Software
0025  * Foundation, either version 2 of that License or (at your option) any
0026  * later version.
0027  *
0028  * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
0029  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0030  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0031  * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
0032  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0033  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0034  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0035  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0036  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0037  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0038  */
0039 
0040 #ifndef _FSL_HCALLS_H
0041 #define _FSL_HCALLS_H
0042 
0043 #include <linux/types.h>
0044 #include <linux/errno.h>
0045 #include <asm/byteorder.h>
0046 #include <asm/epapr_hcalls.h>
0047 
0048 #define FH_API_VERSION          1
0049 
0050 #define FH_ERR_GET_INFO         1
0051 #define FH_PARTITION_GET_DTPROP     2
0052 #define FH_PARTITION_SET_DTPROP     3
0053 #define FH_PARTITION_RESTART        4
0054 #define FH_PARTITION_GET_STATUS     5
0055 #define FH_PARTITION_START      6
0056 #define FH_PARTITION_STOP       7
0057 #define FH_PARTITION_MEMCPY     8
0058 #define FH_DMA_ENABLE           9
0059 #define FH_DMA_DISABLE          10
0060 #define FH_SEND_NMI         11
0061 #define FH_VMPIC_GET_MSIR       12
0062 #define FH_SYSTEM_RESET         13
0063 #define FH_GET_CORE_STATE       14
0064 #define FH_ENTER_NAP            15
0065 #define FH_EXIT_NAP         16
0066 #define FH_CLAIM_DEVICE         17
0067 #define FH_PARTITION_STOP_DMA       18
0068 
0069 /* vendor ID: Freescale Semiconductor */
0070 #define FH_HCALL_TOKEN(num)     _EV_HCALL_TOKEN(EV_FSL_VENDOR_ID, num)
0071 
0072 /*
0073  * We use "uintptr_t" to define a register because it's guaranteed to be a
0074  * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit
0075  * platform.
0076  *
0077  * All registers are either input/output or output only.  Registers that are
0078  * initialized before making the hypercall are input/output.  All
0079  * input/output registers are represented with "+r".  Output-only registers
0080  * are represented with "=r".  Do not specify any unused registers.  The
0081  * clobber list will tell the compiler that the hypercall modifies those
0082  * registers, which is good enough.
0083  */
0084 
0085 /**
0086  * fh_send_nmi - send NMI to virtual cpu(s).
0087  * @vcpu_mask: send NMI to virtual cpu(s) specified by this mask.
0088  *
0089  * Returns 0 for success, or EINVAL for invalid vcpu_mask.
0090  */
0091 static inline unsigned int fh_send_nmi(unsigned int vcpu_mask)
0092 {
0093     register uintptr_t r11 __asm__("r11");
0094     register uintptr_t r3 __asm__("r3");
0095 
0096     r11 = FH_HCALL_TOKEN(FH_SEND_NMI);
0097     r3 = vcpu_mask;
0098 
0099     asm volatile("bl    epapr_hypercall_start"
0100         : "+r" (r11), "+r" (r3)
0101         : : EV_HCALL_CLOBBERS1
0102     );
0103 
0104     return r3;
0105 }
0106 
0107 /* Arbitrary limits to avoid excessive memory allocation in hypervisor */
0108 #define FH_DTPROP_MAX_PATHLEN 4096
0109 #define FH_DTPROP_MAX_PROPLEN 32768
0110 
0111 /**
0112  * fh_partition_get_dtprop - get a property from a guest device tree.
0113  * @handle: handle of partition whose device tree is to be accessed
0114  * @dtpath_addr: physical address of device tree path to access
0115  * @propname_addr: physical address of name of property
0116  * @propvalue_addr: physical address of property value buffer
0117  * @propvalue_len: length of buffer on entry, length of property on return
0118  *
0119  * Returns zero on success, non-zero on error.
0120  */
0121 static inline unsigned int fh_partition_get_dtprop(int handle,
0122                            uint64_t dtpath_addr,
0123                            uint64_t propname_addr,
0124                            uint64_t propvalue_addr,
0125                            uint32_t *propvalue_len)
0126 {
0127     register uintptr_t r11 __asm__("r11");
0128     register uintptr_t r3 __asm__("r3");
0129     register uintptr_t r4 __asm__("r4");
0130     register uintptr_t r5 __asm__("r5");
0131     register uintptr_t r6 __asm__("r6");
0132     register uintptr_t r7 __asm__("r7");
0133     register uintptr_t r8 __asm__("r8");
0134     register uintptr_t r9 __asm__("r9");
0135     register uintptr_t r10 __asm__("r10");
0136 
0137     r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_DTPROP);
0138     r3 = handle;
0139 
0140 #ifdef CONFIG_PHYS_64BIT
0141     r4 = dtpath_addr >> 32;
0142     r6 = propname_addr >> 32;
0143     r8 = propvalue_addr >> 32;
0144 #else
0145     r4 = 0;
0146     r6 = 0;
0147     r8 = 0;
0148 #endif
0149     r5 = (uint32_t)dtpath_addr;
0150     r7 = (uint32_t)propname_addr;
0151     r9 = (uint32_t)propvalue_addr;
0152     r10 = *propvalue_len;
0153 
0154     asm volatile("bl    epapr_hypercall_start"
0155         : "+r" (r11),
0156           "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
0157           "+r" (r8), "+r" (r9), "+r" (r10)
0158         : : EV_HCALL_CLOBBERS8
0159     );
0160 
0161     *propvalue_len = r4;
0162     return r3;
0163 }
0164 
0165 /**
0166  * Set a property in a guest device tree.
0167  * @handle: handle of partition whose device tree is to be accessed
0168  * @dtpath_addr: physical address of device tree path to access
0169  * @propname_addr: physical address of name of property
0170  * @propvalue_addr: physical address of property value
0171  * @propvalue_len: length of property
0172  *
0173  * Returns zero on success, non-zero on error.
0174  */
0175 static inline unsigned int fh_partition_set_dtprop(int handle,
0176                            uint64_t dtpath_addr,
0177                            uint64_t propname_addr,
0178                            uint64_t propvalue_addr,
0179                            uint32_t propvalue_len)
0180 {
0181     register uintptr_t r11 __asm__("r11");
0182     register uintptr_t r3 __asm__("r3");
0183     register uintptr_t r4 __asm__("r4");
0184     register uintptr_t r6 __asm__("r6");
0185     register uintptr_t r8 __asm__("r8");
0186     register uintptr_t r5 __asm__("r5");
0187     register uintptr_t r7 __asm__("r7");
0188     register uintptr_t r9 __asm__("r9");
0189     register uintptr_t r10 __asm__("r10");
0190 
0191     r11 = FH_HCALL_TOKEN(FH_PARTITION_SET_DTPROP);
0192     r3 = handle;
0193 
0194 #ifdef CONFIG_PHYS_64BIT
0195     r4 = dtpath_addr >> 32;
0196     r6 = propname_addr >> 32;
0197     r8 = propvalue_addr >> 32;
0198 #else
0199     r4 = 0;
0200     r6 = 0;
0201     r8 = 0;
0202 #endif
0203     r5 = (uint32_t)dtpath_addr;
0204     r7 = (uint32_t)propname_addr;
0205     r9 = (uint32_t)propvalue_addr;
0206     r10 = propvalue_len;
0207 
0208     asm volatile("bl    epapr_hypercall_start"
0209         : "+r" (r11),
0210           "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
0211           "+r" (r8), "+r" (r9), "+r" (r10)
0212         : : EV_HCALL_CLOBBERS8
0213     );
0214 
0215     return r3;
0216 }
0217 
0218 /**
0219  * fh_partition_restart - reboot the current partition
0220  * @partition: partition ID
0221  *
0222  * Returns an error code if reboot failed.  Does not return if it succeeds.
0223  */
0224 static inline unsigned int fh_partition_restart(unsigned int partition)
0225 {
0226     register uintptr_t r11 __asm__("r11");
0227     register uintptr_t r3 __asm__("r3");
0228 
0229     r11 = FH_HCALL_TOKEN(FH_PARTITION_RESTART);
0230     r3 = partition;
0231 
0232     asm volatile("bl    epapr_hypercall_start"
0233         : "+r" (r11), "+r" (r3)
0234         : : EV_HCALL_CLOBBERS1
0235     );
0236 
0237     return r3;
0238 }
0239 
0240 #define FH_PARTITION_STOPPED    0
0241 #define FH_PARTITION_RUNNING    1
0242 #define FH_PARTITION_STARTING   2
0243 #define FH_PARTITION_STOPPING   3
0244 #define FH_PARTITION_PAUSING    4
0245 #define FH_PARTITION_PAUSED 5
0246 #define FH_PARTITION_RESUMING   6
0247 
0248 /**
0249  * fh_partition_get_status - gets the status of a partition
0250  * @partition: partition ID
0251  * @status: returned status code
0252  *
0253  * Returns 0 for success, or an error code.
0254  */
0255 static inline unsigned int fh_partition_get_status(unsigned int partition,
0256     unsigned int *status)
0257 {
0258     register uintptr_t r11 __asm__("r11");
0259     register uintptr_t r3 __asm__("r3");
0260     register uintptr_t r4 __asm__("r4");
0261 
0262     r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_STATUS);
0263     r3 = partition;
0264 
0265     asm volatile("bl    epapr_hypercall_start"
0266         : "+r" (r11), "+r" (r3), "=r" (r4)
0267         : : EV_HCALL_CLOBBERS2
0268     );
0269 
0270     *status = r4;
0271 
0272     return r3;
0273 }
0274 
0275 /**
0276  * fh_partition_start - boots and starts execution of the specified partition
0277  * @partition: partition ID
0278  * @entry_point: guest physical address to start execution
0279  *
0280  * The hypervisor creates a 1-to-1 virtual/physical IMA mapping, so at boot
0281  * time, guest physical address are the same as guest virtual addresses.
0282  *
0283  * Returns 0 for success, or an error code.
0284  */
0285 static inline unsigned int fh_partition_start(unsigned int partition,
0286     uint32_t entry_point, int load)
0287 {
0288     register uintptr_t r11 __asm__("r11");
0289     register uintptr_t r3 __asm__("r3");
0290     register uintptr_t r4 __asm__("r4");
0291     register uintptr_t r5 __asm__("r5");
0292 
0293     r11 = FH_HCALL_TOKEN(FH_PARTITION_START);
0294     r3 = partition;
0295     r4 = entry_point;
0296     r5 = load;
0297 
0298     asm volatile("bl    epapr_hypercall_start"
0299         : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5)
0300         : : EV_HCALL_CLOBBERS3
0301     );
0302 
0303     return r3;
0304 }
0305 
0306 /**
0307  * fh_partition_stop - stops another partition
0308  * @partition: partition ID
0309  *
0310  * Returns 0 for success, or an error code.
0311  */
0312 static inline unsigned int fh_partition_stop(unsigned int partition)
0313 {
0314     register uintptr_t r11 __asm__("r11");
0315     register uintptr_t r3 __asm__("r3");
0316 
0317     r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP);
0318     r3 = partition;
0319 
0320     asm volatile("bl    epapr_hypercall_start"
0321         : "+r" (r11), "+r" (r3)
0322         : : EV_HCALL_CLOBBERS1
0323     );
0324 
0325     return r3;
0326 }
0327 
0328 /**
0329  * struct fh_sg_list: definition of the fh_partition_memcpy S/G list
0330  * @source: guest physical address to copy from
0331  * @target: guest physical address to copy to
0332  * @size: number of bytes to copy
0333  * @reserved: reserved, must be zero
0334  *
0335  * The scatter/gather list for fh_partition_memcpy() is an array of these
0336  * structures.  The array must be guest physically contiguous.
0337  *
0338  * This structure must be aligned on 32-byte boundary, so that no single
0339  * strucuture can span two pages.
0340  */
0341 struct fh_sg_list {
0342     uint64_t source;   /**< guest physical address to copy from */
0343     uint64_t target;   /**< guest physical address to copy to */
0344     uint64_t size;     /**< number of bytes to copy */
0345     uint64_t reserved; /**< reserved, must be zero */
0346 } __attribute__ ((aligned(32)));
0347 
0348 /**
0349  * fh_partition_memcpy - copies data from one guest to another
0350  * @source: the ID of the partition to copy from
0351  * @target: the ID of the partition to copy to
0352  * @sg_list: guest physical address of an array of &fh_sg_list structures
0353  * @count: the number of entries in @sg_list
0354  *
0355  * Returns 0 for success, or an error code.
0356  */
0357 static inline unsigned int fh_partition_memcpy(unsigned int source,
0358     unsigned int target, phys_addr_t sg_list, unsigned int count)
0359 {
0360     register uintptr_t r11 __asm__("r11");
0361     register uintptr_t r3 __asm__("r3");
0362     register uintptr_t r4 __asm__("r4");
0363     register uintptr_t r5 __asm__("r5");
0364     register uintptr_t r6 __asm__("r6");
0365     register uintptr_t r7 __asm__("r7");
0366 
0367     r11 = FH_HCALL_TOKEN(FH_PARTITION_MEMCPY);
0368     r3 = source;
0369     r4 = target;
0370     r5 = (uint32_t) sg_list;
0371 
0372 #ifdef CONFIG_PHYS_64BIT
0373     r6 = sg_list >> 32;
0374 #else
0375     r6 = 0;
0376 #endif
0377     r7 = count;
0378 
0379     asm volatile("bl    epapr_hypercall_start"
0380         : "+r" (r11),
0381           "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7)
0382         : : EV_HCALL_CLOBBERS5
0383     );
0384 
0385     return r3;
0386 }
0387 
0388 /**
0389  * fh_dma_enable - enable DMA for the specified device
0390  * @liodn: the LIODN of the I/O device for which to enable DMA
0391  *
0392  * Returns 0 for success, or an error code.
0393  */
0394 static inline unsigned int fh_dma_enable(unsigned int liodn)
0395 {
0396     register uintptr_t r11 __asm__("r11");
0397     register uintptr_t r3 __asm__("r3");
0398 
0399     r11 = FH_HCALL_TOKEN(FH_DMA_ENABLE);
0400     r3 = liodn;
0401 
0402     asm volatile("bl    epapr_hypercall_start"
0403         : "+r" (r11), "+r" (r3)
0404         : : EV_HCALL_CLOBBERS1
0405     );
0406 
0407     return r3;
0408 }
0409 
0410 /**
0411  * fh_dma_disable - disable DMA for the specified device
0412  * @liodn: the LIODN of the I/O device for which to disable DMA
0413  *
0414  * Returns 0 for success, or an error code.
0415  */
0416 static inline unsigned int fh_dma_disable(unsigned int liodn)
0417 {
0418     register uintptr_t r11 __asm__("r11");
0419     register uintptr_t r3 __asm__("r3");
0420 
0421     r11 = FH_HCALL_TOKEN(FH_DMA_DISABLE);
0422     r3 = liodn;
0423 
0424     asm volatile("bl    epapr_hypercall_start"
0425         : "+r" (r11), "+r" (r3)
0426         : : EV_HCALL_CLOBBERS1
0427     );
0428 
0429     return r3;
0430 }
0431 
0432 
0433 /**
0434  * fh_vmpic_get_msir - returns the MPIC-MSI register value
0435  * @interrupt: the interrupt number
0436  * @msir_val: returned MPIC-MSI register value
0437  *
0438  * Returns 0 for success, or an error code.
0439  */
0440 static inline unsigned int fh_vmpic_get_msir(unsigned int interrupt,
0441     unsigned int *msir_val)
0442 {
0443     register uintptr_t r11 __asm__("r11");
0444     register uintptr_t r3 __asm__("r3");
0445     register uintptr_t r4 __asm__("r4");
0446 
0447     r11 = FH_HCALL_TOKEN(FH_VMPIC_GET_MSIR);
0448     r3 = interrupt;
0449 
0450     asm volatile("bl    epapr_hypercall_start"
0451         : "+r" (r11), "+r" (r3), "=r" (r4)
0452         : : EV_HCALL_CLOBBERS2
0453     );
0454 
0455     *msir_val = r4;
0456 
0457     return r3;
0458 }
0459 
0460 /**
0461  * fh_system_reset - reset the system
0462  *
0463  * Returns 0 for success, or an error code.
0464  */
0465 static inline unsigned int fh_system_reset(void)
0466 {
0467     register uintptr_t r11 __asm__("r11");
0468     register uintptr_t r3 __asm__("r3");
0469 
0470     r11 = FH_HCALL_TOKEN(FH_SYSTEM_RESET);
0471 
0472     asm volatile("bl    epapr_hypercall_start"
0473         : "+r" (r11), "=r" (r3)
0474         : : EV_HCALL_CLOBBERS1
0475     );
0476 
0477     return r3;
0478 }
0479 
0480 
0481 /**
0482  * fh_err_get_info - get platform error information
0483  * @queue id:
0484  * 0 for guest error event queue
0485  * 1 for global error event queue
0486  *
0487  * @pointer to store the platform error data:
0488  * platform error data is returned in registers r4 - r11
0489  *
0490  * Returns 0 for success, or an error code.
0491  */
0492 static inline unsigned int fh_err_get_info(int queue, uint32_t *bufsize,
0493     uint32_t addr_hi, uint32_t addr_lo, int peek)
0494 {
0495     register uintptr_t r11 __asm__("r11");
0496     register uintptr_t r3 __asm__("r3");
0497     register uintptr_t r4 __asm__("r4");
0498     register uintptr_t r5 __asm__("r5");
0499     register uintptr_t r6 __asm__("r6");
0500     register uintptr_t r7 __asm__("r7");
0501 
0502     r11 = FH_HCALL_TOKEN(FH_ERR_GET_INFO);
0503     r3 = queue;
0504     r4 = *bufsize;
0505     r5 = addr_hi;
0506     r6 = addr_lo;
0507     r7 = peek;
0508 
0509     asm volatile("bl    epapr_hypercall_start"
0510         : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6),
0511           "+r" (r7)
0512         : : EV_HCALL_CLOBBERS5
0513     );
0514 
0515     *bufsize = r4;
0516 
0517     return r3;
0518 }
0519 
0520 
0521 #define FH_VCPU_RUN 0
0522 #define FH_VCPU_IDLE    1
0523 #define FH_VCPU_NAP 2
0524 
0525 /**
0526  * fh_get_core_state - get the state of a vcpu
0527  *
0528  * @handle: handle of partition containing the vcpu
0529  * @vcpu: vcpu number within the partition
0530  * @state:the current state of the vcpu, see FH_VCPU_*
0531  *
0532  * Returns 0 for success, or an error code.
0533  */
0534 static inline unsigned int fh_get_core_state(unsigned int handle,
0535     unsigned int vcpu, unsigned int *state)
0536 {
0537     register uintptr_t r11 __asm__("r11");
0538     register uintptr_t r3 __asm__("r3");
0539     register uintptr_t r4 __asm__("r4");
0540 
0541     r11 = FH_HCALL_TOKEN(FH_GET_CORE_STATE);
0542     r3 = handle;
0543     r4 = vcpu;
0544 
0545     asm volatile("bl    epapr_hypercall_start"
0546         : "+r" (r11), "+r" (r3), "+r" (r4)
0547         : : EV_HCALL_CLOBBERS2
0548     );
0549 
0550     *state = r4;
0551     return r3;
0552 }
0553 
0554 /**
0555  * fh_enter_nap - enter nap on a vcpu
0556  *
0557  * Note that though the API supports entering nap on a vcpu other
0558  * than the caller, this may not be implmented and may return EINVAL.
0559  *
0560  * @handle: handle of partition containing the vcpu
0561  * @vcpu: vcpu number within the partition
0562  *
0563  * Returns 0 for success, or an error code.
0564  */
0565 static inline unsigned int fh_enter_nap(unsigned int handle, unsigned int vcpu)
0566 {
0567     register uintptr_t r11 __asm__("r11");
0568     register uintptr_t r3 __asm__("r3");
0569     register uintptr_t r4 __asm__("r4");
0570 
0571     r11 = FH_HCALL_TOKEN(FH_ENTER_NAP);
0572     r3 = handle;
0573     r4 = vcpu;
0574 
0575     asm volatile("bl    epapr_hypercall_start"
0576         : "+r" (r11), "+r" (r3), "+r" (r4)
0577         : : EV_HCALL_CLOBBERS2
0578     );
0579 
0580     return r3;
0581 }
0582 
0583 /**
0584  * fh_exit_nap - exit nap on a vcpu
0585  * @handle: handle of partition containing the vcpu
0586  * @vcpu: vcpu number within the partition
0587  *
0588  * Returns 0 for success, or an error code.
0589  */
0590 static inline unsigned int fh_exit_nap(unsigned int handle, unsigned int vcpu)
0591 {
0592     register uintptr_t r11 __asm__("r11");
0593     register uintptr_t r3 __asm__("r3");
0594     register uintptr_t r4 __asm__("r4");
0595 
0596     r11 = FH_HCALL_TOKEN(FH_EXIT_NAP);
0597     r3 = handle;
0598     r4 = vcpu;
0599 
0600     asm volatile("bl    epapr_hypercall_start"
0601         : "+r" (r11), "+r" (r3), "+r" (r4)
0602         : : EV_HCALL_CLOBBERS2
0603     );
0604 
0605     return r3;
0606 }
0607 /**
0608  * fh_claim_device - claim a "claimable" shared device
0609  * @handle: fsl,hv-device-handle of node to claim
0610  *
0611  * Returns 0 for success, or an error code.
0612  */
0613 static inline unsigned int fh_claim_device(unsigned int handle)
0614 {
0615     register uintptr_t r11 __asm__("r11");
0616     register uintptr_t r3 __asm__("r3");
0617 
0618     r11 = FH_HCALL_TOKEN(FH_CLAIM_DEVICE);
0619     r3 = handle;
0620 
0621     asm volatile("bl    epapr_hypercall_start"
0622         : "+r" (r11), "+r" (r3)
0623         : : EV_HCALL_CLOBBERS1
0624     );
0625 
0626     return r3;
0627 }
0628 
0629 /**
0630  * Run deferred DMA disabling on a partition's private devices
0631  *
0632  * This applies to devices which a partition owns either privately,
0633  * or which are claimable and still actively owned by that partition,
0634  * and which do not have the no-dma-disable property.
0635  *
0636  * @handle: partition (must be stopped) whose DMA is to be disabled
0637  *
0638  * Returns 0 for success, or an error code.
0639  */
0640 static inline unsigned int fh_partition_stop_dma(unsigned int handle)
0641 {
0642     register uintptr_t r11 __asm__("r11");
0643     register uintptr_t r3 __asm__("r3");
0644 
0645     r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP_DMA);
0646     r3 = handle;
0647 
0648     asm volatile("bl    epapr_hypercall_start"
0649         : "+r" (r11), "+r" (r3)
0650         : : EV_HCALL_CLOBBERS1
0651     );
0652 
0653     return r3;
0654 }
0655 #endif