162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * ePAPR hcall interface 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 2008-2011 Freescale Semiconductor, Inc. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Author: Timur Tabi <timur@freescale.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This file is provided under a dual BSD/GPL license. When using or 962306a36Sopenharmony_ci * redistributing this file, you may do so under either license. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 1262306a36Sopenharmony_ci * modification, are permitted provided that the following conditions are met: 1362306a36Sopenharmony_ci * * Redistributions of source code must retain the above copyright 1462306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 1562306a36Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 1662306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 1762306a36Sopenharmony_ci * documentation and/or other materials provided with the distribution. 1862306a36Sopenharmony_ci * * Neither the name of Freescale Semiconductor nor the 1962306a36Sopenharmony_ci * names of its contributors may be used to endorse or promote products 2062306a36Sopenharmony_ci * derived from this software without specific prior written permission. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the 2462306a36Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software 2562306a36Sopenharmony_ci * Foundation, either version 2 of that License or (at your option) any 2662306a36Sopenharmony_ci * later version. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 2962306a36Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3062306a36Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 3162306a36Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 3262306a36Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3362306a36Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 3462306a36Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 3562306a36Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3662306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3762306a36Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* A "hypercall" is an "sc 1" instruction. This header file provides C 4162306a36Sopenharmony_ci * wrapper functions for the ePAPR hypervisor interface. It is inteded 4262306a36Sopenharmony_ci * for use by Linux device drivers and other operating systems. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * The hypercalls are implemented as inline assembly, rather than assembly 4562306a36Sopenharmony_ci * language functions in a .S file, for optimization. It allows 4662306a36Sopenharmony_ci * the caller to issue the hypercall instruction directly, improving both 4762306a36Sopenharmony_ci * performance and memory footprint. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#ifndef _EPAPR_HCALLS_H 5162306a36Sopenharmony_ci#define _EPAPR_HCALLS_H 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#include <uapi/asm/epapr_hcalls.h> 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 5662306a36Sopenharmony_ci#include <linux/types.h> 5762306a36Sopenharmony_ci#include <linux/errno.h> 5862306a36Sopenharmony_ci#include <asm/byteorder.h> 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * Hypercall register clobber list 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * These macros are used to define the list of clobbered registers during a 6462306a36Sopenharmony_ci * hypercall. Technically, registers r0 and r3-r12 are always clobbered, 6562306a36Sopenharmony_ci * but the gcc inline assembly syntax does not allow us to specify registers 6662306a36Sopenharmony_ci * on the clobber list that are also on the input/output list. Therefore, 6762306a36Sopenharmony_ci * the lists of clobbered registers depends on the number of register 6862306a36Sopenharmony_ci * parameters ("+r" and "=r") passed to the hypercall. 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * Each assembly block should use one of the HCALL_CLOBBERSx macros. As a 7162306a36Sopenharmony_ci * general rule, 'x' is the number of parameters passed to the assembly 7262306a36Sopenharmony_ci * block *except* for r11. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * If you're not sure, just use the smallest value of 'x' that does not 7562306a36Sopenharmony_ci * generate a compilation error. Because these are static inline functions, 7662306a36Sopenharmony_ci * the compiler will only check the clobber list for a function if you 7762306a36Sopenharmony_ci * compile code that calls that function. 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * r3 and r11 are not included in any clobbers list because they are always 8062306a36Sopenharmony_ci * listed as output registers. 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * XER, CTR, and LR are currently listed as clobbers because it's uncertain 8362306a36Sopenharmony_ci * whether they will be clobbered. 8462306a36Sopenharmony_ci * 8562306a36Sopenharmony_ci * Note that r11 can be used as an output parameter. 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * The "memory" clobber is only necessary for hcalls where the Hypervisor 8862306a36Sopenharmony_ci * will read or write guest memory. However, we add it to all hcalls because 8962306a36Sopenharmony_ci * the impact is minimal, and we want to ensure that it's present for the 9062306a36Sopenharmony_ci * hcalls that need it. 9162306a36Sopenharmony_ci*/ 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* List of common clobbered registers. Do not use this macro. */ 9462306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc", "memory" 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS 9762306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10" 9862306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS6 EV_HCALL_CLOBBERS7, "r9" 9962306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS5 EV_HCALL_CLOBBERS6, "r8" 10062306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS4 EV_HCALL_CLOBBERS5, "r7" 10162306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS3 EV_HCALL_CLOBBERS4, "r6" 10262306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5" 10362306a36Sopenharmony_ci#define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4" 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciextern bool epapr_paravirt_enabled; 10662306a36Sopenharmony_ciextern u32 epapr_hypercall_start[]; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci#ifdef CONFIG_EPAPR_PARAVIRT 10962306a36Sopenharmony_ciint __init epapr_paravirt_early_init(void); 11062306a36Sopenharmony_ci#else 11162306a36Sopenharmony_cistatic inline int epapr_paravirt_early_init(void) { return 0; } 11262306a36Sopenharmony_ci#endif 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* 11562306a36Sopenharmony_ci * We use "uintptr_t" to define a register because it's guaranteed to be a 11662306a36Sopenharmony_ci * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit 11762306a36Sopenharmony_ci * platform. 11862306a36Sopenharmony_ci * 11962306a36Sopenharmony_ci * All registers are either input/output or output only. Registers that are 12062306a36Sopenharmony_ci * initialized before making the hypercall are input/output. All 12162306a36Sopenharmony_ci * input/output registers are represented with "+r". Output-only registers 12262306a36Sopenharmony_ci * are represented with "=r". Do not specify any unused registers. The 12362306a36Sopenharmony_ci * clobber list will tell the compiler that the hypercall modifies those 12462306a36Sopenharmony_ci * registers, which is good enough. 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/** 12862306a36Sopenharmony_ci * ev_int_set_config - configure the specified interrupt 12962306a36Sopenharmony_ci * @interrupt: the interrupt number 13062306a36Sopenharmony_ci * @config: configuration for this interrupt 13162306a36Sopenharmony_ci * @priority: interrupt priority 13262306a36Sopenharmony_ci * @destination: destination CPU number 13362306a36Sopenharmony_ci * 13462306a36Sopenharmony_ci * Returns 0 for success, or an error code. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_cistatic inline unsigned int ev_int_set_config(unsigned int interrupt, 13762306a36Sopenharmony_ci uint32_t config, unsigned int priority, uint32_t destination) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 14062306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 14162306a36Sopenharmony_ci register uintptr_t r4 __asm__("r4"); 14262306a36Sopenharmony_ci register uintptr_t r5 __asm__("r5"); 14362306a36Sopenharmony_ci register uintptr_t r6 __asm__("r6"); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG); 14662306a36Sopenharmony_ci r3 = interrupt; 14762306a36Sopenharmony_ci r4 = config; 14862306a36Sopenharmony_ci r5 = priority; 14962306a36Sopenharmony_ci r6 = destination; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 15262306a36Sopenharmony_ci : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6) 15362306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS4 15462306a36Sopenharmony_ci ); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return r3; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/** 16062306a36Sopenharmony_ci * ev_int_get_config - return the config of the specified interrupt 16162306a36Sopenharmony_ci * @interrupt: the interrupt number 16262306a36Sopenharmony_ci * @config: returned configuration for this interrupt 16362306a36Sopenharmony_ci * @priority: returned interrupt priority 16462306a36Sopenharmony_ci * @destination: returned destination CPU number 16562306a36Sopenharmony_ci * 16662306a36Sopenharmony_ci * Returns 0 for success, or an error code. 16762306a36Sopenharmony_ci */ 16862306a36Sopenharmony_cistatic inline unsigned int ev_int_get_config(unsigned int interrupt, 16962306a36Sopenharmony_ci uint32_t *config, unsigned int *priority, uint32_t *destination) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 17262306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 17362306a36Sopenharmony_ci register uintptr_t r4 __asm__("r4"); 17462306a36Sopenharmony_ci register uintptr_t r5 __asm__("r5"); 17562306a36Sopenharmony_ci register uintptr_t r6 __asm__("r6"); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG); 17862306a36Sopenharmony_ci r3 = interrupt; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 18162306a36Sopenharmony_ci : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6) 18262306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS4 18362306a36Sopenharmony_ci ); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci *config = r4; 18662306a36Sopenharmony_ci *priority = r5; 18762306a36Sopenharmony_ci *destination = r6; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return r3; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci/** 19362306a36Sopenharmony_ci * ev_int_set_mask - sets the mask for the specified interrupt source 19462306a36Sopenharmony_ci * @interrupt: the interrupt number 19562306a36Sopenharmony_ci * @mask: 0=enable interrupts, 1=disable interrupts 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * Returns 0 for success, or an error code. 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_cistatic inline unsigned int ev_int_set_mask(unsigned int interrupt, 20062306a36Sopenharmony_ci unsigned int mask) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 20362306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 20462306a36Sopenharmony_ci register uintptr_t r4 __asm__("r4"); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK); 20762306a36Sopenharmony_ci r3 = interrupt; 20862306a36Sopenharmony_ci r4 = mask; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 21162306a36Sopenharmony_ci : "+r" (r11), "+r" (r3), "+r" (r4) 21262306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS2 21362306a36Sopenharmony_ci ); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci return r3; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/** 21962306a36Sopenharmony_ci * ev_int_get_mask - returns the mask for the specified interrupt source 22062306a36Sopenharmony_ci * @interrupt: the interrupt number 22162306a36Sopenharmony_ci * @mask: returned mask for this interrupt (0=enabled, 1=disabled) 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * Returns 0 for success, or an error code. 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_cistatic inline unsigned int ev_int_get_mask(unsigned int interrupt, 22662306a36Sopenharmony_ci unsigned int *mask) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 22962306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 23062306a36Sopenharmony_ci register uintptr_t r4 __asm__("r4"); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK); 23362306a36Sopenharmony_ci r3 = interrupt; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 23662306a36Sopenharmony_ci : "+r" (r11), "+r" (r3), "=r" (r4) 23762306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS2 23862306a36Sopenharmony_ci ); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci *mask = r4; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci return r3; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci/** 24662306a36Sopenharmony_ci * ev_int_eoi - signal the end of interrupt processing 24762306a36Sopenharmony_ci * @interrupt: the interrupt number 24862306a36Sopenharmony_ci * 24962306a36Sopenharmony_ci * This function signals the end of processing for the specified 25062306a36Sopenharmony_ci * interrupt, which must be the interrupt currently in service. By 25162306a36Sopenharmony_ci * definition, this is also the highest-priority interrupt. 25262306a36Sopenharmony_ci * 25362306a36Sopenharmony_ci * Returns 0 for success, or an error code. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_cistatic inline unsigned int ev_int_eoi(unsigned int interrupt) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 25862306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_INT_EOI); 26162306a36Sopenharmony_ci r3 = interrupt; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 26462306a36Sopenharmony_ci : "+r" (r11), "+r" (r3) 26562306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS1 26662306a36Sopenharmony_ci ); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci return r3; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/** 27262306a36Sopenharmony_ci * ev_byte_channel_send - send characters to a byte stream 27362306a36Sopenharmony_ci * @handle: byte stream handle 27462306a36Sopenharmony_ci * @count: (input) num of chars to send, (output) num chars sent 27562306a36Sopenharmony_ci * @buffer: pointer to a 16-byte buffer 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * @buffer must be at least 16 bytes long, because all 16 bytes will be 27862306a36Sopenharmony_ci * read from memory into registers, even if count < 16. 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * Returns 0 for success, or an error code. 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_cistatic inline unsigned int ev_byte_channel_send(unsigned int handle, 28362306a36Sopenharmony_ci unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES]) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 28662306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 28762306a36Sopenharmony_ci register uintptr_t r4 __asm__("r4"); 28862306a36Sopenharmony_ci register uintptr_t r5 __asm__("r5"); 28962306a36Sopenharmony_ci register uintptr_t r6 __asm__("r6"); 29062306a36Sopenharmony_ci register uintptr_t r7 __asm__("r7"); 29162306a36Sopenharmony_ci register uintptr_t r8 __asm__("r8"); 29262306a36Sopenharmony_ci const uint32_t *p = (const uint32_t *) buffer; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND); 29562306a36Sopenharmony_ci r3 = handle; 29662306a36Sopenharmony_ci r4 = *count; 29762306a36Sopenharmony_ci r5 = be32_to_cpu(p[0]); 29862306a36Sopenharmony_ci r6 = be32_to_cpu(p[1]); 29962306a36Sopenharmony_ci r7 = be32_to_cpu(p[2]); 30062306a36Sopenharmony_ci r8 = be32_to_cpu(p[3]); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 30362306a36Sopenharmony_ci : "+r" (r11), "+r" (r3), 30462306a36Sopenharmony_ci "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8) 30562306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS6 30662306a36Sopenharmony_ci ); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci *count = r4; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci return r3; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci/** 31462306a36Sopenharmony_ci * ev_byte_channel_receive - fetch characters from a byte channel 31562306a36Sopenharmony_ci * @handle: byte channel handle 31662306a36Sopenharmony_ci * @count: (input) max num of chars to receive, (output) num chars received 31762306a36Sopenharmony_ci * @buffer: pointer to a 16-byte buffer 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * The size of @buffer must be at least 16 bytes, even if you request fewer 32062306a36Sopenharmony_ci * than 16 characters, because we always write 16 bytes to @buffer. This is 32162306a36Sopenharmony_ci * for performance reasons. 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * Returns 0 for success, or an error code. 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_cistatic inline unsigned int ev_byte_channel_receive(unsigned int handle, 32662306a36Sopenharmony_ci unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES]) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 32962306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 33062306a36Sopenharmony_ci register uintptr_t r4 __asm__("r4"); 33162306a36Sopenharmony_ci register uintptr_t r5 __asm__("r5"); 33262306a36Sopenharmony_ci register uintptr_t r6 __asm__("r6"); 33362306a36Sopenharmony_ci register uintptr_t r7 __asm__("r7"); 33462306a36Sopenharmony_ci register uintptr_t r8 __asm__("r8"); 33562306a36Sopenharmony_ci uint32_t *p = (uint32_t *) buffer; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE); 33862306a36Sopenharmony_ci r3 = handle; 33962306a36Sopenharmony_ci r4 = *count; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 34262306a36Sopenharmony_ci : "+r" (r11), "+r" (r3), "+r" (r4), 34362306a36Sopenharmony_ci "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8) 34462306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS6 34562306a36Sopenharmony_ci ); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci *count = r4; 34862306a36Sopenharmony_ci p[0] = cpu_to_be32(r5); 34962306a36Sopenharmony_ci p[1] = cpu_to_be32(r6); 35062306a36Sopenharmony_ci p[2] = cpu_to_be32(r7); 35162306a36Sopenharmony_ci p[3] = cpu_to_be32(r8); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci return r3; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci/** 35762306a36Sopenharmony_ci * ev_byte_channel_poll - returns the status of the byte channel buffers 35862306a36Sopenharmony_ci * @handle: byte channel handle 35962306a36Sopenharmony_ci * @rx_count: returned count of bytes in receive queue 36062306a36Sopenharmony_ci * @tx_count: returned count of free space in transmit queue 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci * This function reports the amount of data in the receive queue (i.e. the 36362306a36Sopenharmony_ci * number of bytes you can read), and the amount of free space in the transmit 36462306a36Sopenharmony_ci * queue (i.e. the number of bytes you can write). 36562306a36Sopenharmony_ci * 36662306a36Sopenharmony_ci * Returns 0 for success, or an error code. 36762306a36Sopenharmony_ci */ 36862306a36Sopenharmony_cistatic inline unsigned int ev_byte_channel_poll(unsigned int handle, 36962306a36Sopenharmony_ci unsigned int *rx_count, unsigned int *tx_count) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 37262306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 37362306a36Sopenharmony_ci register uintptr_t r4 __asm__("r4"); 37462306a36Sopenharmony_ci register uintptr_t r5 __asm__("r5"); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL); 37762306a36Sopenharmony_ci r3 = handle; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 38062306a36Sopenharmony_ci : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5) 38162306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS3 38262306a36Sopenharmony_ci ); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci *rx_count = r4; 38562306a36Sopenharmony_ci *tx_count = r5; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci return r3; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci/** 39162306a36Sopenharmony_ci * ev_int_iack - acknowledge an interrupt 39262306a36Sopenharmony_ci * @handle: handle to the target interrupt controller 39362306a36Sopenharmony_ci * @vector: returned interrupt vector 39462306a36Sopenharmony_ci * 39562306a36Sopenharmony_ci * If handle is zero, the function returns the next interrupt source 39662306a36Sopenharmony_ci * number to be handled irrespective of the hierarchy or cascading 39762306a36Sopenharmony_ci * of interrupt controllers. If non-zero, specifies a handle to the 39862306a36Sopenharmony_ci * interrupt controller that is the target of the acknowledge. 39962306a36Sopenharmony_ci * 40062306a36Sopenharmony_ci * Returns 0 for success, or an error code. 40162306a36Sopenharmony_ci */ 40262306a36Sopenharmony_cistatic inline unsigned int ev_int_iack(unsigned int handle, 40362306a36Sopenharmony_ci unsigned int *vector) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 40662306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 40762306a36Sopenharmony_ci register uintptr_t r4 __asm__("r4"); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_INT_IACK); 41062306a36Sopenharmony_ci r3 = handle; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 41362306a36Sopenharmony_ci : "+r" (r11), "+r" (r3), "=r" (r4) 41462306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS2 41562306a36Sopenharmony_ci ); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci *vector = r4; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci return r3; 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci/** 42362306a36Sopenharmony_ci * ev_doorbell_send - send a doorbell to another partition 42462306a36Sopenharmony_ci * @handle: doorbell send handle 42562306a36Sopenharmony_ci * 42662306a36Sopenharmony_ci * Returns 0 for success, or an error code. 42762306a36Sopenharmony_ci */ 42862306a36Sopenharmony_cistatic inline unsigned int ev_doorbell_send(unsigned int handle) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 43162306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND); 43462306a36Sopenharmony_ci r3 = handle; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 43762306a36Sopenharmony_ci : "+r" (r11), "+r" (r3) 43862306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS1 43962306a36Sopenharmony_ci ); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci return r3; 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci/** 44562306a36Sopenharmony_ci * ev_idle -- wait for next interrupt on this core 44662306a36Sopenharmony_ci * 44762306a36Sopenharmony_ci * Returns 0 for success, or an error code. 44862306a36Sopenharmony_ci */ 44962306a36Sopenharmony_cistatic inline unsigned int ev_idle(void) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci register uintptr_t r11 __asm__("r11"); 45262306a36Sopenharmony_ci register uintptr_t r3 __asm__("r3"); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci r11 = EV_HCALL_TOKEN(EV_IDLE); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 45762306a36Sopenharmony_ci : "+r" (r11), "=r" (r3) 45862306a36Sopenharmony_ci : : EV_HCALL_CLOBBERS1 45962306a36Sopenharmony_ci ); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci return r3; 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci#ifdef CONFIG_EPAPR_PARAVIRT 46562306a36Sopenharmony_cistatic inline unsigned long epapr_hypercall(unsigned long *in, 46662306a36Sopenharmony_ci unsigned long *out, 46762306a36Sopenharmony_ci unsigned long nr) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci register unsigned long r0 asm("r0"); 47062306a36Sopenharmony_ci register unsigned long r3 asm("r3") = in[0]; 47162306a36Sopenharmony_ci register unsigned long r4 asm("r4") = in[1]; 47262306a36Sopenharmony_ci register unsigned long r5 asm("r5") = in[2]; 47362306a36Sopenharmony_ci register unsigned long r6 asm("r6") = in[3]; 47462306a36Sopenharmony_ci register unsigned long r7 asm("r7") = in[4]; 47562306a36Sopenharmony_ci register unsigned long r8 asm("r8") = in[5]; 47662306a36Sopenharmony_ci register unsigned long r9 asm("r9") = in[6]; 47762306a36Sopenharmony_ci register unsigned long r10 asm("r10") = in[7]; 47862306a36Sopenharmony_ci register unsigned long r11 asm("r11") = nr; 47962306a36Sopenharmony_ci register unsigned long r12 asm("r12"); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci asm volatile("bl epapr_hypercall_start" 48262306a36Sopenharmony_ci : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6), 48362306a36Sopenharmony_ci "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11), 48462306a36Sopenharmony_ci "=r"(r12) 48562306a36Sopenharmony_ci : "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "r"(r8), 48662306a36Sopenharmony_ci "r"(r9), "r"(r10), "r"(r11) 48762306a36Sopenharmony_ci : "memory", "cc", "xer", "ctr", "lr"); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci out[0] = r4; 49062306a36Sopenharmony_ci out[1] = r5; 49162306a36Sopenharmony_ci out[2] = r6; 49262306a36Sopenharmony_ci out[3] = r7; 49362306a36Sopenharmony_ci out[4] = r8; 49462306a36Sopenharmony_ci out[5] = r9; 49562306a36Sopenharmony_ci out[6] = r10; 49662306a36Sopenharmony_ci out[7] = r11; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci return r3; 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci#else 50162306a36Sopenharmony_cistatic unsigned long epapr_hypercall(unsigned long *in, 50262306a36Sopenharmony_ci unsigned long *out, 50362306a36Sopenharmony_ci unsigned long nr) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci return EV_UNIMPLEMENTED; 50662306a36Sopenharmony_ci} 50762306a36Sopenharmony_ci#endif 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_cistatic inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2) 51062306a36Sopenharmony_ci{ 51162306a36Sopenharmony_ci unsigned long in[8] = {0}; 51262306a36Sopenharmony_ci unsigned long out[8]; 51362306a36Sopenharmony_ci unsigned long r; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci r = epapr_hypercall(in, out, nr); 51662306a36Sopenharmony_ci *r2 = out[0]; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci return r; 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_cistatic inline long epapr_hypercall0(unsigned int nr) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci unsigned long in[8] = {0}; 52462306a36Sopenharmony_ci unsigned long out[8]; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci return epapr_hypercall(in, out, nr); 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic inline long epapr_hypercall1(unsigned int nr, unsigned long p1) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci unsigned long in[8] = {0}; 53262306a36Sopenharmony_ci unsigned long out[8]; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci in[0] = p1; 53562306a36Sopenharmony_ci return epapr_hypercall(in, out, nr); 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic inline long epapr_hypercall2(unsigned int nr, unsigned long p1, 53962306a36Sopenharmony_ci unsigned long p2) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci unsigned long in[8] = {0}; 54262306a36Sopenharmony_ci unsigned long out[8]; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci in[0] = p1; 54562306a36Sopenharmony_ci in[1] = p2; 54662306a36Sopenharmony_ci return epapr_hypercall(in, out, nr); 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cistatic inline long epapr_hypercall3(unsigned int nr, unsigned long p1, 55062306a36Sopenharmony_ci unsigned long p2, unsigned long p3) 55162306a36Sopenharmony_ci{ 55262306a36Sopenharmony_ci unsigned long in[8] = {0}; 55362306a36Sopenharmony_ci unsigned long out[8]; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci in[0] = p1; 55662306a36Sopenharmony_ci in[1] = p2; 55762306a36Sopenharmony_ci in[2] = p3; 55862306a36Sopenharmony_ci return epapr_hypercall(in, out, nr); 55962306a36Sopenharmony_ci} 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_cistatic inline long epapr_hypercall4(unsigned int nr, unsigned long p1, 56262306a36Sopenharmony_ci unsigned long p2, unsigned long p3, 56362306a36Sopenharmony_ci unsigned long p4) 56462306a36Sopenharmony_ci{ 56562306a36Sopenharmony_ci unsigned long in[8] = {0}; 56662306a36Sopenharmony_ci unsigned long out[8]; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci in[0] = p1; 56962306a36Sopenharmony_ci in[1] = p2; 57062306a36Sopenharmony_ci in[2] = p3; 57162306a36Sopenharmony_ci in[3] = p4; 57262306a36Sopenharmony_ci return epapr_hypercall(in, out, nr); 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 57562306a36Sopenharmony_ci#endif /* _EPAPR_HCALLS_H */ 576