summaryrefslogtreecommitdiff
path: root/arch/x86/lib
diff options
context:
space:
mode:
authorJian Luo <jian.luo4@boschrexroth.de>2015-07-06 16:42:06 +0800
committerSimon Glass <sjg@chromium.org>2015-07-14 18:03:18 -0600
commit7b5c3498901712dbd6503bf81c03bb6ea8e3b516 (patch)
treec7024dbf67f06786b3010a1ffae0be738e689fad /arch/x86/lib
parentb018a8c71602d53d5d5ebac859f33327b97e9cec (diff)
downloadu-boot-imx-7b5c3498901712dbd6503bf81c03bb6ea8e3b516.zip
u-boot-imx-7b5c3498901712dbd6503bf81c03bb6ea8e3b516.tar.gz
u-boot-imx-7b5c3498901712dbd6503bf81c03bb6ea8e3b516.tar.bz2
x86: bios: Synchronize stack between real and protected mode
PCI option rom may use different SS during its execution, so it is not safe to assume esp pointed to the same location in the protected mode. Signed-off-by: Jian Luo <jian.luo4@boschrexroth.de> Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Acked-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch/x86/lib')
-rw-r--r--arch/x86/lib/bios_asm.S23
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/x86/lib/bios_asm.S b/arch/x86/lib/bios_asm.S
index 4faa70e..9dbf969 100644
--- a/arch/x86/lib/bios_asm.S
+++ b/arch/x86/lib/bios_asm.S
@@ -246,6 +246,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 +261,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 +296,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