0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 #ifndef _EPAPR_HCALLS_H
0051 #define _EPAPR_HCALLS_H
0052
0053 #include <uapi/asm/epapr_hcalls.h>
0054
0055 #ifndef __ASSEMBLY__
0056 #include <linux/types.h>
0057 #include <linux/errno.h>
0058 #include <asm/byteorder.h>
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 #define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc", "memory"
0095
0096 #define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS
0097 #define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10"
0098 #define EV_HCALL_CLOBBERS6 EV_HCALL_CLOBBERS7, "r9"
0099 #define EV_HCALL_CLOBBERS5 EV_HCALL_CLOBBERS6, "r8"
0100 #define EV_HCALL_CLOBBERS4 EV_HCALL_CLOBBERS5, "r7"
0101 #define EV_HCALL_CLOBBERS3 EV_HCALL_CLOBBERS4, "r6"
0102 #define EV_HCALL_CLOBBERS2 EV_HCALL_CLOBBERS3, "r5"
0103 #define EV_HCALL_CLOBBERS1 EV_HCALL_CLOBBERS2, "r4"
0104
0105 extern bool epapr_paravirt_enabled;
0106 extern u32 epapr_hypercall_start[];
0107
0108 #ifdef CONFIG_EPAPR_PARAVIRT
0109 int __init epapr_paravirt_early_init(void);
0110 #else
0111 static inline int epapr_paravirt_early_init(void) { return 0; }
0112 #endif
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 static inline unsigned int ev_int_set_config(unsigned int interrupt,
0137 uint32_t config, unsigned int priority, uint32_t destination)
0138 {
0139 register uintptr_t r11 __asm__("r11");
0140 register uintptr_t r3 __asm__("r3");
0141 register uintptr_t r4 __asm__("r4");
0142 register uintptr_t r5 __asm__("r5");
0143 register uintptr_t r6 __asm__("r6");
0144
0145 r11 = EV_HCALL_TOKEN(EV_INT_SET_CONFIG);
0146 r3 = interrupt;
0147 r4 = config;
0148 r5 = priority;
0149 r6 = destination;
0150
0151 asm volatile("bl epapr_hypercall_start"
0152 : "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
0153 : : EV_HCALL_CLOBBERS4
0154 );
0155
0156 return r3;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168 static inline unsigned int ev_int_get_config(unsigned int interrupt,
0169 uint32_t *config, unsigned int *priority, uint32_t *destination)
0170 {
0171 register uintptr_t r11 __asm__("r11");
0172 register uintptr_t r3 __asm__("r3");
0173 register uintptr_t r4 __asm__("r4");
0174 register uintptr_t r5 __asm__("r5");
0175 register uintptr_t r6 __asm__("r6");
0176
0177 r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
0178 r3 = interrupt;
0179
0180 asm volatile("bl epapr_hypercall_start"
0181 : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
0182 : : EV_HCALL_CLOBBERS4
0183 );
0184
0185 *config = r4;
0186 *priority = r5;
0187 *destination = r6;
0188
0189 return r3;
0190 }
0191
0192
0193
0194
0195
0196
0197
0198
0199 static inline unsigned int ev_int_set_mask(unsigned int interrupt,
0200 unsigned int mask)
0201 {
0202 register uintptr_t r11 __asm__("r11");
0203 register uintptr_t r3 __asm__("r3");
0204 register uintptr_t r4 __asm__("r4");
0205
0206 r11 = EV_HCALL_TOKEN(EV_INT_SET_MASK);
0207 r3 = interrupt;
0208 r4 = mask;
0209
0210 asm volatile("bl epapr_hypercall_start"
0211 : "+r" (r11), "+r" (r3), "+r" (r4)
0212 : : EV_HCALL_CLOBBERS2
0213 );
0214
0215 return r3;
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225 static inline unsigned int ev_int_get_mask(unsigned int interrupt,
0226 unsigned int *mask)
0227 {
0228 register uintptr_t r11 __asm__("r11");
0229 register uintptr_t r3 __asm__("r3");
0230 register uintptr_t r4 __asm__("r4");
0231
0232 r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
0233 r3 = interrupt;
0234
0235 asm volatile("bl epapr_hypercall_start"
0236 : "+r" (r11), "+r" (r3), "=r" (r4)
0237 : : EV_HCALL_CLOBBERS2
0238 );
0239
0240 *mask = r4;
0241
0242 return r3;
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255 static inline unsigned int ev_int_eoi(unsigned int interrupt)
0256 {
0257 register uintptr_t r11 __asm__("r11");
0258 register uintptr_t r3 __asm__("r3");
0259
0260 r11 = EV_HCALL_TOKEN(EV_INT_EOI);
0261 r3 = interrupt;
0262
0263 asm volatile("bl epapr_hypercall_start"
0264 : "+r" (r11), "+r" (r3)
0265 : : EV_HCALL_CLOBBERS1
0266 );
0267
0268 return r3;
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282 static inline unsigned int ev_byte_channel_send(unsigned int handle,
0283 unsigned int *count, const char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
0284 {
0285 register uintptr_t r11 __asm__("r11");
0286 register uintptr_t r3 __asm__("r3");
0287 register uintptr_t r4 __asm__("r4");
0288 register uintptr_t r5 __asm__("r5");
0289 register uintptr_t r6 __asm__("r6");
0290 register uintptr_t r7 __asm__("r7");
0291 register uintptr_t r8 __asm__("r8");
0292 const uint32_t *p = (const uint32_t *) buffer;
0293
0294 r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_SEND);
0295 r3 = handle;
0296 r4 = *count;
0297 r5 = be32_to_cpu(p[0]);
0298 r6 = be32_to_cpu(p[1]);
0299 r7 = be32_to_cpu(p[2]);
0300 r8 = be32_to_cpu(p[3]);
0301
0302 asm volatile("bl epapr_hypercall_start"
0303 : "+r" (r11), "+r" (r3),
0304 "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
0305 : : EV_HCALL_CLOBBERS6
0306 );
0307
0308 *count = r4;
0309
0310 return r3;
0311 }
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 static inline unsigned int ev_byte_channel_receive(unsigned int handle,
0326 unsigned int *count, char buffer[EV_BYTE_CHANNEL_MAX_BYTES])
0327 {
0328 register uintptr_t r11 __asm__("r11");
0329 register uintptr_t r3 __asm__("r3");
0330 register uintptr_t r4 __asm__("r4");
0331 register uintptr_t r5 __asm__("r5");
0332 register uintptr_t r6 __asm__("r6");
0333 register uintptr_t r7 __asm__("r7");
0334 register uintptr_t r8 __asm__("r8");
0335 uint32_t *p = (uint32_t *) buffer;
0336
0337 r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_RECEIVE);
0338 r3 = handle;
0339 r4 = *count;
0340
0341 asm volatile("bl epapr_hypercall_start"
0342 : "+r" (r11), "+r" (r3), "+r" (r4),
0343 "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
0344 : : EV_HCALL_CLOBBERS6
0345 );
0346
0347 *count = r4;
0348 p[0] = cpu_to_be32(r5);
0349 p[1] = cpu_to_be32(r6);
0350 p[2] = cpu_to_be32(r7);
0351 p[3] = cpu_to_be32(r8);
0352
0353 return r3;
0354 }
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368 static inline unsigned int ev_byte_channel_poll(unsigned int handle,
0369 unsigned int *rx_count, unsigned int *tx_count)
0370 {
0371 register uintptr_t r11 __asm__("r11");
0372 register uintptr_t r3 __asm__("r3");
0373 register uintptr_t r4 __asm__("r4");
0374 register uintptr_t r5 __asm__("r5");
0375
0376 r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
0377 r3 = handle;
0378
0379 asm volatile("bl epapr_hypercall_start"
0380 : "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
0381 : : EV_HCALL_CLOBBERS3
0382 );
0383
0384 *rx_count = r4;
0385 *tx_count = r5;
0386
0387 return r3;
0388 }
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402 static inline unsigned int ev_int_iack(unsigned int handle,
0403 unsigned int *vector)
0404 {
0405 register uintptr_t r11 __asm__("r11");
0406 register uintptr_t r3 __asm__("r3");
0407 register uintptr_t r4 __asm__("r4");
0408
0409 r11 = EV_HCALL_TOKEN(EV_INT_IACK);
0410 r3 = handle;
0411
0412 asm volatile("bl epapr_hypercall_start"
0413 : "+r" (r11), "+r" (r3), "=r" (r4)
0414 : : EV_HCALL_CLOBBERS2
0415 );
0416
0417 *vector = r4;
0418
0419 return r3;
0420 }
0421
0422
0423
0424
0425
0426
0427
0428 static inline unsigned int ev_doorbell_send(unsigned int handle)
0429 {
0430 register uintptr_t r11 __asm__("r11");
0431 register uintptr_t r3 __asm__("r3");
0432
0433 r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
0434 r3 = handle;
0435
0436 asm volatile("bl epapr_hypercall_start"
0437 : "+r" (r11), "+r" (r3)
0438 : : EV_HCALL_CLOBBERS1
0439 );
0440
0441 return r3;
0442 }
0443
0444
0445
0446
0447
0448
0449 static inline unsigned int ev_idle(void)
0450 {
0451 register uintptr_t r11 __asm__("r11");
0452 register uintptr_t r3 __asm__("r3");
0453
0454 r11 = EV_HCALL_TOKEN(EV_IDLE);
0455
0456 asm volatile("bl epapr_hypercall_start"
0457 : "+r" (r11), "=r" (r3)
0458 : : EV_HCALL_CLOBBERS1
0459 );
0460
0461 return r3;
0462 }
0463
0464 #ifdef CONFIG_EPAPR_PARAVIRT
0465 static inline unsigned long epapr_hypercall(unsigned long *in,
0466 unsigned long *out,
0467 unsigned long nr)
0468 {
0469 register unsigned long r0 asm("r0");
0470 register unsigned long r3 asm("r3") = in[0];
0471 register unsigned long r4 asm("r4") = in[1];
0472 register unsigned long r5 asm("r5") = in[2];
0473 register unsigned long r6 asm("r6") = in[3];
0474 register unsigned long r7 asm("r7") = in[4];
0475 register unsigned long r8 asm("r8") = in[5];
0476 register unsigned long r9 asm("r9") = in[6];
0477 register unsigned long r10 asm("r10") = in[7];
0478 register unsigned long r11 asm("r11") = nr;
0479 register unsigned long r12 asm("r12");
0480
0481 asm volatile("bl epapr_hypercall_start"
0482 : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6),
0483 "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11),
0484 "=r"(r12)
0485 : "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "r"(r8),
0486 "r"(r9), "r"(r10), "r"(r11)
0487 : "memory", "cc", "xer", "ctr", "lr");
0488
0489 out[0] = r4;
0490 out[1] = r5;
0491 out[2] = r6;
0492 out[3] = r7;
0493 out[4] = r8;
0494 out[5] = r9;
0495 out[6] = r10;
0496 out[7] = r11;
0497
0498 return r3;
0499 }
0500 #else
0501 static unsigned long epapr_hypercall(unsigned long *in,
0502 unsigned long *out,
0503 unsigned long nr)
0504 {
0505 return EV_UNIMPLEMENTED;
0506 }
0507 #endif
0508
0509 static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2)
0510 {
0511 unsigned long in[8] = {0};
0512 unsigned long out[8];
0513 unsigned long r;
0514
0515 r = epapr_hypercall(in, out, nr);
0516 *r2 = out[0];
0517
0518 return r;
0519 }
0520
0521 static inline long epapr_hypercall0(unsigned int nr)
0522 {
0523 unsigned long in[8] = {0};
0524 unsigned long out[8];
0525
0526 return epapr_hypercall(in, out, nr);
0527 }
0528
0529 static inline long epapr_hypercall1(unsigned int nr, unsigned long p1)
0530 {
0531 unsigned long in[8] = {0};
0532 unsigned long out[8];
0533
0534 in[0] = p1;
0535 return epapr_hypercall(in, out, nr);
0536 }
0537
0538 static inline long epapr_hypercall2(unsigned int nr, unsigned long p1,
0539 unsigned long p2)
0540 {
0541 unsigned long in[8] = {0};
0542 unsigned long out[8];
0543
0544 in[0] = p1;
0545 in[1] = p2;
0546 return epapr_hypercall(in, out, nr);
0547 }
0548
0549 static inline long epapr_hypercall3(unsigned int nr, unsigned long p1,
0550 unsigned long p2, unsigned long p3)
0551 {
0552 unsigned long in[8] = {0};
0553 unsigned long out[8];
0554
0555 in[0] = p1;
0556 in[1] = p2;
0557 in[2] = p3;
0558 return epapr_hypercall(in, out, nr);
0559 }
0560
0561 static inline long epapr_hypercall4(unsigned int nr, unsigned long p1,
0562 unsigned long p2, unsigned long p3,
0563 unsigned long p4)
0564 {
0565 unsigned long in[8] = {0};
0566 unsigned long out[8];
0567
0568 in[0] = p1;
0569 in[1] = p2;
0570 in[2] = p3;
0571 in[3] = p4;
0572 return epapr_hypercall(in, out, nr);
0573 }
0574 #endif
0575 #endif