PageRenderTime 50ms CodeModel.GetById 18ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/powerpc/include/asm/epapr_hcalls.h

http://github.com/mirrors/linux
C Header | 575 lines | 306 code | 77 blank | 192 comment | 0 complexity | 78334f06bf278cc64ff10f93ffdc161d MD5 | raw file
  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#ifdef CONFIG_EPAPR_PARAVIRT
109int __init epapr_paravirt_early_init(void);
110#else
111static 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 */
136static 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 */
168static 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 */
199static 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 */
225static 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 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 */
255static 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 */
282static 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 */
325static 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 */
368static 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 */
402static 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 */
428static 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 */
449static 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
465static 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
501static unsigned long epapr_hypercall(unsigned long *in,
502				   unsigned long *out,
503				   unsigned long nr)
504{
505	return EV_UNIMPLEMENTED;
506}
507#endif
508
509static 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
521static 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
529static 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
538static 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
549static 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
561static 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 */