diff options
author | Glauber de Oliveira Costa <gcosta@redhat.com> | 2008-01-30 07:32:05 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:32:05 -0500 |
commit | a4746364da0c7caa155cc945a5c10312e7925b46 (patch) | |
tree | 0ebcd0f8457d607699bfea555bf5a30ddcc1cf5e /include | |
parent | b1df07bd6674a84fbd9248759dc3fa3ff5c78e5b (diff) |
x86: adjust PVOP_CALL/VCALL macros for 64-bit
This patch adjust the PVOP_VCALL and PVOP_CALL macros to
work with x86_64. It has a different calling convention, and
we use auxiliary macros to account for both calling conventions
as cleanly as possible
Comments are adjusted accordingly.
Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-x86/paravirt.h | 87 |
1 files changed, 65 insertions, 22 deletions
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h index 24406703007f..bef932772661 100644 --- a/include/asm-x86/paravirt.h +++ b/include/asm-x86/paravirt.h | |||
@@ -320,7 +320,7 @@ int paravirt_disable_iospace(void); | |||
320 | * runtime. | 320 | * runtime. |
321 | * | 321 | * |
322 | * Normally, a call to a pv_op function is a simple indirect call: | 322 | * Normally, a call to a pv_op function is a simple indirect call: |
323 | * (paravirt_ops.operations)(args...). | 323 | * (pv_op_struct.operations)(args...). |
324 | * | 324 | * |
325 | * Unfortunately, this is a relatively slow operation for modern CPUs, | 325 | * Unfortunately, this is a relatively slow operation for modern CPUs, |
326 | * because it cannot necessarily determine what the destination | 326 | * because it cannot necessarily determine what the destination |
@@ -330,11 +330,17 @@ int paravirt_disable_iospace(void); | |||
330 | * calls are essentially free, because the call and return addresses | 330 | * calls are essentially free, because the call and return addresses |
331 | * are completely predictable.) | 331 | * are completely predictable.) |
332 | * | 332 | * |
333 | * These macros rely on the standard gcc "regparm(3)" calling | 333 | * For i386, these macros rely on the standard gcc "regparm(3)" calling |
334 | * convention, in which the first three arguments are placed in %eax, | 334 | * convention, in which the first three arguments are placed in %eax, |
335 | * %edx, %ecx (in that order), and the remaining arguments are placed | 335 | * %edx, %ecx (in that order), and the remaining arguments are placed |
336 | * on the stack. All caller-save registers (eax,edx,ecx) are expected | 336 | * on the stack. All caller-save registers (eax,edx,ecx) are expected |
337 | * to be modified (either clobbered or used for return values). | 337 | * to be modified (either clobbered or used for return values). |
338 | * X86_64, on the other hand, already specifies a register-based calling | ||
339 | * conventions, returning at %rax, with parameteres going on %rdi, %rsi, | ||
340 | * %rdx, and %rcx. Note that for this reason, x86_64 does not need any | ||
341 | * special handling for dealing with 4 arguments, unlike i386. | ||
342 | * However, x86_64 also have to clobber all caller saved registers, which | ||
343 | * unfortunately, are quite a bit (r8 - r11) | ||
338 | * | 344 | * |
339 | * The call instruction itself is marked by placing its start address | 345 | * The call instruction itself is marked by placing its start address |
340 | * and size into the .parainstructions section, so that | 346 | * and size into the .parainstructions section, so that |
@@ -357,10 +363,12 @@ int paravirt_disable_iospace(void); | |||
357 | * the return type. The macro then uses sizeof() on that type to | 363 | * the return type. The macro then uses sizeof() on that type to |
358 | * determine whether its a 32 or 64 bit value, and places the return | 364 | * determine whether its a 32 or 64 bit value, and places the return |
359 | * in the right register(s) (just %eax for 32-bit, and %edx:%eax for | 365 | * in the right register(s) (just %eax for 32-bit, and %edx:%eax for |
360 | * 64-bit). | 366 | * 64-bit). For x86_64 machines, it just returns at %rax regardless of |
367 | * the return value size. | ||
361 | * | 368 | * |
362 | * 64-bit arguments are passed as a pair of adjacent 32-bit arguments | 369 | * 64-bit arguments are passed as a pair of adjacent 32-bit arguments |
363 | * in low,high order. | 370 | * i386 also passes 64-bit arguments as a pair of adjacent 32-bit arguments |
371 | * in low,high order | ||
364 | * | 372 | * |
365 | * Small structures are passed and returned in registers. The macro | 373 | * Small structures are passed and returned in registers. The macro |
366 | * calling convention can't directly deal with this, so the wrapper | 374 | * calling convention can't directly deal with this, so the wrapper |
@@ -370,46 +378,67 @@ int paravirt_disable_iospace(void); | |||
370 | * means that all uses must be wrapped in inline functions. This also | 378 | * means that all uses must be wrapped in inline functions. This also |
371 | * makes sure the incoming and outgoing types are always correct. | 379 | * makes sure the incoming and outgoing types are always correct. |
372 | */ | 380 | */ |
381 | #ifdef CONFIG_X86_32 | ||
382 | #define PVOP_VCALL_ARGS unsigned long __eax, __edx, __ecx | ||
383 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS | ||
384 | #define PVOP_VCALL_CLOBBERS "=a" (__eax), "=d" (__edx), \ | ||
385 | "=c" (__ecx) | ||
386 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS | ||
387 | #define EXTRA_CLOBBERS | ||
388 | #define VEXTRA_CLOBBERS | ||
389 | #else | ||
390 | #define PVOP_VCALL_ARGS unsigned long __edi, __esi, __edx, __ecx | ||
391 | #define PVOP_CALL_ARGS PVOP_VCALL_ARGS, __eax | ||
392 | #define PVOP_VCALL_CLOBBERS "=D" (__edi), \ | ||
393 | "=S" (__esi), "=d" (__edx), \ | ||
394 | "=c" (__ecx) | ||
395 | |||
396 | #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) | ||
397 | |||
398 | #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" | ||
399 | #define VEXTRA_CLOBBERS , "rax", "r8", "r9", "r10", "r11" | ||
400 | #endif | ||
401 | |||
373 | #define __PVOP_CALL(rettype, op, pre, post, ...) \ | 402 | #define __PVOP_CALL(rettype, op, pre, post, ...) \ |
374 | ({ \ | 403 | ({ \ |
375 | rettype __ret; \ | 404 | rettype __ret; \ |
376 | unsigned long __eax, __edx, __ecx; \ | 405 | PVOP_CALL_ARGS; \ |
406 | /* This is 32-bit specific, but is okay in 64-bit */ \ | ||
407 | /* since this condition will never hold */ \ | ||
377 | if (sizeof(rettype) > sizeof(unsigned long)) { \ | 408 | if (sizeof(rettype) > sizeof(unsigned long)) { \ |
378 | asm volatile(pre \ | 409 | asm volatile(pre \ |
379 | paravirt_alt(PARAVIRT_CALL) \ | 410 | paravirt_alt(PARAVIRT_CALL) \ |
380 | post \ | 411 | post \ |
381 | : "=a" (__eax), "=d" (__edx), \ | 412 | : PVOP_CALL_CLOBBERS \ |
382 | "=c" (__ecx) \ | ||
383 | : paravirt_type(op), \ | 413 | : paravirt_type(op), \ |
384 | paravirt_clobber(CLBR_ANY), \ | 414 | paravirt_clobber(CLBR_ANY), \ |
385 | ##__VA_ARGS__ \ | 415 | ##__VA_ARGS__ \ |
386 | : "memory", "cc"); \ | 416 | : "memory", "cc" EXTRA_CLOBBERS); \ |
387 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ | 417 | __ret = (rettype)((((u64)__edx) << 32) | __eax); \ |
388 | } else { \ | 418 | } else { \ |
389 | asm volatile(pre \ | 419 | asm volatile(pre \ |
390 | paravirt_alt(PARAVIRT_CALL) \ | 420 | paravirt_alt(PARAVIRT_CALL) \ |
391 | post \ | 421 | post \ |
392 | : "=a" (__eax), "=d" (__edx), \ | 422 | : PVOP_CALL_CLOBBERS \ |
393 | "=c" (__ecx) \ | ||
394 | : paravirt_type(op), \ | 423 | : paravirt_type(op), \ |
395 | paravirt_clobber(CLBR_ANY), \ | 424 | paravirt_clobber(CLBR_ANY), \ |
396 | ##__VA_ARGS__ \ | 425 | ##__VA_ARGS__ \ |
397 | : "memory", "cc"); \ | 426 | : "memory", "cc" EXTRA_CLOBBERS); \ |
398 | __ret = (rettype)__eax; \ | 427 | __ret = (rettype)__eax; \ |
399 | } \ | 428 | } \ |
400 | __ret; \ | 429 | __ret; \ |
401 | }) | 430 | }) |
402 | #define __PVOP_VCALL(op, pre, post, ...) \ | 431 | #define __PVOP_VCALL(op, pre, post, ...) \ |
403 | ({ \ | 432 | ({ \ |
404 | unsigned long __eax, __edx, __ecx; \ | 433 | PVOP_VCALL_ARGS; \ |
405 | asm volatile(pre \ | 434 | asm volatile(pre \ |
406 | paravirt_alt(PARAVIRT_CALL) \ | 435 | paravirt_alt(PARAVIRT_CALL) \ |
407 | post \ | 436 | post \ |
408 | : "=a" (__eax), "=d" (__edx), "=c" (__ecx) \ | 437 | : PVOP_VCALL_CLOBBERS \ |
409 | : paravirt_type(op), \ | 438 | : paravirt_type(op), \ |
410 | paravirt_clobber(CLBR_ANY), \ | 439 | paravirt_clobber(CLBR_ANY), \ |
411 | ##__VA_ARGS__ \ | 440 | ##__VA_ARGS__ \ |
412 | : "memory", "cc"); \ | 441 | : "memory", "cc" VEXTRA_CLOBBERS); \ |
413 | }) | 442 | }) |
414 | 443 | ||
415 | #define PVOP_CALL0(rettype, op) \ | 444 | #define PVOP_CALL0(rettype, op) \ |
@@ -418,22 +447,26 @@ int paravirt_disable_iospace(void); | |||
418 | __PVOP_VCALL(op, "", "") | 447 | __PVOP_VCALL(op, "", "") |
419 | 448 | ||
420 | #define PVOP_CALL1(rettype, op, arg1) \ | 449 | #define PVOP_CALL1(rettype, op, arg1) \ |
421 | __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1))) | 450 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1))) |
422 | #define PVOP_VCALL1(op, arg1) \ | 451 | #define PVOP_VCALL1(op, arg1) \ |
423 | __PVOP_VCALL(op, "", "", "0" ((u32)(arg1))) | 452 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1))) |
424 | 453 | ||
425 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ | 454 | #define PVOP_CALL2(rettype, op, arg1, arg2) \ |
426 | __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2))) | 455 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ |
456 | "1" ((unsigned long)(arg2))) | ||
427 | #define PVOP_VCALL2(op, arg1, arg2) \ | 457 | #define PVOP_VCALL2(op, arg1, arg2) \ |
428 | __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1" ((u32)(arg2))) | 458 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ |
459 | "1" ((unsigned long)(arg2))) | ||
429 | 460 | ||
430 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ | 461 | #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ |
431 | __PVOP_CALL(rettype, op, "", "", "0" ((u32)(arg1)), \ | 462 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ |
432 | "1"((u32)(arg2)), "2"((u32)(arg3))) | 463 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) |
433 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ | 464 | #define PVOP_VCALL3(op, arg1, arg2, arg3) \ |
434 | __PVOP_VCALL(op, "", "", "0" ((u32)(arg1)), "1"((u32)(arg2)), \ | 465 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ |
435 | "2"((u32)(arg3))) | 466 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3))) |
436 | 467 | ||
468 | /* This is the only difference in x86_64. We can make it much simpler */ | ||
469 | #ifdef CONFIG_X86_32 | ||
437 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | 470 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ |
438 | __PVOP_CALL(rettype, op, \ | 471 | __PVOP_CALL(rettype, op, \ |
439 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | 472 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ |
@@ -444,6 +477,16 @@ int paravirt_disable_iospace(void); | |||
444 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ | 477 | "push %[_arg4];", "lea 4(%%esp),%%esp;", \ |
445 | "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ | 478 | "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ |
446 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) | 479 | "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) |
480 | #else | ||
481 | #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ | ||
482 | __PVOP_CALL(rettype, op, "", "", "0" ((unsigned long)(arg1)), \ | ||
483 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ | ||
484 | "3"((unsigned long)(arg4))) | ||
485 | #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ | ||
486 | __PVOP_VCALL(op, "", "", "0" ((unsigned long)(arg1)), \ | ||
487 | "1"((unsigned long)(arg2)), "2"((unsigned long)(arg3)), \ | ||
488 | "3"((unsigned long)(arg4))) | ||
489 | #endif | ||
447 | 490 | ||
448 | static inline int paravirt_enabled(void) | 491 | static inline int paravirt_enabled(void) |
449 | { | 492 | { |