linux/arch/powerpc/include/asm/epapr_hcalls.h
<<
>>
Prefs
   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 <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 * parmeters ("+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
 105extern bool epapr_paravirt_enabled;
 106extern u32 epapr_hypercall_start[];
 107
 108/*
 109 * We use "uintptr_t" to define a register because it's guaranteed to be a
 110 * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit
 111 * platform.
 112 *
 113 * All registers are either input/output or output only.  Registers that are
 114 * initialized before making the hypercall are input/output.  All
 115 * input/output registers are represented with "+r".  Output-only registers
 116 * are represented with "=r".  Do not specify any unused registers.  The
 117 * clobber list will tell the compiler that the hypercall modifies those
 118 * registers, which is good enough.
 119 */
 120
 121/**
 122 * ev_int_set_config - configure the specified interrupt
 123 * @interrupt: the interrupt number
 124 * @config: configuration for this interrupt
 125 * @priority: interrupt priority
 126 * @destination: destination CPU number
 127 *
 128 * Returns 0 for success, or an error code.
 129 */
 130static inline unsigned int ev_int_set_config(unsigned int interrupt,
 131        uint32_t config, unsigned int priority, uint32_t destination)
 132{
 133        register uintptr_t r11 __asm__("r11");
 134        register uintptr_t r3 __asm__("r3");
 135        register uintptr_t r4 __asm__("r4");
 136        register uintptr_t r5 __asm__("r5");
 137        register uintptr_t r6 __asm__("r6");
 138
 139        r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG);
 140        r3  = interrupt;
 141        r4  = config;
 142        r5  = priority;
 143        r6  = destination;
 144
 145        asm volatile("bl        epapr_hypercall_start"
 146                : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
 147                : : EV_HCALL_CLOBBERS4
 148        );
 149
 150        return r3;
 151}
 152
 153/**
 154 * ev_int_get_config - return the config of the specified interrupt
 155 * @interrupt: the interrupt number
 156 * @config: returned configuration for this interrupt
 157 * @priority: returned interrupt priority
 158 * @destination: returned destination CPU number
 159 *
 160 * Returns 0 for success, or an error code.
 161 */
 162static inline unsigned int ev_int_get_config(unsigned int interrupt,
 163        uint32_t *config, unsigned int *priority, uint32_t *destination)
 164{
 165        register uintptr_t r11 __asm__("r11");
 166        register uintptr_t r3 __asm__("r3");
 167        register uintptr_t r4 __asm__("r4");
 168        register uintptr_t r5 __asm__("r5");
 169        register uintptr_t r6 __asm__("r6");
 170
 171        r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
 172        r3 = interrupt;
 173
 174        asm volatile("bl        epapr_hypercall_start"
 175                : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
 176                : : EV_HCALL_CLOBBERS4
 177        );
 178
 179        *config = r4;
 180        *priority = r5;
 181        *destination = r6;
 182
 183        return r3;
 184}
 185
 186/**
 187 * ev_int_set_mask - sets the mask for the specified interrupt source
 188 * @interrupt: the interrupt number
 189 * @mask: 0=enable interrupts, 1=disable interrupts
 190 *
 191 * Returns 0 for success, or an error code.
 192 */
 193static inline unsigned int ev_int_set_mask(unsigned int interrupt,
 194        unsigned int mask)
 195{
 196        register uintptr_t r11 __asm__("r11");
 197        register uintptr_t r3 __asm__("r3");
 198        register uintptr_t r4 __asm__("r4");
 199
 200        r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK);
 201        r3 = interrupt;
 202        r4 = mask;
 203
 204        asm volatile("bl        epapr_hypercall_start"
 205                : "+r" (r11), "+r" (r3), "+r" (r4)
 206                : : EV_HCALL_CLOBBERS2
 207        );
 208
 209        return r3;
 210}
 211
 212/**
 213 * ev_int_get_mask - returns the mask for the specified interrupt source
 214 * @interrupt: the interrupt number
 215 * @mask: returned mask for this interrupt (0=enabled, 1=disabled)
 216 *
 217 * Returns 0 for success, or an error code.
 218 */
 219static inline unsigned int ev_int_get_mask(unsigned int interrupt,
 220        unsigned int *mask)
 221{
 222        register uintptr_t r11 __asm__("r11");
 223        register uintptr_t r3 __asm__("r3");
 224        register uintptr_t r4 __asm__("r4");
 225
 226        r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
 227        r3 = interrupt;
 228
 229        asm volatile("bl        epapr_hypercall_start"
 230                : "+r" (r11), "+r" (r3), "=r" (r4)
 231                : : EV_HCALL_CLOBBERS2
 232        );
 233
 234        *mask = r4;
 235
 236        return r3;
 237}
 238
 239/**
 240 * ev_int_eoi - signal the end of interrupt processing
 241 * @interrupt: the interrupt number
 242 *
 243 * This function signals the end of processing for the the specified
 244 * interrupt, which must be the interrupt currently in service. By
 245 * definition, this is also the highest-priority interrupt.
 246 *
 247 * Returns 0 for success, or an error code.
 248 */
 249static inline unsigned int ev_int_eoi(unsigned int interrupt)
 250{
 251        register uintptr_t r11 __asm__("r11");
 252        register uintptr_t r3 __asm__("r3");
 253
 254        r11 = EV_HCALL_TOKEN(EV_INT_EOI);
 255        r3 = interrupt;
 256
 257        asm volatile("bl        epapr_hypercall_start"
 258                : "+r" (r11), "+r" (r3)
 259                : : EV_HCALL_CLOBBERS1
 260        );
 261
 262        return r3;
 263}
 264
 265/**
 266 * ev_byte_channel_send - send characters to a byte stream
 267 * @handle: byte stream handle
 268 * @count: (input) num of chars to send, (output) num chars sent
 269 * @buffer: pointer to a 16-byte buffer
 270 *
 271 * @buffer must be at least 16 bytes long, because all 16 bytes will be
 272 * read from memory into registers, even if count < 16.
 273 *
 274 * Returns 0 for success, or an error code.
 275 */
 276static inline unsigned int ev_byte_channel_send(unsigned int handle,
 277        unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
 278{
 279        register uintptr_t r11 __asm__("r11");
 280        register uintptr_t r3 __asm__("r3");
 281        register uintptr_t r4 __asm__("r4");
 282        register uintptr_t r5 __asm__("r5");
 283        register uintptr_t r6 __asm__("r6");
 284        register uintptr_t r7 __asm__("r7");
 285        register uintptr_t r8 __asm__("r8");
 286        const uint32_t *p = (const uint32_t *) buffer;
 287
 288        r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND);
 289        r3 = handle;
 290        r4 = *count;
 291        r5 = be32_to_cpu(p[0]);
 292        r6 = be32_to_cpu(p[1]);
 293        r7 = be32_to_cpu(p[2]);
 294        r8 = be32_to_cpu(p[3]);
 295
 296        asm volatile("bl        epapr_hypercall_start"
 297                : "+r" (r11), "+r" (r3),
 298                  "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
 299                : : EV_HCALL_CLOBBERS6
 300        );
 301
 302        *count = r4;
 303
 304        return r3;
 305}
 306
 307/**
 308 * ev_byte_channel_receive - fetch characters from a byte channel
 309 * @handle: byte channel handle
 310 * @count: (input) max num of chars to receive, (output) num chars received
 311 * @buffer: pointer to a 16-byte buffer
 312 *
 313 * The size of @buffer must be at least 16 bytes, even if you request fewer
 314 * than 16 characters, because we always write 16 bytes to @buffer.  This is
 315 * for performance reasons.
 316 *
 317 * Returns 0 for success, or an error code.
 318 */
 319static inline unsigned int ev_byte_channel_receive(unsigned int handle,
 320        unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
 321{
 322        register uintptr_t r11 __asm__("r11");
 323        register uintptr_t r3 __asm__("r3");
 324        register uintptr_t r4 __asm__("r4");
 325        register uintptr_t r5 __asm__("r5");
 326        register uintptr_t r6 __asm__("r6");
 327        register uintptr_t r7 __asm__("r7");
 328        register uintptr_t r8 __asm__("r8");
 329        uint32_t *p = (uint32_t *) buffer;
 330
 331        r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE);
 332        r3 = handle;
 333        r4 = *count;
 334
 335        asm volatile("bl        epapr_hypercall_start"
 336                : "+r" (r11), "+r" (r3), "+r" (r4),
 337                  "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
 338                : : EV_HCALL_CLOBBERS6
 339        );
 340
 341        *count = r4;
 342        p[0] = cpu_to_be32(r5);
 343        p[1] = cpu_to_be32(r6);
 344        p[2] = cpu_to_be32(r7);
 345        p[3] = cpu_to_be32(r8);
 346
 347        return r3;
 348}
 349
 350/**
 351 * ev_byte_channel_poll - returns the status of the byte channel buffers
 352 * @handle: byte channel handle
 353 * @rx_count: returned count of bytes in receive queue
 354 * @tx_count: returned count of free space in transmit queue
 355 *
 356 * This function reports the amount of data in the receive queue (i.e. the
 357 * number of bytes you can read), and the amount of free space in the transmit
 358 * queue (i.e. the number of bytes you can write).
 359 *
 360 * Returns 0 for success, or an error code.
 361 */
 362static inline unsigned int ev_byte_channel_poll(unsigned int handle,
 363        unsigned int *rx_count, unsigned int *tx_count)
 364{
 365        register uintptr_t r11 __asm__("r11");
 366        register uintptr_t r3 __asm__("r3");
 367        register uintptr_t r4 __asm__("r4");
 368        register uintptr_t r5 __asm__("r5");
 369
 370        r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
 371        r3 = handle;
 372
 373        asm volatile("bl        epapr_hypercall_start"
 374                : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
 375                : : EV_HCALL_CLOBBERS3
 376        );
 377
 378        *rx_count = r4;
 379        *tx_count = r5;
 380
 381        return r3;
 382}
 383
 384/**
 385 * ev_int_iack - acknowledge an interrupt
 386 * @handle: handle to the target interrupt controller
 387 * @vector: returned interrupt vector
 388 *
 389 * If handle is zero, the function returns the next interrupt source
 390 * number to be handled irrespective of the hierarchy or cascading
 391 * of interrupt controllers. If non-zero, specifies a handle to the
 392 * interrupt controller that is the target of the acknowledge.
 393 *
 394 * Returns 0 for success, or an error code.
 395 */
 396static inline unsigned int ev_int_iack(unsigned int handle,
 397        unsigned int *vector)
 398{
 399        register uintptr_t r11 __asm__("r11");
 400        register uintptr_t r3 __asm__("r3");
 401        register uintptr_t r4 __asm__("r4");
 402
 403        r11 = EV_HCALL_TOKEN(EV_INT_IACK);
 404        r3 = handle;
 405
 406        asm volatile("bl        epapr_hypercall_start"
 407                : "+r" (r11), "+r" (r3), "=r" (r4)
 408                : : EV_HCALL_CLOBBERS2
 409        );
 410
 411        *vector = r4;
 412
 413        return r3;
 414}
 415
 416/**
 417 * ev_doorbell_send - send a doorbell to another partition
 418 * @handle: doorbell send handle
 419 *
 420 * Returns 0 for success, or an error code.
 421 */
 422static inline unsigned int ev_doorbell_send(unsigned int handle)
 423{
 424        register uintptr_t r11 __asm__("r11");
 425        register uintptr_t r3 __asm__("r3");
 426
 427        r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
 428        r3 = handle;
 429
 430        asm volatile("bl        epapr_hypercall_start"
 431                : "+r" (r11), "+r" (r3)
 432                : : EV_HCALL_CLOBBERS1
 433        );
 434
 435        return r3;
 436}
 437
 438/**
 439 * ev_idle -- wait for next interrupt on this core
 440 *
 441 * Returns 0 for success, or an error code.
 442 */
 443static inline unsigned int ev_idle(void)
 444{
 445        register uintptr_t r11 __asm__("r11");
 446        register uintptr_t r3 __asm__("r3");
 447
 448        r11 = EV_HCALL_TOKEN(EV_IDLE);
 449
 450        asm volatile("bl        epapr_hypercall_start"
 451                : "+r" (r11), "=r" (r3)
 452                : : EV_HCALL_CLOBBERS1
 453        );
 454
 455        return r3;
 456}
 457#endif /* !__ASSEMBLY__ */
 458#endif /* _EPAPR_HCALLS_H */
 459