1 /* 2 * ePAPR hcall interface 3 * 4 * Copyright 2008-2011 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 /* A "hypercall" is an "sc 1" instruction. This header file provides C 41 * wrapper functions for the ePAPR hypervisor interface. It is inteded 42 * for use by Linux device drivers and other operating systems. 43 * 44 * The hypercalls are implemented as inline assembly, rather than assembly 45 * language functions in a .S file, for optimization. It allows 46 * the caller to issue the hypercall instruction directly, improving both 47 * performance and memory footprint. 48 */ 49 50 #ifndef _EPAPR_HCALLS_H 51 #define _EPAPR_HCALLS_H 52 53 #include <uapi/asm/epapr_hcalls.h> 54 55 #ifndef __ASSEMBLY__ 56 #include <linux/types.h> 57 #include <linux/errno.h> 58 #include <asm/byteorder.h> 59 60 /* 61 * Hypercall register clobber list 62 * 63 * These macros are used to define the list of clobbered registers during a 64 * hypercall. Technically, registers r0 and r3-r12 are always clobbered, 65 * but the gcc inline assembly syntax does not allow us to specify registers 66 * on the clobber list that are also on the input/output list. Therefore, 67 * the lists of clobbered registers depends on the number of register 68 * parameters ("+r" and "=r") passed to the hypercall. 69 * 70 * Each assembly block should use one of the HCALL_CLOBBERSx macros. As a 71 * general rule, 'x' is the number of parameters passed to the assembly 72 * block *except* for r11. 73 * 74 * If you're not sure, just use the smallest value of 'x' that does not 75 * generate a compilation error. Because these are static inline functions, 76 * the compiler will only check the clobber list for a function if you 77 * compile code that calls that function. 78 * 79 * r3 and r11 are not included in any clobbers list because they are always 80 * listed as output registers. 81 * 82 * XER, CTR, and LR are currently listed as clobbers because it's uncertain 83 * whether they will be clobbered. 84 * 85 * Note that r11 can be used as an output parameter. 86 * 87 * The "memory" clobber is only necessary for hcalls where the Hypervisor 88 * will read or write guest memory. However, we add it to all hcalls because 89 * the impact is minimal, and we want to ensure that it's present for the 90 * hcalls that need it. 91 */ 92 93 /* List of common clobbered registers. Do not use this macro. */ 94 #define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc", "memory" 95 96 #define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS 97 #define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10" 98 #define EV_HCALL_CLOBBERS6 EV_HCALL_CLOBBERS7, "r9" 99 #define EV_HCALL_CLOBBERS5 EV_HCALL_CLOBBERS6, "r8" 100 #define EV_HCALL_CLOBBERS4 EV_HCALL_CLOBBERS5, "r7" 101 #define EV_HCALL_CLOBBERS3 EV_HCALL_CLOBBERS4, "r6" 102 #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5" 103 #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4" 104 105 extern bool epapr_paravirt_enabled; 106 extern u32 epapr_hypercall_start[]; 107 108 #ifdef CONFIG_EPAPR_PARAVIRT 109 int __init epapr_paravirt_early_init(void); 110 #else 111 static inline int epapr_paravirt_early_init(void) { return 0; } 112 #endif 113 114 /* 115 * We use "uintptr_t" to define a register because it's guaranteed to be a 116 * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit 117 * platform. 118 * 119 * All registers are either input/output or output only. Registers that are 120 * initialized before making the hypercall are input/output. All 121 * input/output registers are represented with "+r". Output-only registers 122 * are represented with "=r". Do not specify any unused registers. The 123 * clobber list will tell the compiler that the hypercall modifies those 124 * registers, which is good enough. 125 */ 126 127 /** 128 * ev_int_set_config - configure the specified interrupt 129 * @interrupt: the interrupt number 130 * @config: configuration for this interrupt 131 * @priority: interrupt priority 132 * @destination: destination CPU number 133 * 134 * Returns 0 for success, or an error code. 135 */ 136 static inline unsigned int ev_int_set_config(unsigned int interrupt, 137 uint32_t config, unsigned int priority, uint32_t destination) 138 { 139 register uintptr_t r11 __asm__("r11"); 140 register uintptr_t r3 __asm__("r3"); 141 register uintptr_t r4 __asm__("r4"); 142 register uintptr_t r5 __asm__("r5"); 143 register uintptr_t r6 __asm__("r6"); 144 145 r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG); 146 r3 = interrupt; 147 r4 = config; 148 r5 = priority; 149 r6 = destination; 150 151 asm volatile("bl epapr_hypercall_start" 152 : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6) 153 : : EV_HCALL_CLOBBERS4 154 ); 155 156 return r3; 157 } 158 159 /** 160 * ev_int_get_config - return the config of the specified interrupt 161 * @interrupt: the interrupt number 162 * @config: returned configuration for this interrupt 163 * @priority: returned interrupt priority 164 * @destination: returned destination CPU number 165 * 166 * Returns 0 for success, or an error code. 167 */ 168 static inline unsigned int ev_int_get_config(unsigned int interrupt, 169 uint32_t *config, unsigned int *priority, uint32_t *destination) 170 { 171 register uintptr_t r11 __asm__("r11"); 172 register uintptr_t r3 __asm__("r3"); 173 register uintptr_t r4 __asm__("r4"); 174 register uintptr_t r5 __asm__("r5"); 175 register uintptr_t r6 __asm__("r6"); 176 177 r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG); 178 r3 = interrupt; 179 180 asm volatile("bl epapr_hypercall_start" 181 : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6) 182 : : EV_HCALL_CLOBBERS4 183 ); 184 185 *config = r4; 186 *priority = r5; 187 *destination = r6; 188 189 return r3; 190 } 191 192 /** 193 * ev_int_set_mask - sets the mask for the specified interrupt source 194 * @interrupt: the interrupt number 195 * @mask: 0=enable interrupts, 1=disable interrupts 196 * 197 * Returns 0 for success, or an error code. 198 */ 199 static inline unsigned int ev_int_set_mask(unsigned int interrupt, 200 unsigned int mask) 201 { 202 register uintptr_t r11 __asm__("r11"); 203 register uintptr_t r3 __asm__("r3"); 204 register uintptr_t r4 __asm__("r4"); 205 206 r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK); 207 r3 = interrupt; 208 r4 = mask; 209 210 asm volatile("bl epapr_hypercall_start" 211 : "+r" (r11), "+r" (r3), "+r" (r4) 212 : : EV_HCALL_CLOBBERS2 213 ); 214 215 return r3; 216 } 217 218 /** 219 * ev_int_get_mask - returns the mask for the specified interrupt source 220 * @interrupt: the interrupt number 221 * @mask: returned mask for this interrupt (0=enabled, 1=disabled) 222 * 223 * Returns 0 for success, or an error code. 224 */ 225 static inline unsigned int ev_int_get_mask(unsigned int interrupt, 226 unsigned int *mask) 227 { 228 register uintptr_t r11 __asm__("r11"); 229 register uintptr_t r3 __asm__("r3"); 230 register uintptr_t r4 __asm__("r4"); 231 232 r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK); 233 r3 = interrupt; 234 235 asm volatile("bl epapr_hypercall_start" 236 : "+r" (r11), "+r" (r3), "=r" (r4) 237 : : EV_HCALL_CLOBBERS2 238 ); 239 240 *mask = r4; 241 242 return r3; 243 } 244 245 /** 246 * ev_int_eoi - signal the end of interrupt processing 247 * @interrupt: the interrupt number 248 * 249 * This function signals the end of processing for the specified 250 * interrupt, which must be the interrupt currently in service. By 251 * definition, this is also the highest-priority interrupt. 252 * 253 * Returns 0 for success, or an error code. 254 */ 255 static inline unsigned int ev_int_eoi(unsigned int interrupt) 256 { 257 register uintptr_t r11 __asm__("r11"); 258 register uintptr_t r3 __asm__("r3"); 259 260 r11 = EV_HCALL_TOKEN(EV_INT_EOI); 261 r3 = interrupt; 262 263 asm volatile("bl epapr_hypercall_start" 264 : "+r" (r11), "+r" (r3) 265 : : EV_HCALL_CLOBBERS1 266 ); 267 268 return r3; 269 } 270 271 /** 272 * ev_byte_channel_send - send characters to a byte stream 273 * @handle: byte stream handle 274 * @count: (input) num of chars to send, (output) num chars sent 275 * @buffer: pointer to a 16-byte buffer 276 * 277 * @buffer must be at least 16 bytes long, because all 16 bytes will be 278 * read from memory into registers, even if count < 16. 279 * 280 * Returns 0 for success, or an error code. 281 */ 282 static inline unsigned int ev_byte_channel_send(unsigned int handle, 283 unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES]) 284 { 285 register uintptr_t r11 __asm__("r11"); 286 register uintptr_t r3 __asm__("r3"); 287 register uintptr_t r4 __asm__("r4"); 288 register uintptr_t r5 __asm__("r5"); 289 register uintptr_t r6 __asm__("r6"); 290 register uintptr_t r7 __asm__("r7"); 291 register uintptr_t r8 __asm__("r8"); 292 const uint32_t *p = (const uint32_t *) buffer; 293 294 r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND); 295 r3 = handle; 296 r4 = *count; 297 r5 = be32_to_cpu(p[0]); 298 r6 = be32_to_cpu(p[1]); 299 r7 = be32_to_cpu(p[2]); 300 r8 = be32_to_cpu(p[3]); 301 302 asm volatile("bl epapr_hypercall_start" 303 : "+r" (r11), "+r" (r3), 304 "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8) 305 : : EV_HCALL_CLOBBERS6 306 ); 307 308 *count = r4; 309 310 return r3; 311 } 312 313 /** 314 * ev_byte_channel_receive - fetch characters from a byte channel 315 * @handle: byte channel handle 316 * @count: (input) max num of chars to receive, (output) num chars received 317 * @buffer: pointer to a 16-byte buffer 318 * 319 * The size of @buffer must be at least 16 bytes, even if you request fewer 320 * than 16 characters, because we always write 16 bytes to @buffer. This is 321 * for performance reasons. 322 * 323 * Returns 0 for success, or an error code. 324 */ 325 static inline unsigned int ev_byte_channel_receive(unsigned int handle, 326 unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES]) 327 { 328 register uintptr_t r11 __asm__("r11"); 329 register uintptr_t r3 __asm__("r3"); 330 register uintptr_t r4 __asm__("r4"); 331 register uintptr_t r5 __asm__("r5"); 332 register uintptr_t r6 __asm__("r6"); 333 register uintptr_t r7 __asm__("r7"); 334 register uintptr_t r8 __asm__("r8"); 335 uint32_t *p = (uint32_t *) buffer; 336 337 r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE); 338 r3 = handle; 339 r4 = *count; 340 341 asm volatile("bl epapr_hypercall_start" 342 : "+r" (r11), "+r" (r3), "+r" (r4), 343 "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8) 344 : : EV_HCALL_CLOBBERS6 345 ); 346 347 *count = r4; 348 p[0] = cpu_to_be32(r5); 349 p[1] = cpu_to_be32(r6); 350 p[2] = cpu_to_be32(r7); 351 p[3] = cpu_to_be32(r8); 352 353 return r3; 354 } 355 356 /** 357 * ev_byte_channel_poll - returns the status of the byte channel buffers 358 * @handle: byte channel handle 359 * @rx_count: returned count of bytes in receive queue 360 * @tx_count: returned count of free space in transmit queue 361 * 362 * This function reports the amount of data in the receive queue (i.e. the 363 * number of bytes you can read), and the amount of free space in the transmit 364 * queue (i.e. the number of bytes you can write). 365 * 366 * Returns 0 for success, or an error code. 367 */ 368 static inline unsigned int ev_byte_channel_poll(unsigned int handle, 369 unsigned int *rx_count, unsigned int *tx_count) 370 { 371 register uintptr_t r11 __asm__("r11"); 372 register uintptr_t r3 __asm__("r3"); 373 register uintptr_t r4 __asm__("r4"); 374 register uintptr_t r5 __asm__("r5"); 375 376 r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL); 377 r3 = handle; 378 379 asm volatile("bl epapr_hypercall_start" 380 : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5) 381 : : EV_HCALL_CLOBBERS3 382 ); 383 384 *rx_count = r4; 385 *tx_count = r5; 386 387 return r3; 388 } 389 390 /** 391 * ev_int_iack - acknowledge an interrupt 392 * @handle: handle to the target interrupt controller 393 * @vector: returned interrupt vector 394 * 395 * If handle is zero, the function returns the next interrupt source 396 * number to be handled irrespective of the hierarchy or cascading 397 * of interrupt controllers. If non-zero, specifies a handle to the 398 * interrupt controller that is the target of the acknowledge. 399 * 400 * Returns 0 for success, or an error code. 401 */ 402 static inline unsigned int ev_int_iack(unsigned int handle, 403 unsigned int *vector) 404 { 405 register uintptr_t r11 __asm__("r11"); 406 register uintptr_t r3 __asm__("r3"); 407 register uintptr_t r4 __asm__("r4"); 408 409 r11 = EV_HCALL_TOKEN(EV_INT_IACK); 410 r3 = handle; 411 412 asm volatile("bl epapr_hypercall_start" 413 : "+r" (r11), "+r" (r3), "=r" (r4) 414 : : EV_HCALL_CLOBBERS2 415 ); 416 417 *vector = r4; 418 419 return r3; 420 } 421 422 /** 423 * ev_doorbell_send - send a doorbell to another partition 424 * @handle: doorbell send handle 425 * 426 * Returns 0 for success, or an error code. 427 */ 428 static inline unsigned int ev_doorbell_send(unsigned int handle) 429 { 430 register uintptr_t r11 __asm__("r11"); 431 register uintptr_t r3 __asm__("r3"); 432 433 r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND); 434 r3 = handle; 435 436 asm volatile("bl epapr_hypercall_start" 437 : "+r" (r11), "+r" (r3) 438 : : EV_HCALL_CLOBBERS1 439 ); 440 441 return r3; 442 } 443 444 /** 445 * ev_idle -- wait for next interrupt on this core 446 * 447 * Returns 0 for success, or an error code. 448 */ 449 static inline unsigned int ev_idle(void) 450 { 451 register uintptr_t r11 __asm__("r11"); 452 register uintptr_t r3 __asm__("r3"); 453 454 r11 = EV_HCALL_TOKEN(EV_IDLE); 455 456 asm volatile("bl epapr_hypercall_start" 457 : "+r" (r11), "=r" (r3) 458 : : EV_HCALL_CLOBBERS1 459 ); 460 461 return r3; 462 } 463 464 #ifdef CONFIG_EPAPR_PARAVIRT 465 static inline unsigned long epapr_hypercall(unsigned long *in, 466 unsigned long *out, 467 unsigned long nr) 468 { 469 register unsigned long r0 asm("r0"); 470 register unsigned long r3 asm("r3") = in[0]; 471 register unsigned long r4 asm("r4") = in[1]; 472 register unsigned long r5 asm("r5") = in[2]; 473 register unsigned long r6 asm("r6") = in[3]; 474 register unsigned long r7 asm("r7") = in[4]; 475 register unsigned long r8 asm("r8") = in[5]; 476 register unsigned long r9 asm("r9") = in[6]; 477 register unsigned long r10 asm("r10") = in[7]; 478 register unsigned long r11 asm("r11") = nr; 479 register unsigned long r12 asm("r12"); 480 481 asm volatile("bl epapr_hypercall_start" 482 : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6), 483 "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11), 484 "=r"(r12) 485 : "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "r"(r8), 486 "r"(r9), "r"(r10), "r"(r11) 487 : "memory", "cc", "xer", "ctr", "lr"); 488 489 out[0] = r4; 490 out[1] = r5; 491 out[2] = r6; 492 out[3] = r7; 493 out[4] = r8; 494 out[5] = r9; 495 out[6] = r10; 496 out[7] = r11; 497 498 return r3; 499 } 500 #else 501 static unsigned long epapr_hypercall(unsigned long *in, 502 unsigned long *out, 503 unsigned long nr) 504 { 505 return EV_UNIMPLEMENTED; 506 } 507 #endif 508 509 static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2) 510 { 511 unsigned long in[8] = {0}; 512 unsigned long out[8]; 513 unsigned long r; 514 515 r = epapr_hypercall(in, out, nr); 516 *r2 = out[0]; 517 518 return r; 519 } 520 521 static inline long epapr_hypercall0(unsigned int nr) 522 { 523 unsigned long in[8] = {0}; 524 unsigned long out[8]; 525 526 return epapr_hypercall(in, out, nr); 527 } 528 529 static inline long epapr_hypercall1(unsigned int nr, unsigned long p1) 530 { 531 unsigned long in[8] = {0}; 532 unsigned long out[8]; 533 534 in[0] = p1; 535 return epapr_hypercall(in, out, nr); 536 } 537 538 static inline long epapr_hypercall2(unsigned int nr, unsigned long p1, 539 unsigned long p2) 540 { 541 unsigned long in[8] = {0}; 542 unsigned long out[8]; 543 544 in[0] = p1; 545 in[1] = p2; 546 return epapr_hypercall(in, out, nr); 547 } 548 549 static inline long epapr_hypercall3(unsigned int nr, unsigned long p1, 550 unsigned long p2, unsigned long p3) 551 { 552 unsigned long in[8] = {0}; 553 unsigned long out[8]; 554 555 in[0] = p1; 556 in[1] = p2; 557 in[2] = p3; 558 return epapr_hypercall(in, out, nr); 559 } 560 561 static inline long epapr_hypercall4(unsigned int nr, unsigned long p1, 562 unsigned long p2, unsigned long p3, 563 unsigned long p4) 564 { 565 unsigned long in[8] = {0}; 566 unsigned long out[8]; 567 568 in[0] = p1; 569 in[1] = p2; 570 in[2] = p3; 571 in[3] = p4; 572 return epapr_hypercall(in, out, nr); 573 } 574 #endif /* !__ASSEMBLY__ */ 575 #endif /* _EPAPR_HCALLS_H */ 576
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.