Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:57

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