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