Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: introduce ePAPR embedded hypervisor hcall interface

ePAPR hypervisors provide operating system services via a "hypercall"
interface. The following steps need to be performed to make an hcall:

1. Load r11 with the hcall number
2. Load specific other registers with parameters
3. Issue instrucion "sc 1"
4. The return code is in r3
5. Other returned parameters are in other registers.

To provide this service to the kernel, these steps are wrapped in inline
assembly functions. Standard ePAPR hcalls are in epapr_hcalls.h, and
Freescale extensions are in fsl_hcalls.h.

Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by

Timur Tabi and committed by
Kumar Gala
bd497fc9 6ec36b58

+1157
+502
arch/powerpc/include/asm/epapr_hcalls.h
··· 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 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 <linux/types.h> 54 + #include <linux/errno.h> 55 + #include <asm/byteorder.h> 56 + 57 + #define EV_BYTE_CHANNEL_SEND 1 58 + #define EV_BYTE_CHANNEL_RECEIVE 2 59 + #define EV_BYTE_CHANNEL_POLL 3 60 + #define EV_INT_SET_CONFIG 4 61 + #define EV_INT_GET_CONFIG 5 62 + #define EV_INT_SET_MASK 6 63 + #define EV_INT_GET_MASK 7 64 + #define EV_INT_IACK 9 65 + #define EV_INT_EOI 10 66 + #define EV_INT_SEND_IPI 11 67 + #define EV_INT_SET_TASK_PRIORITY 12 68 + #define EV_INT_GET_TASK_PRIORITY 13 69 + #define EV_DOORBELL_SEND 14 70 + #define EV_MSGSND 15 71 + #define EV_IDLE 16 72 + 73 + /* vendor ID: epapr */ 74 + #define EV_LOCAL_VENDOR_ID 0 /* for private use */ 75 + #define EV_EPAPR_VENDOR_ID 1 76 + #define EV_FSL_VENDOR_ID 2 /* Freescale Semiconductor */ 77 + #define EV_IBM_VENDOR_ID 3 /* IBM */ 78 + #define EV_GHS_VENDOR_ID 4 /* Green Hills Software */ 79 + #define EV_ENEA_VENDOR_ID 5 /* Enea */ 80 + #define EV_WR_VENDOR_ID 6 /* Wind River Systems */ 81 + #define EV_AMCC_VENDOR_ID 7 /* Applied Micro Circuits */ 82 + #define EV_KVM_VENDOR_ID 42 /* KVM */ 83 + 84 + /* The max number of bytes that a byte channel can send or receive per call */ 85 + #define EV_BYTE_CHANNEL_MAX_BYTES 16 86 + 87 + 88 + #define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num)) 89 + #define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num) 90 + 91 + /* epapr error codes */ 92 + #define EV_EPERM 1 /* Operation not permitted */ 93 + #define EV_ENOENT 2 /* Entry Not Found */ 94 + #define EV_EIO 3 /* I/O error occured */ 95 + #define EV_EAGAIN 4 /* The operation had insufficient 96 + * resources to complete and should be 97 + * retried 98 + */ 99 + #define EV_ENOMEM 5 /* There was insufficient memory to 100 + * complete the operation */ 101 + #define EV_EFAULT 6 /* Bad guest address */ 102 + #define EV_ENODEV 7 /* No such device */ 103 + #define EV_EINVAL 8 /* An argument supplied to the hcall 104 + was out of range or invalid */ 105 + #define EV_INTERNAL 9 /* An internal error occured */ 106 + #define EV_CONFIG 10 /* A configuration error was detected */ 107 + #define EV_INVALID_STATE 11 /* The object is in an invalid state */ 108 + #define EV_UNIMPLEMENTED 12 /* Unimplemented hypercall */ 109 + #define EV_BUFFER_OVERFLOW 13 /* Caller-supplied buffer too small */ 110 + 111 + /* 112 + * Hypercall register clobber list 113 + * 114 + * These macros are used to define the list of clobbered registers during a 115 + * hypercall. Technically, registers r0 and r3-r12 are always clobbered, 116 + * but the gcc inline assembly syntax does not allow us to specify registers 117 + * on the clobber list that are also on the input/output list. Therefore, 118 + * the lists of clobbered registers depends on the number of register 119 + * parmeters ("+r" and "=r") passed to the hypercall. 120 + * 121 + * Each assembly block should use one of the HCALL_CLOBBERSx macros. As a 122 + * general rule, 'x' is the number of parameters passed to the assembly 123 + * block *except* for r11. 124 + * 125 + * If you're not sure, just use the smallest value of 'x' that does not 126 + * generate a compilation error. Because these are static inline functions, 127 + * the compiler will only check the clobber list for a function if you 128 + * compile code that calls that function. 129 + * 130 + * r3 and r11 are not included in any clobbers list because they are always 131 + * listed as output registers. 132 + * 133 + * XER, CTR, and LR are currently listed as clobbers because it's uncertain 134 + * whether they will be clobbered. 135 + * 136 + * Note that r11 can be used as an output parameter. 137 + */ 138 + 139 + /* List of common clobbered registers. Do not use this macro. */ 140 + #define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc" 141 + 142 + #define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS 143 + #define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10" 144 + #define EV_HCALL_CLOBBERS6 EV_HCALL_CLOBBERS7, "r9" 145 + #define EV_HCALL_CLOBBERS5 EV_HCALL_CLOBBERS6, "r8" 146 + #define EV_HCALL_CLOBBERS4 EV_HCALL_CLOBBERS5, "r7" 147 + #define EV_HCALL_CLOBBERS3 EV_HCALL_CLOBBERS4, "r6" 148 + #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5" 149 + #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4" 150 + 151 + 152 + /* 153 + * We use "uintptr_t" to define a register because it's guaranteed to be a 154 + * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit 155 + * platform. 156 + * 157 + * All registers are either input/output or output only. Registers that are 158 + * initialized before making the hypercall are input/output. All 159 + * input/output registers are represented with "+r". Output-only registers 160 + * are represented with "=r". Do not specify any unused registers. The 161 + * clobber list will tell the compiler that the hypercall modifies those 162 + * registers, which is good enough. 163 + */ 164 + 165 + /** 166 + * ev_int_set_config - configure the specified interrupt 167 + * @interrupt: the interrupt number 168 + * @config: configuration for this interrupt 169 + * @priority: interrupt priority 170 + * @destination: destination CPU number 171 + * 172 + * Returns 0 for success, or an error code. 173 + */ 174 + static inline unsigned int ev_int_set_config(unsigned int interrupt, 175 + uint32_t config, unsigned int priority, uint32_t destination) 176 + { 177 + register uintptr_t r11 __asm__("r11"); 178 + register uintptr_t r3 __asm__("r3"); 179 + register uintptr_t r4 __asm__("r4"); 180 + register uintptr_t r5 __asm__("r5"); 181 + register uintptr_t r6 __asm__("r6"); 182 + 183 + r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG); 184 + r3 = interrupt; 185 + r4 = config; 186 + r5 = priority; 187 + r6 = destination; 188 + 189 + __asm__ __volatile__ ("sc 1" 190 + : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6) 191 + : : EV_HCALL_CLOBBERS4 192 + ); 193 + 194 + return r3; 195 + } 196 + 197 + /** 198 + * ev_int_get_config - return the config of the specified interrupt 199 + * @interrupt: the interrupt number 200 + * @config: returned configuration for this interrupt 201 + * @priority: returned interrupt priority 202 + * @destination: returned destination CPU number 203 + * 204 + * Returns 0 for success, or an error code. 205 + */ 206 + static inline unsigned int ev_int_get_config(unsigned int interrupt, 207 + uint32_t *config, unsigned int *priority, uint32_t *destination) 208 + { 209 + register uintptr_t r11 __asm__("r11"); 210 + register uintptr_t r3 __asm__("r3"); 211 + register uintptr_t r4 __asm__("r4"); 212 + register uintptr_t r5 __asm__("r5"); 213 + register uintptr_t r6 __asm__("r6"); 214 + 215 + r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG); 216 + r3 = interrupt; 217 + 218 + __asm__ __volatile__ ("sc 1" 219 + : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6) 220 + : : EV_HCALL_CLOBBERS4 221 + ); 222 + 223 + *config = r4; 224 + *priority = r5; 225 + *destination = r6; 226 + 227 + return r3; 228 + } 229 + 230 + /** 231 + * ev_int_set_mask - sets the mask for the specified interrupt source 232 + * @interrupt: the interrupt number 233 + * @mask: 0=enable interrupts, 1=disable interrupts 234 + * 235 + * Returns 0 for success, or an error code. 236 + */ 237 + static inline unsigned int ev_int_set_mask(unsigned int interrupt, 238 + unsigned int mask) 239 + { 240 + register uintptr_t r11 __asm__("r11"); 241 + register uintptr_t r3 __asm__("r3"); 242 + register uintptr_t r4 __asm__("r4"); 243 + 244 + r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK); 245 + r3 = interrupt; 246 + r4 = mask; 247 + 248 + __asm__ __volatile__ ("sc 1" 249 + : "+r" (r11), "+r" (r3), "+r" (r4) 250 + : : EV_HCALL_CLOBBERS2 251 + ); 252 + 253 + return r3; 254 + } 255 + 256 + /** 257 + * ev_int_get_mask - returns the mask for the specified interrupt source 258 + * @interrupt: the interrupt number 259 + * @mask: returned mask for this interrupt (0=enabled, 1=disabled) 260 + * 261 + * Returns 0 for success, or an error code. 262 + */ 263 + static inline unsigned int ev_int_get_mask(unsigned int interrupt, 264 + unsigned int *mask) 265 + { 266 + register uintptr_t r11 __asm__("r11"); 267 + register uintptr_t r3 __asm__("r3"); 268 + register uintptr_t r4 __asm__("r4"); 269 + 270 + r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK); 271 + r3 = interrupt; 272 + 273 + __asm__ __volatile__ ("sc 1" 274 + : "+r" (r11), "+r" (r3), "=r" (r4) 275 + : : EV_HCALL_CLOBBERS2 276 + ); 277 + 278 + *mask = r4; 279 + 280 + return r3; 281 + } 282 + 283 + /** 284 + * ev_int_eoi - signal the end of interrupt processing 285 + * @interrupt: the interrupt number 286 + * 287 + * This function signals the end of processing for the the specified 288 + * interrupt, which must be the interrupt currently in service. By 289 + * definition, this is also the highest-priority interrupt. 290 + * 291 + * Returns 0 for success, or an error code. 292 + */ 293 + static inline unsigned int ev_int_eoi(unsigned int interrupt) 294 + { 295 + register uintptr_t r11 __asm__("r11"); 296 + register uintptr_t r3 __asm__("r3"); 297 + 298 + r11 = EV_HCALL_TOKEN(EV_INT_EOI); 299 + r3 = interrupt; 300 + 301 + __asm__ __volatile__ ("sc 1" 302 + : "+r" (r11), "+r" (r3) 303 + : : EV_HCALL_CLOBBERS1 304 + ); 305 + 306 + return r3; 307 + } 308 + 309 + /** 310 + * ev_byte_channel_send - send characters to a byte stream 311 + * @handle: byte stream handle 312 + * @count: (input) num of chars to send, (output) num chars sent 313 + * @buffer: pointer to a 16-byte buffer 314 + * 315 + * @buffer must be at least 16 bytes long, because all 16 bytes will be 316 + * read from memory into registers, even if count < 16. 317 + * 318 + * Returns 0 for success, or an error code. 319 + */ 320 + static inline unsigned int ev_byte_channel_send(unsigned int handle, 321 + unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES]) 322 + { 323 + register uintptr_t r11 __asm__("r11"); 324 + register uintptr_t r3 __asm__("r3"); 325 + register uintptr_t r4 __asm__("r4"); 326 + register uintptr_t r5 __asm__("r5"); 327 + register uintptr_t r6 __asm__("r6"); 328 + register uintptr_t r7 __asm__("r7"); 329 + register uintptr_t r8 __asm__("r8"); 330 + const uint32_t *p = (const uint32_t *) buffer; 331 + 332 + r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND); 333 + r3 = handle; 334 + r4 = *count; 335 + r5 = be32_to_cpu(p[0]); 336 + r6 = be32_to_cpu(p[1]); 337 + r7 = be32_to_cpu(p[2]); 338 + r8 = be32_to_cpu(p[3]); 339 + 340 + __asm__ __volatile__ ("sc 1" 341 + : "+r" (r11), "+r" (r3), 342 + "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8) 343 + : : EV_HCALL_CLOBBERS6 344 + ); 345 + 346 + *count = r4; 347 + 348 + return r3; 349 + } 350 + 351 + /** 352 + * ev_byte_channel_receive - fetch characters from a byte channel 353 + * @handle: byte channel handle 354 + * @count: (input) max num of chars to receive, (output) num chars received 355 + * @buffer: pointer to a 16-byte buffer 356 + * 357 + * The size of @buffer must be at least 16 bytes, even if you request fewer 358 + * than 16 characters, because we always write 16 bytes to @buffer. This is 359 + * for performance reasons. 360 + * 361 + * Returns 0 for success, or an error code. 362 + */ 363 + static inline unsigned int ev_byte_channel_receive(unsigned int handle, 364 + unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES]) 365 + { 366 + register uintptr_t r11 __asm__("r11"); 367 + register uintptr_t r3 __asm__("r3"); 368 + register uintptr_t r4 __asm__("r4"); 369 + register uintptr_t r5 __asm__("r5"); 370 + register uintptr_t r6 __asm__("r6"); 371 + register uintptr_t r7 __asm__("r7"); 372 + register uintptr_t r8 __asm__("r8"); 373 + uint32_t *p = (uint32_t *) buffer; 374 + 375 + r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE); 376 + r3 = handle; 377 + r4 = *count; 378 + 379 + __asm__ __volatile__ ("sc 1" 380 + : "+r" (r11), "+r" (r3), "+r" (r4), 381 + "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8) 382 + : : EV_HCALL_CLOBBERS6 383 + ); 384 + 385 + *count = r4; 386 + p[0] = cpu_to_be32(r5); 387 + p[1] = cpu_to_be32(r6); 388 + p[2] = cpu_to_be32(r7); 389 + p[3] = cpu_to_be32(r8); 390 + 391 + return r3; 392 + } 393 + 394 + /** 395 + * ev_byte_channel_poll - returns the status of the byte channel buffers 396 + * @handle: byte channel handle 397 + * @rx_count: returned count of bytes in receive queue 398 + * @tx_count: returned count of free space in transmit queue 399 + * 400 + * This function reports the amount of data in the receive queue (i.e. the 401 + * number of bytes you can read), and the amount of free space in the transmit 402 + * queue (i.e. the number of bytes you can write). 403 + * 404 + * Returns 0 for success, or an error code. 405 + */ 406 + static inline unsigned int ev_byte_channel_poll(unsigned int handle, 407 + unsigned int *rx_count, unsigned int *tx_count) 408 + { 409 + register uintptr_t r11 __asm__("r11"); 410 + register uintptr_t r3 __asm__("r3"); 411 + register uintptr_t r4 __asm__("r4"); 412 + register uintptr_t r5 __asm__("r5"); 413 + 414 + r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL); 415 + r3 = handle; 416 + 417 + __asm__ __volatile__ ("sc 1" 418 + : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5) 419 + : : EV_HCALL_CLOBBERS3 420 + ); 421 + 422 + *rx_count = r4; 423 + *tx_count = r5; 424 + 425 + return r3; 426 + } 427 + 428 + /** 429 + * ev_int_iack - acknowledge an interrupt 430 + * @handle: handle to the target interrupt controller 431 + * @vector: returned interrupt vector 432 + * 433 + * If handle is zero, the function returns the next interrupt source 434 + * number to be handled irrespective of the hierarchy or cascading 435 + * of interrupt controllers. If non-zero, specifies a handle to the 436 + * interrupt controller that is the target of the acknowledge. 437 + * 438 + * Returns 0 for success, or an error code. 439 + */ 440 + static inline unsigned int ev_int_iack(unsigned int handle, 441 + unsigned int *vector) 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 = EV_HCALL_TOKEN(EV_INT_IACK); 448 + r3 = handle; 449 + 450 + __asm__ __volatile__ ("sc 1" 451 + : "+r" (r11), "+r" (r3), "=r" (r4) 452 + : : EV_HCALL_CLOBBERS2 453 + ); 454 + 455 + *vector = r4; 456 + 457 + return r3; 458 + } 459 + 460 + /** 461 + * ev_doorbell_send - send a doorbell to another partition 462 + * @handle: doorbell send handle 463 + * 464 + * Returns 0 for success, or an error code. 465 + */ 466 + static inline unsigned int ev_doorbell_send(unsigned int handle) 467 + { 468 + register uintptr_t r11 __asm__("r11"); 469 + register uintptr_t r3 __asm__("r3"); 470 + 471 + r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND); 472 + r3 = handle; 473 + 474 + __asm__ __volatile__ ("sc 1" 475 + : "+r" (r11), "+r" (r3) 476 + : : EV_HCALL_CLOBBERS1 477 + ); 478 + 479 + return r3; 480 + } 481 + 482 + /** 483 + * ev_idle -- wait for next interrupt on this core 484 + * 485 + * Returns 0 for success, or an error code. 486 + */ 487 + static inline unsigned int ev_idle(void) 488 + { 489 + register uintptr_t r11 __asm__("r11"); 490 + register uintptr_t r3 __asm__("r3"); 491 + 492 + r11 = EV_HCALL_TOKEN(EV_IDLE); 493 + 494 + __asm__ __volatile__ ("sc 1" 495 + : "+r" (r11), "=r" (r3) 496 + : : EV_HCALL_CLOBBERS1 497 + ); 498 + 499 + return r3; 500 + } 501 + 502 + #endif
+655
arch/powerpc/include/asm/fsl_hcalls.h
··· 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 + */ 91 + static 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__ ("sc 1" 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_partiton_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 + */ 121 + static 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__ ("sc 1" 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 + */ 175 + static 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__ ("sc 1" 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 + */ 224 + static 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__ ("sc 1" 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 + */ 255 + static 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__ ("sc 1" 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 + */ 285 + static 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__ ("sc 1" 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 + */ 312 + static 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__ ("sc 1" 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 + */ 341 + struct 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 + */ 357 + static 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__ ("sc 1" 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 + */ 394 + static 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__ ("sc 1" 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 + */ 416 + static 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__ ("sc 1" 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 + */ 440 + static 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__ ("sc 1" 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 + */ 465 + static 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__ ("sc 1" 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 + */ 492 + static 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__ ("sc 1" 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 + */ 534 + static 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__ ("sc 1" 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 + */ 565 + static 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__ ("sc 1" 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 + */ 590 + static 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__ ("sc 1" 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 + */ 613 + static 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__ ("sc 1" 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 + */ 640 + static 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__ ("sc 1" 649 + : "+r" (r11), "+r" (r3) 650 + : : EV_HCALL_CLOBBERS1 651 + ); 652 + 653 + return r3; 654 + } 655 + #endif