cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fsl_hcalls.h (17615B)


      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 */
     91static 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("bl	epapr_hypercall_start"
    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_partition_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 */
    121static 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("bl	epapr_hypercall_start"
    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 */
    175static 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("bl	epapr_hypercall_start"
    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 */
    224static 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("bl	epapr_hypercall_start"
    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 */
    255static 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("bl	epapr_hypercall_start"
    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 */
    285static 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("bl	epapr_hypercall_start"
    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 */
    312static 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("bl	epapr_hypercall_start"
    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 */
    341struct 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 */
    357static 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("bl	epapr_hypercall_start"
    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 */
    394static 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("bl	epapr_hypercall_start"
    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 */
    416static 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("bl	epapr_hypercall_start"
    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 */
    440static 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("bl	epapr_hypercall_start"
    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 */
    465static 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("bl	epapr_hypercall_start"
    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 */
    492static 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("bl	epapr_hypercall_start"
    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 */
    534static 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("bl	epapr_hypercall_start"
    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 */
    565static 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("bl	epapr_hypercall_start"
    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 */
    590static 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("bl	epapr_hypercall_start"
    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 */
    613static 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("bl	epapr_hypercall_start"
    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 */
    640static 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("bl	epapr_hypercall_start"
    649		: "+r" (r11), "+r" (r3)
    650		: : EV_HCALL_CLOBBERS1
    651	);
    652
    653	return r3;
    654}
    655#endif