diff options
Diffstat (limited to 'include/asm-i386/paravirt.h')
-rw-r--r-- | include/asm-i386/paravirt.h | 248 |
1 files changed, 60 insertions, 188 deletions
diff --git a/include/asm-i386/paravirt.h b/include/asm-i386/paravirt.h index c5451923c79e..2ba18963e114 100644 --- a/include/asm-i386/paravirt.h +++ b/include/asm-i386/paravirt.h | |||
@@ -332,211 +332,81 @@ unsigned paravirt_patch_insns(void *site, unsigned len, | |||
332 | * means that all uses must be wrapped in inline functions. This also | 332 | * means that all uses must be wrapped in inline functions. This also |
333 | * makes sure the incoming and outgoing types are always correct. | 333 | * makes sure the incoming and outgoing types are always correct. |
334 | */ | 334 | */ |
335 | #define PVOP_CALL0(__rettype, __op) \ | 335 | #define __PVOP_CALL(rettype, op, pre, post, ...) \ |
336 | ({ \ | ||
337 | __rettype __ret; \ | ||
338 | if (sizeof(__rettype) > sizeof(unsigned long)) { \ | ||
339 | unsigned long long __tmp; \ | ||
340 | unsigned long __ecx; \ | ||
341 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
342 | : "=A" (__tmp), "=c" (__ecx) \ | ||
343 | : paravirt_type(__op), \ | ||
344 | paravirt_clobber(CLBR_ANY) \ | ||
345 | : "memory", "cc"); \ | ||
346 | __ret = (__rettype)__tmp; \ | ||
347 | } else { \ | ||
348 | unsigned long __tmp, __edx, __ecx; \ | ||
349 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
350 | : "=a" (__tmp), "=d" (__edx), \ | ||
351 | "=c" (__ecx) \ | ||
352 | : paravirt_type(__op), \ | ||
353 | paravirt_clobber(CLBR_ANY) \ | ||
354 | : "memory", "cc"); \ | ||
355 | __ret = (__rettype)__tmp; \ | ||
356 | } \ | ||
357 | __ret; \ | ||
358 | }) | ||
359 | #define PVOP_VCALL0(__op) \ | ||
360 | ({ \ | 336 | ({ \ |
337 | rettype __ret; \ | ||
361 | unsigned long __eax, __edx, __ecx; \ | 338 | unsigned long __eax, __edx, __ecx; \ |
362 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | 339 | if (sizeof(rettype) > sizeof(unsigned long)) { \ |
363 | : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ | 340 | asm volatile(pre \ |
364 | : paravirt_type(__op), \ | 341 | paravirt_alt(PARAVIRT_CALL) \ |
365 | paravirt_clobber(CLBR_ANY) \ | 342 | post \ |
366 | : "memory", "cc"); \ | 343 | : "=a" (__eax), "=d" (__edx), \ |
367 | }) | ||
368 | |||
369 | #define PVOP_CALL1(__rettype, __op, arg1) \ | ||
370 | ({ \ | ||
371 | __rettype __ret; \ | ||
372 | if (sizeof(__rettype) > sizeof(unsigned long)) { \ | ||
373 | unsigned long long __tmp; \ | ||
374 | unsigned long __ecx; \ | ||
375 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
376 | : "=A" (__tmp), "=c" (__ecx) \ | ||
377 | : "a" ((u32)(arg1)), \ | ||
378 | paravirt_type(__op), \ | ||
379 | paravirt_clobber(CLBR_ANY) \ | ||
380 | : "memory", "cc"); \ | ||
381 | __ret = (__rettype)__tmp; \ | ||
382 | } else { \ | ||
383 | unsigned long __tmp, __edx, __ecx; \ | ||
384 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
385 | : "=a" (__tmp), "=d" (__edx), \ | ||
386 | "=c" (__ecx) \ | ||
387 | : "0" ((u32)(arg1)), \ | ||
388 | paravirt_type(__op), \ | ||
389 | paravirt_clobber(CLBR_ANY) \ | ||
390 | : "memory", "cc"); \ | ||
391 | __ret = (__rettype)__tmp; \ | ||
392 | } \ | ||
393 | __ret; \ | ||
394 | }) | ||
395 | #define PVOP_VCALL1(__op, arg1) \ | ||
396 | ({ \ | ||
397 | unsigned long __eax, __edx, __ecx; \ | ||
398 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
399 | : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ | ||
400 | : "0" ((u32)(arg1)), \ | ||
401 | paravirt_type(__op), \ | ||
402 | paravirt_clobber(CLBR_ANY) \ | ||
403 | : "memory", "cc"); \ | ||
404 | }) | ||
405 | |||
406 | #define PVOP_CALL2(__rettype, __op, arg1, arg2) \ | ||
407 | ({ \ | ||
408 | __rettype __ret; \ | ||
409 | if (sizeof(__rettype) > sizeof(unsigned long)) { \ | ||
410 | unsigned long long __tmp; \ | ||
411 | unsigned long __ecx; \ | ||
412 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
413 | : "=A" (__tmp), "=c" (__ecx) \ | ||
414 | : "a" ((u32)(arg1)), \ | ||
415 | "d" ((u32)(arg2)), \ | ||
416 | paravirt_type(__op), \ | ||
417 | paravirt_clobber(CLBR_ANY) \ | ||
418 | : "memory", "cc"); \ | ||
419 | __ret = (__rettype)__tmp; \ | ||
420 | } else { \ | ||
421 | unsigned long __tmp, __edx, __ecx; \ | ||
422 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
423 | : "=a" (__tmp), "=d" (__edx), \ | ||
424 | "=c" (__ecx) \ | ||
425 | : "0" ((u32)(arg1)), \ | ||
426 | "1" ((u32)(arg2)), \ | ||
427 | paravirt_type(__op), \ | ||
428 | paravirt_clobber(CLBR_ANY) \ | ||
429 | : "memory", "cc"); \ | ||
430 | __ret = (__rettype)__tmp; \ | ||
431 | } \ | ||
432 | __ret; \ | ||
433 | }) | ||
434 | #define PVOP_VCALL2(__op, arg1, arg2) \ | ||
435 | ({ \ | ||
436 | unsigned long __eax, __edx, __ecx; \ | ||
437 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
438 | : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ | ||
439 | : "0" ((u32)(arg1)), \ | ||
440 | "1" ((u32)(arg2)), \ | ||
441 | paravirt_type(__op), \ | ||
442 | paravirt_clobber(CLBR_ANY) \ | ||
443 | : "memory", "cc"); \ | ||
444 | }) | ||
445 | |||
446 | #define PVOP_CALL3(__rettype, __op, arg1, arg2, arg3) \ | ||
447 | ({ \ | ||
448 | __rettype __ret; \ | ||
449 | if (sizeof(__rettype) > sizeof(unsigned long)) { \ | ||
450 | unsigned long long __tmp; \ | ||
451 | unsigned long __ecx; \ | ||
452 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
453 | : "=A" (__tmp), "=c" (__ecx) \ | ||
454 | : "a" ((u32)(arg1)), \ | ||
455 | "d" ((u32)(arg2)), \ | ||
456 | "1" ((u32)(arg3)), \ | ||
457 | paravirt_type(__op), \ | ||
458 | paravirt_clobber(CLBR_ANY) \ | ||
459 | : "memory", "cc"); \ | ||
460 | __ret = (__rettype)__tmp; \ | ||
461 | } else { \ | ||
462 | unsigned long __tmp, __edx, __ecx; \ | ||
463 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
464 | : "=a" (__tmp), "=d" (__edx), \ | ||
465 | "=c" (__ecx) \ | 344 | "=c" (__ecx) \ |
466 | : "0" ((u32)(arg1)), \ | 345 | : paravirt_type(op), \ |
467 | "1" ((u32)(arg2)), \ | 346 | paravirt_clobber(CLBR_ANY), \ |
468 | "2" ((u32)(arg3)), \ | 347 | ##__VA_ARGS__ \ |
469 | paravirt_type(__op), \ | ||
470 | paravirt_clobber(CLBR_ANY) \ | ||
471 | : "memory", "cc"); \ | 348 | : "memory", "cc"); \ |
472 | __ret = (__rettype)__tmp; \ | 349 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ |
473 | } \ | ||
474 | __ret; \ | ||
475 | }) | ||
476 | #define PVOP_VCALL3(__op, arg1, arg2, arg3) \ | ||
477 | ({ \ | ||
478 | unsigned long __eax, __edx, __ecx; \ | ||
479 | asm volatile(paravirt_alt(PARAVIRT_CALL) \ | ||
480 | : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ | ||
481 | : "0" ((u32)(arg1)), \ | ||
482 | "1" ((u32)(arg2)), \ | ||
483 | "2" ((u32)(arg3)), \ | ||
484 | paravirt_type(__op), \ | ||
485 | paravirt_clobber(CLBR_ANY) \ | ||
486 | : "memory", "cc"); \ | ||
487 | }) | ||
488 | |||
489 | #define PVOP_CALL4(__rettype, __op, arg1, arg2, arg3, arg4) \ | ||
490 | ({ \ | ||
491 | __rettype __ret; \ | ||
492 | if (sizeof(__rettype) > sizeof(unsigned long)) { \ | ||
493 | unsigned long long __tmp; \ | ||
494 | unsigned long __ecx; \ | ||
495 | asm volatile("push %[_arg4]; " \ | ||
496 | paravirt_alt(PARAVIRT_CALL) \ | ||
497 | "lea 4(%%esp),%%esp" \ | ||
498 | : "=A" (__tmp), "=c" (__ecx) \ | ||
499 | : "a" ((u32)(arg1)), \ | ||
500 | "d" ((u32)(arg2)), \ | ||
501 | "1" ((u32)(arg3)), \ | ||
502 | [_arg4] "mr" ((u32)(arg4)), \ | ||
503 | paravirt_type(__op), \ | ||
504 | paravirt_clobber(CLBR_ANY) \ | ||
505 | : "memory", "cc",); \ | ||
506 | __ret = (__rettype)__tmp; \ | ||
507 | } else { \ | 350 | } else { \ |
508 | unsigned long __tmp, __edx, __ecx; \ | 351 | asm volatile(pre \ |
509 | asm volatile("push %[_arg4]; " \ | ||
510 | paravirt_alt(PARAVIRT_CALL) \ | 352 | paravirt_alt(PARAVIRT_CALL) \ |
511 | "lea 4(%%esp),%%esp" \ | 353 | post \ |
512 | : "=a" (__tmp), "=d" (__edx), "=c" (__ecx) \ | 354 | : "=a" (__eax), "=d" (__edx), \ |
513 | : "0" ((u32)(arg1)), \ | 355 | "=c" (__ecx) \ |
514 | "1" ((u32)(arg2)), \ | 356 | : paravirt_type(op), \ |
515 | "2" ((u32)(arg3)), \ | 357 | paravirt_clobber(CLBR_ANY), \ |
516 | [_arg4]"mr" ((u32)(arg4)), \ | 358 | ##__VA_ARGS__ \ |
517 | paravirt_type(__op), \ | ||
518 | paravirt_clobber(CLBR_ANY) \ | ||
519 | : "memory", "cc"); \ | 359 | : "memory", "cc"); \ |
520 | __ret = (__rettype)__tmp; \ | 360 | __ret = (rettype)__eax; \ |
521 | } \ | 361 | } \ |
522 | __ret; \ | 362 | __ret; \ |
523 | }) | 363 | }) |
524 | #define PVOP_VCALL4(__op, arg1, arg2, arg3, arg4) \ | 364 | #define __PVOP_VCALL(op, pre, post, ...) \ |
525 | ({ \ | 365 | ({ \ |
526 | unsigned long __eax, __edx, __ecx; \ | 366 | unsigned long __eax, __edx, __ecx; \ |
527 | asm volatile("push %[_arg4]; " \ | 367 | asm volatile(pre \ |
528 | paravirt_alt(PARAVIRT_CALL) \ | 368 | paravirt_alt(PARAVIRT_CALL) \ |
529 | "lea 4(%%esp),%%esp" \ | 369 | post \ |
530 | : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ | 370 | : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ |
531 | : "0" ((u32)(arg1)), \ | 371 | : paravirt_type(op), \ |
532 | "1" ((u32)(arg2)), \ | 372 | paravirt_clobber(CLBR_ANY), \ |
533 | "2" ((u32)(arg3)), \ | 373 | ##__VA_ARGS__ \ |
534 | [_arg4]"mr" ((u32)(arg4)), \ | ||
535 | paravirt_type(__op), \ | ||
536 | paravirt_clobber(CLBR_ANY) \ | ||
537 | : "memory", "cc"); \ | 374 | : "memory", "cc"); \ |
538 | }) | 375 | }) |
539 | 376 | ||
377 | #define PVOP_CALL0(rettype, op) \ | ||
378 | __PVOP_CALL(rettype, op, "", "") | ||
379 | #define PVOP_VCALL0(op) \ | ||
380 | __PVOP_VCALL(op, "", "") | ||
381 | |||
382 | #define PVOP_CALL1(rettype, op, arg1) \ | ||
383 | __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1))) | ||
384 | #define PVOP_VCALL1(op, arg1) \ | ||
385 | __PVOP_VCALL(op, "", "", "0" ((u32)(arg1))) | ||
386 | |||
387 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ | ||
388 | __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2))) | ||
389 | #define PVOP_VCALL2(op, arg1, arg2) \ | ||
390 | __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2))) | ||
391 | |||
392 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ | ||
393 | __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), \ | ||
394 | "1"((u32)(arg2)), "2"((u32)(arg3))) | ||
395 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ | ||
396 | __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1"((u32)(arg2)), \ | ||
397 | "2"((u32)(arg3))) | ||
398 | |||
399 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | ||
400 | __PVOP_CALL(rettype, op, \ | ||
401 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | ||
402 | "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ | ||
403 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | ||
404 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ | ||
405 | __PVOP_VCALL(op, \ | ||
406 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | ||
407 | "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ | ||
408 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | ||
409 | |||
540 | static inline int paravirt_enabled(void) | 410 | static inline int paravirt_enabled(void) |
541 | { | 411 | { |
542 | return paravirt_ops.paravirt_enabled; | 412 | return paravirt_ops.paravirt_enabled; |
@@ -1162,6 +1032,8 @@ static inline unsigned long __raw_local_irq_save(void) | |||
1162 | 1032 | ||
1163 | /* Make sure as little as possible of this mess escapes. */ | 1033 | /* Make sure as little as possible of this mess escapes. */ |
1164 | #undef PARAVIRT_CALL | 1034 | #undef PARAVIRT_CALL |
1035 | #undef __PVOP_CALL | ||
1036 | #undef __PVOP_VCALL | ||
1165 | #undef PVOP_VCALL0 | 1037 | #undef PVOP_VCALL0 |
1166 | #undef PVOP_CALL0 | 1038 | #undef PVOP_CALL0 |
1167 | #undef PVOP_VCALL1 | 1039 | #undef PVOP_VCALL1 |