SPDX: Convert all of our single license tags to Linux Kernel style
[oweals/u-boot.git] / arch / x86 / lib / bios_asm.S
index 4faa70e314dc540c69a5754beb00e4ed7e813d74..62dc5652dbab4944a3f000de5f821b411d672fdc 100644 (file)
@@ -1,9 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * From coreboot x86_asm.S, cleaned up substantially
  *
  * Copyright (C) 2009-2010 coresystems GmbH
- *
- * SPDX-License-Identifier:    GPL-2.0
  */
 
 #include <asm/processor.h>
@@ -246,6 +245,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
        push    %fs
        push    %gs
 
+       /* Save real mode SS */
+       movw    %ss, %cs:__realmode_ss
+
        /* Clear DF to not break ABI assumptions */
        cld
 
@@ -258,12 +260,29 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
 
        enter_protected_mode
 
+       /*
+        * Now we are in protected mode. We need compute the right ESP based
+        * on saved real mode SS otherwise interrupt_handler() won't get
+        * correct parameters from the stack.
+        */
+       movzwl  %cs:__realmode_ss, %ecx
+       shll    $4, %ecx
+       addl    %ecx, %esp
+
        /* Call the C interrupt handler */
        movl    $interrupt_handler, %eax
        call    *%eax
 
+       /* Restore real mode ESP based on saved SS */
+       movzwl  %cs:__realmode_ss, %ecx
+       shll    $4, %ecx
+       subl    %ecx, %esp
+
        enter_real_mode
 
+       /* Restore real mode SS */
+       movw    %cs:__realmode_ss, %ss
+
        /*
         * Restore all registers, including those manipulated by the C
         * handler
@@ -276,6 +295,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
        popal
        iret
 
+__realmode_ss = PTR_TO_REAL_MODE(.)
+       .word   0
+
        .globl asm_realmode_code_size
 asm_realmode_code_size:
        .long  . - asm_realmode_code