diff --git a/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S index 9ae755b067..d9b991b703 100644 --- a/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S +++ b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S @@ -23,8 +23,47 @@ ASM_GLOBAL ASM_PFX(JumpToKernel) # ); #------------------------------------------------------------------------------ ASM_PFX(JumpToKernel): - movq %rdx, %rsi - addq $0x200, %rcx - callq %rcx - ret + + // Set up for executing kernel. BP in %esi, entry point on the stack + // (64-bit when the 'ret' will use it as 32-bit, but we're little-endian) + movq %rdx, %rsi + pushq %rcx + + // Jump into the compatibility mode CS + pushq $0x10 + leaq 1f, %rax + pushq %rax + retfq + +1: // Now in compatibility mode +.code32 + movl $0x18, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + // Disable paging + movl %cr0, %eax + btcl $31, %eax + movl %eax, %cr0 + + // Disable long mode in EFER + movl $0x0c0000080, %ecx + rdmsr + btcl $8, %eax + wrmsr + + // Disable PAE + movl %cr4, %eax + btcl $5, %eax + movl %eax, %cr4 + + // Zero registers and 'return' to kernel + xorl %ebp, %ebp + xorl %edi, %edi + xorl %ebx, %ebx + ret +.code64 diff --git a/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm index ed53321c23..4df9c723aa 100644 --- a/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm +++ b/OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm @@ -24,10 +24,47 @@ ;------------------------------------------------------------------------------ JumpToKernel PROC - mov rsi, rdx - add rcx, 200h - call rcx - ret + ; Set up for executing kernel. BP in %esi, entry point on the stack + ; (64-bit when the 'ret' will use it as 32-bit, but we're little-endian) + mov rsi, rdx + push rcx + + ; Jump into the compatibility mode CS + push 10h + lea rax, @F + push rax + DB 048h, 0cbh ; retfq + +@@: + ; Now in compatibility mode. + + DB 0b8h, 018h, 000h, 000h, 000h ; movl $0x18, %eax + DB 08eh, 0d8h ; movl %eax, %ds + DB 08eh, 0c0h ; movl %eax, %es + DB 08eh, 0e0h ; movl %eax, %fs + DB 08eh, 0e8h ; movl %eax, %gs + DB 08eh, 0d0h ; movl %eax, %ss + + ; Disable paging + DB 00fh, 020h, 0c0h ; movl %cr0, %eax + DB 00fh, 0bah, 0f8h, 01fh ; btcl $31, %eax + DB 00fh, 022h, 0c0h ; movl %eax, %cr0 + + ; Disable long mode in EFER + DB 0b9h, 080h, 000h, 000h, 0c0h ; movl $0x0c0000080, %ecx + DB 00fh, 032h ; rdmsr + DB 00fh, 0bah, 0f8h, 008h ; btcl $8, %eax + DB 00fh, 030h ; wrmsr + + ; Disable PAE + DB 00fh, 020h, 0e0h ; movl %cr4, %eax + DB 00fh, 0bah, 0f8h, 005h ; btcl $5, %eax + DB 00fh, 022h, 0e0h ; movl %eax, %cr4 + + DB 031h, 0edh ; xor %ebp, %ebp + DB 031h, 0ffh ; xor %edi, %edi + DB 031h, 0dbh ; xor %ebx, %ebx + DB 0c3h ; ret JumpToKernel ENDP