.. | .. |
---|
454 | 454 | /* Save the trampoline address in RCX */ |
---|
455 | 455 | movq %rax, %rcx |
---|
456 | 456 | |
---|
| 457 | + /* Set up 32-bit addressable stack */ |
---|
| 458 | + leaq TRAMPOLINE_32BIT_STACK_END(%rcx), %rsp |
---|
| 459 | + |
---|
457 | 460 | /* |
---|
458 | | - * Load the address of trampoline_return() into RDI. |
---|
459 | | - * It will be used by the trampoline to return to the main code. |
---|
| 461 | + * Preserve live 64-bit registers on the stack: this is necessary |
---|
| 462 | + * because the architecture does not guarantee that GPRs will retain |
---|
| 463 | + * their full 64-bit values across a 32-bit mode switch. |
---|
| 464 | + */ |
---|
| 465 | + pushq %rbp |
---|
| 466 | + pushq %rbx |
---|
| 467 | + pushq %rsi |
---|
| 468 | + |
---|
| 469 | + /* |
---|
| 470 | + * Push the 64-bit address of trampoline_return() onto the new stack. |
---|
| 471 | + * It will be used by the trampoline to return to the main code. Due to |
---|
| 472 | + * the 32-bit mode switch, it cannot be kept it in a register either. |
---|
460 | 473 | */ |
---|
461 | 474 | leaq trampoline_return(%rip), %rdi |
---|
| 475 | + pushq %rdi |
---|
462 | 476 | |
---|
463 | 477 | /* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */ |
---|
464 | 478 | pushq $__KERNEL32_CS |
---|
.. | .. |
---|
466 | 480 | pushq %rax |
---|
467 | 481 | lretq |
---|
468 | 482 | trampoline_return: |
---|
| 483 | + /* Restore live 64-bit registers */ |
---|
| 484 | + popq %rsi |
---|
| 485 | + popq %rbx |
---|
| 486 | + popq %rbp |
---|
| 487 | + |
---|
469 | 488 | /* Restore the stack, the 32-bit trampoline uses its own stack */ |
---|
470 | 489 | leaq rva(boot_stack_end)(%rbx), %rsp |
---|
471 | 490 | |
---|
.. | .. |
---|
586 | 605 | /* |
---|
587 | 606 | * This is the 32-bit trampoline that will be copied over to low memory. |
---|
588 | 607 | * |
---|
589 | | - * RDI contains the return address (might be above 4G). |
---|
| 608 | + * Return address is at the top of the stack (might be above 4G). |
---|
590 | 609 | * ECX contains the base address of the trampoline memory. |
---|
591 | 610 | * Non zero RDX means trampoline needs to enable 5-level paging. |
---|
592 | 611 | */ |
---|
.. | .. |
---|
595 | 614 | movl $__KERNEL_DS, %eax |
---|
596 | 615 | movl %eax, %ds |
---|
597 | 616 | movl %eax, %ss |
---|
598 | | - |
---|
599 | | - /* Set up new stack */ |
---|
600 | | - leal TRAMPOLINE_32BIT_STACK_END(%ecx), %esp |
---|
601 | 617 | |
---|
602 | 618 | /* Disable paging */ |
---|
603 | 619 | movl %cr0, %eax |
---|
.. | .. |
---|
658 | 674 | .code64 |
---|
659 | 675 | SYM_FUNC_START_LOCAL_NOALIGN(.Lpaging_enabled) |
---|
660 | 676 | /* Return from the trampoline */ |
---|
661 | | - jmp *%rdi |
---|
| 677 | + retq |
---|
662 | 678 | SYM_FUNC_END(.Lpaging_enabled) |
---|
663 | 679 | |
---|
664 | 680 | /* |
---|