Back to home page

LXR

 
 

    


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

0001 /*
0002  * ePAPR hcall interface
0003  *
0004  * Copyright 2008-2011 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 /* A "hypercall" is an "sc 1" instruction.  This header file file provides C
0041  * wrapper functions for the ePAPR hypervisor interface.  It is inteded
0042  * for use by Linux device drivers and other operating systems.
0043  *
0044  * The hypercalls are implemented as inline assembly, rather than assembly
0045  * language functions in a .S file, for optimization.  It allows
0046  * the caller to issue the hypercall instruction directly, improving both
0047  * performance and memory footprint.
0048  */
0049 
0050 #ifndef _EPAPR_HCALLS_H
0051 #define _EPAPR_HCALLS_H
0052 
0053 #include <uapi/asm/epapr_hcalls.h>
0054 
0055 #ifndef __ASSEMBLY__
0056 #include <sys/endian.h>
0057 
0058 /*
0059  * Hypercall register clobber list
0060  *
0061  * These macros are used to define the list of clobbered registers during a
0062  * hypercall.  Technically, registers r0 and r3-r12 are always clobbered,
0063  * but the gcc inline assembly syntax does not allow us to specify registers
0064  * on the clobber list that are also on the input/output list.  Therefore,
0065  * the lists of clobbered registers depends on the number of register
0066  * parmeters ("+r" and "=r") passed to the hypercall.
0067  *
0068  * Each assembly block should use one of the HCALL_CLOBBERSx macros.  As a
0069  * general rule, 'x' is the number of parameters passed to the assembly
0070  * block *except* for r11.
0071  *
0072  * If you're not sure, just use the smallest value of 'x' that does not
0073  * generate a compilation error.  Because these are static inline functions,
0074  * the compiler will only check the clobber list for a function if you
0075  * compile code that calls that function.
0076  *
0077  * r3 and r11 are not included in any clobbers list because they are always
0078  * listed as output registers.
0079  *
0080  * XER, CTR, and LR are currently listed as clobbers because it's uncertain
0081  * whether they will be clobbered.
0082  *
0083  * Note that r11 can be used as an output parameter.
0084  *
0085  * The "memory" clobber is only necessary for hcalls where the Hypervisor
0086  * will read or write guest memory. However, we add it to all hcalls because
0087  * the impact is minimal, and we want to ensure that it's present for the
0088  * hcalls that need it.
0089 */
0090 
0091 /* List of common clobbered registers.  Do not use this macro. */
0092 #define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc", "memory"
0093 
0094 #define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS
0095 #define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10"
0096 #define EV_HCALL_CLOBBERS6 EV_HCALL_CLOBBERS7, "r9"
0097 #define EV_HCALL_CLOBBERS5 EV_HCALL_CLOBBERS6, "r8"
0098 #define EV_HCALL_CLOBBERS4 EV_HCALL_CLOBBERS5, "r7"
0099 #define EV_HCALL_CLOBBERS3 EV_HCALL_CLOBBERS4, "r6"
0100 #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
0101 #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
0102 
0103 extern bool epapr_paravirt_enabled;
0104 extern uint32_t epapr_hypercall_start[];
0105 
0106 #ifdef CONFIG_EPAPR_PARAVIRT
0107 int __init epapr_paravirt_early_init(void);
0108 #else
0109 static inline int epapr_paravirt_early_init(void) { return 0; }
0110 #endif
0111 
0112 /*
0113  * We use "uintptr_t" to define a register because it's guaranteed to be a
0114  * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit
0115  * platform.
0116  *
0117  * All registers are either input/output or output only.  Registers that are
0118  * initialized before making the hypercall are input/output.  All
0119  * input/output registers are represented with "+r".  Output-only registers
0120  * are represented with "=r".  Do not specify any unused registers.  The
0121  * clobber list will tell the compiler that the hypercall modifies those
0122  * registers, which is good enough.
0123  */
0124 
0125 /**
0126  * ev_int_set_config - configure the specified interrupt
0127  * @interrupt: the interrupt number
0128  * @config: configuration for this interrupt
0129  * @priority: interrupt priority
0130  * @destination: destination CPU number
0131  *
0132  * Returns 0 for success, or an error code.
0133  */
0134 static inline unsigned int ev_int_set_config(unsigned int interrupt,
0135     uint32_t config, unsigned int priority, uint32_t destination)
0136 {
0137     register uintptr_t r11 __asm__("r11");
0138     register uintptr_t r3 __asm__("r3");
0139     register uintptr_t r4 __asm__("r4");
0140     register uintptr_t r5 __asm__("r5");
0141     register uintptr_t r6 __asm__("r6");
0142 
0143     r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG);
0144     r3  = interrupt;
0145     r4  = config;
0146     r5  = priority;
0147     r6  = destination;
0148 
0149     asm volatile("bl    epapr_hypercall_start"
0150         : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
0151         : : EV_HCALL_CLOBBERS4
0152     );
0153 
0154     return r3;
0155 }
0156 
0157 /**
0158  * ev_int_get_config - return the config of the specified interrupt
0159  * @interrupt: the interrupt number
0160  * @config: returned configuration for this interrupt
0161  * @priority: returned interrupt priority
0162  * @destination: returned destination CPU number
0163  *
0164  * Returns 0 for success, or an error code.
0165  */
0166 static inline unsigned int ev_int_get_config(unsigned int interrupt,
0167     uint32_t *config, unsigned int *priority, uint32_t *destination)
0168 {
0169     register uintptr_t r11 __asm__("r11");
0170     register uintptr_t r3 __asm__("r3");
0171     register uintptr_t r4 __asm__("r4");
0172     register uintptr_t r5 __asm__("r5");
0173     register uintptr_t r6 __asm__("r6");
0174 
0175     r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
0176     r3 = interrupt;
0177 
0178     asm volatile("bl    epapr_hypercall_start"
0179         : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
0180         : : EV_HCALL_CLOBBERS4
0181     );
0182 
0183     *config = r4;
0184     *priority = r5;
0185     *destination = r6;
0186 
0187     return r3;
0188 }
0189 
0190 /**
0191  * ev_int_set_mask - sets the mask for the specified interrupt source
0192  * @interrupt: the interrupt number
0193  * @mask: 0=enable interrupts, 1=disable interrupts
0194  *
0195  * Returns 0 for success, or an error code.
0196  */
0197 static inline unsigned int ev_int_set_mask(unsigned int interrupt,
0198     unsigned int mask)
0199 {
0200     register uintptr_t r11 __asm__("r11");
0201     register uintptr_t r3 __asm__("r3");
0202     register uintptr_t r4 __asm__("r4");
0203 
0204     r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK);
0205     r3 = interrupt;
0206     r4 = mask;
0207 
0208     asm volatile("bl    epapr_hypercall_start"
0209         : "+r" (r11), "+r" (r3), "+r" (r4)
0210         : : EV_HCALL_CLOBBERS2
0211     );
0212 
0213     return r3;
0214 }
0215 
0216 /**
0217  * ev_int_get_mask - returns the mask for the specified interrupt source
0218  * @interrupt: the interrupt number
0219  * @mask: returned mask for this interrupt (0=enabled, 1=disabled)
0220  *
0221  * Returns 0 for success, or an error code.
0222  */
0223 static inline unsigned int ev_int_get_mask(unsigned int interrupt,
0224     unsigned int *mask)
0225 {
0226     register uintptr_t r11 __asm__("r11");
0227     register uintptr_t r3 __asm__("r3");
0228     register uintptr_t r4 __asm__("r4");
0229 
0230     r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
0231     r3 = interrupt;
0232 
0233     asm volatile("bl    epapr_hypercall_start"
0234         : "+r" (r11), "+r" (r3), "=r" (r4)
0235         : : EV_HCALL_CLOBBERS2
0236     );
0237 
0238     *mask = r4;
0239 
0240     return r3;
0241 }
0242 
0243 /**
0244  * ev_int_eoi - signal the end of interrupt processing
0245  * @interrupt: the interrupt number
0246  *
0247  * This function signals the end of processing for the the specified
0248  * interrupt, which must be the interrupt currently in service. By
0249  * definition, this is also the highest-priority interrupt.
0250  *
0251  * Returns 0 for success, or an error code.
0252  */
0253 static inline unsigned int ev_int_eoi(unsigned int interrupt)
0254 {
0255     register uintptr_t r11 __asm__("r11");
0256     register uintptr_t r3 __asm__("r3");
0257 
0258     r11 = EV_HCALL_TOKEN(EV_INT_EOI);
0259     r3 = interrupt;
0260 
0261     asm volatile("bl    epapr_hypercall_start"
0262         : "+r" (r11), "+r" (r3)
0263         : : EV_HCALL_CLOBBERS1
0264     );
0265 
0266     return r3;
0267 }
0268 
0269 /**
0270  * ev_byte_channel_send - send characters to a byte stream
0271  * @handle: byte stream handle
0272  * @count: (input) num of chars to send, (output) num chars sent
0273  * @buffer: pointer to a 16-byte buffer
0274  *
0275  * @buffer must be at least 16 bytes long, because all 16 bytes will be
0276  * read from memory into registers, even if count < 16.
0277  *
0278  * Returns 0 for success, or an error code.
0279  */
0280 static inline unsigned int ev_byte_channel_send(unsigned int handle,
0281     unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
0282 {
0283     register uintptr_t r11 __asm__("r11");
0284     register uintptr_t r3 __asm__("r3");
0285     register uintptr_t r4 __asm__("r4");
0286     register uintptr_t r5 __asm__("r5");
0287     register uintptr_t r6 __asm__("r6");
0288     register uintptr_t r7 __asm__("r7");
0289     register uintptr_t r8 __asm__("r8");
0290     const uint32_t *p = (const uint32_t *) buffer;
0291 
0292     r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND);
0293     r3 = handle;
0294     r4 = *count;
0295     r5 = be32toh(p[0]);
0296     r6 = be32toh(p[1]);
0297     r7 = be32toh(p[2]);
0298     r8 = be32toh(p[3]);
0299 
0300     asm volatile("bl    epapr_hypercall_start"
0301         : "+r" (r11), "+r" (r3),
0302           "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
0303         : : EV_HCALL_CLOBBERS6
0304     );
0305 
0306     *count = r4;
0307 
0308     return r3;
0309 }
0310 
0311 /**
0312  * ev_byte_channel_receive - fetch characters from a byte channel
0313  * @handle: byte channel handle
0314  * @count: (input) max num of chars to receive, (output) num chars received
0315  * @buffer: pointer to a 16-byte buffer
0316  *
0317  * The size of @buffer must be at least 16 bytes, even if you request fewer
0318  * than 16 characters, because we always write 16 bytes to @buffer.  This is
0319  * for performance reasons.
0320  *
0321  * Returns 0 for success, or an error code.
0322  */
0323 static inline unsigned int ev_byte_channel_receive(unsigned int handle,
0324     unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
0325 {
0326     register uintptr_t r11 __asm__("r11");
0327     register uintptr_t r3 __asm__("r3");
0328     register uintptr_t r4 __asm__("r4");
0329     register uintptr_t r5 __asm__("r5");
0330     register uintptr_t r6 __asm__("r6");
0331     register uintptr_t r7 __asm__("r7");
0332     register uintptr_t r8 __asm__("r8");
0333     uint32_t *p = (uint32_t *) buffer;
0334 
0335     r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE);
0336     r3 = handle;
0337     r4 = *count;
0338 
0339     asm volatile("bl    epapr_hypercall_start"
0340         : "+r" (r11), "+r" (r3), "+r" (r4),
0341           "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
0342         : : EV_HCALL_CLOBBERS6
0343     );
0344 
0345     *count = r4;
0346     p[0] = htobe32(r5);
0347     p[1] = htobe32(r6);
0348     p[2] = htobe32(r7);
0349     p[3] = htobe32(r8);
0350 
0351     return r3;
0352 }
0353 
0354 /**
0355  * ev_byte_channel_poll - returns the status of the byte channel buffers
0356  * @handle: byte channel handle
0357  * @rx_count: returned count of bytes in receive queue
0358  * @tx_count: returned count of free space in transmit queue
0359  *
0360  * This function reports the amount of data in the receive queue (i.e. the
0361  * number of bytes you can read), and the amount of free space in the transmit
0362  * queue (i.e. the number of bytes you can write).
0363  *
0364  * Returns 0 for success, or an error code.
0365  */
0366 static inline unsigned int ev_byte_channel_poll(unsigned int handle,
0367     unsigned int *rx_count, unsigned int *tx_count)
0368 {
0369     register uintptr_t r11 __asm__("r11");
0370     register uintptr_t r3 __asm__("r3");
0371     register uintptr_t r4 __asm__("r4");
0372     register uintptr_t r5 __asm__("r5");
0373 
0374     r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
0375     r3 = handle;
0376 
0377     asm volatile("bl    epapr_hypercall_start"
0378         : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
0379         : : EV_HCALL_CLOBBERS3
0380     );
0381 
0382     *rx_count = r4;
0383     *tx_count = r5;
0384 
0385     return r3;
0386 }
0387 
0388 /**
0389  * ev_int_iack - acknowledge an interrupt
0390  * @handle: handle to the target interrupt controller
0391  * @vector: returned interrupt vector
0392  *
0393  * If handle is zero, the function returns the next interrupt source
0394  * number to be handled irrespective of the hierarchy or cascading
0395  * of interrupt controllers. If non-zero, specifies a handle to the
0396  * interrupt controller that is the target of the acknowledge.
0397  *
0398  * Returns 0 for success, or an error code.
0399  */
0400 static inline unsigned int ev_int_iack(unsigned int handle,
0401     unsigned int *vector)
0402 {
0403     register uintptr_t r11 __asm__("r11");
0404     register uintptr_t r3 __asm__("r3");
0405     register uintptr_t r4 __asm__("r4");
0406 
0407     r11 = EV_HCALL_TOKEN(EV_INT_IACK);
0408     r3 = handle;
0409 
0410     asm volatile("bl    epapr_hypercall_start"
0411         : "+r" (r11), "+r" (r3), "=r" (r4)
0412         : : EV_HCALL_CLOBBERS2
0413     );
0414 
0415     *vector = r4;
0416 
0417     return r3;
0418 }
0419 
0420 /**
0421  * ev_doorbell_send - send a doorbell to another partition
0422  * @handle: doorbell send handle
0423  *
0424  * Returns 0 for success, or an error code.
0425  */
0426 static inline unsigned int ev_doorbell_send(unsigned int handle)
0427 {
0428     register uintptr_t r11 __asm__("r11");
0429     register uintptr_t r3 __asm__("r3");
0430 
0431     r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
0432     r3 = handle;
0433 
0434     asm volatile("bl    epapr_hypercall_start"
0435         : "+r" (r11), "+r" (r3)
0436         : : EV_HCALL_CLOBBERS1
0437     );
0438 
0439     return r3;
0440 }
0441 
0442 /**
0443  * ev_idle -- wait for next interrupt on this core
0444  *
0445  * Returns 0 for success, or an error code.
0446  */
0447 static inline unsigned int ev_idle(void)
0448 {
0449     register uintptr_t r11 __asm__("r11");
0450     register uintptr_t r3 __asm__("r3");
0451 
0452     r11 = EV_HCALL_TOKEN(EV_IDLE);
0453 
0454     asm volatile("bl    epapr_hypercall_start"
0455         : "+r" (r11), "=r" (r3)
0456         : : EV_HCALL_CLOBBERS1
0457     );
0458 
0459     return r3;
0460 }
0461 
0462 #ifdef CONFIG_EPAPR_PARAVIRT
0463 static inline unsigned long epapr_hypercall(unsigned long *in,
0464                 unsigned long *out,
0465                 unsigned long nr)
0466 {
0467     unsigned long register r0 asm("r0");
0468     unsigned long register r3 asm("r3") = in[0];
0469     unsigned long register r4 asm("r4") = in[1];
0470     unsigned long register r5 asm("r5") = in[2];
0471     unsigned long register r6 asm("r6") = in[3];
0472     unsigned long register r7 asm("r7") = in[4];
0473     unsigned long register r8 asm("r8") = in[5];
0474     unsigned long register r9 asm("r9") = in[6];
0475     unsigned long register r10 asm("r10") = in[7];
0476     unsigned long register r11 asm("r11") = nr;
0477     unsigned long register r12 asm("r12");
0478 
0479     asm volatile("bl    epapr_hypercall_start"
0480              : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6),
0481                "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11),
0482                "=r"(r12)
0483              : "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "r"(r8),
0484                "r"(r9), "r"(r10), "r"(r11)
0485              : "memory", "cc", "xer", "ctr", "lr");
0486 
0487     out[0] = r4;
0488     out[1] = r5;
0489     out[2] = r6;
0490     out[3] = r7;
0491     out[4] = r8;
0492     out[5] = r9;
0493     out[6] = r10;
0494     out[7] = r11;
0495 
0496     return r3;
0497 }
0498 #else
0499 static unsigned long epapr_hypercall(unsigned long *in,
0500                    unsigned long *out,
0501                    unsigned long nr)
0502 {
0503     return EV_UNIMPLEMENTED;
0504 }
0505 #endif
0506 
0507 static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2)
0508 {
0509     unsigned long in[8];
0510     unsigned long out[8];
0511     unsigned long r;
0512 
0513     r = epapr_hypercall(in, out, nr);
0514     *r2 = out[0];
0515 
0516     return r;
0517 }
0518 
0519 static inline long epapr_hypercall0(unsigned int nr)
0520 {
0521     unsigned long in[8];
0522     unsigned long out[8];
0523 
0524     return epapr_hypercall(in, out, nr);
0525 }
0526 
0527 static inline long epapr_hypercall1(unsigned int nr, unsigned long p1)
0528 {
0529     unsigned long in[8];
0530     unsigned long out[8];
0531 
0532     in[0] = p1;
0533     return epapr_hypercall(in, out, nr);
0534 }
0535 
0536 static inline long epapr_hypercall2(unsigned int nr, unsigned long p1,
0537                     unsigned long p2)
0538 {
0539     unsigned long in[8];
0540     unsigned long out[8];
0541 
0542     in[0] = p1;
0543     in[1] = p2;
0544     return epapr_hypercall(in, out, nr);
0545 }
0546 
0547 static inline long epapr_hypercall3(unsigned int nr, unsigned long p1,
0548                     unsigned long p2, unsigned long p3)
0549 {
0550     unsigned long in[8];
0551     unsigned long out[8];
0552 
0553     in[0] = p1;
0554     in[1] = p2;
0555     in[2] = p3;
0556     return epapr_hypercall(in, out, nr);
0557 }
0558 
0559 static inline long epapr_hypercall4(unsigned int nr, unsigned long p1,
0560                     unsigned long p2, unsigned long p3,
0561                     unsigned long p4)
0562 {
0563     unsigned long in[8];
0564     unsigned long out[8];
0565 
0566     in[0] = p1;
0567     in[1] = p2;
0568     in[2] = p3;
0569     in[3] = p4;
0570     return epapr_hypercall(in, out, nr);
0571 }
0572 #endif /* !__ASSEMBLY__ */
0573 #endif /* _EPAPR_HCALLS_H */