Hi Simon, On Wed, Jul 22, 2015 at 11:49 PM, Simon Glass <s...@chromium.org> wrote: > The procedure to drop from 64-bit mode to 32-bit is a bit messy. Add a > function to take care of it. It requires identity-mapped pages and that > the calling code is running below 4GB. > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > arch/x86/cpu/Makefile | 6 +++++ > arch/x86/cpu/call32.S | 65 > ++++++++++++++++++++++++++++++++++++++++++++++ > arch/x86/include/asm/cpu.h | 9 +++++++ > 3 files changed, 80 insertions(+) > create mode 100644 arch/x86/cpu/call32.S > > diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile > index 9678976..eb993ec 100644 > --- a/arch/x86/cpu/Makefile > +++ b/arch/x86/cpu/Makefile > @@ -12,6 +12,12 @@ extra-y = start.o > obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o > obj-y += interrupts.o cpu.o cpu_x86.o call64.o > > +AFLAGS_REMOVE_call32.o := -mregparm=3 \ > + $(if $(CONFIG_EFI_STUB_64BIT),-march=i386 -m32) > +AFLAGS_call32.o := -fpic -fshort-wchar > + > +extra-y += call32.o > + > obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/ > obj-$(CONFIG_SYS_COREBOOT) += coreboot/ > obj-$(CONFIG_ARCH_EFI) += efi/ > diff --git a/arch/x86/cpu/call32.S b/arch/x86/cpu/call32.S > new file mode 100644 > index 0000000..3fe010e > --- /dev/null > +++ b/arch/x86/cpu/call32.S > @@ -0,0 +1,65 @@ > +/* > + * (C) Copyright 2015 Google, Inc > + * Written by Simon Glass <s...@chromium.org> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <asm/global_data.h> > +#include <asm/msr-index.h> > +#include <asm/processor-flags.h> > + > + /* > + * rdi - 32-bit code segment selector > + * rsi - target address > + * rdx - table address (0 if none) > + */ > +.code64 > +.globl cpu_call32 > +cpu_call32: > + cli > + > + /* Save table pointer */ > + mov %edx, %ebx > + > + /* > + * Debugging option, this outputs characters to the console UART > + * mov $0x3f8,%edx > + * mov $'a',%al > + * out %al,(%dx) > + */ > + > + pushf > + push %rdi /* 32-bit code segment */ > + lea compat(%rip), %rax > + push %rax > + .byte 0x48
I think this is a REX prefix. Is there any compiler macro we can use? We can put some comments here for better understanding. BTW: is this a must? I believe retf will operate on 64-bit by operand in 64-bit by default? > + retf > +.code32 > +compat: > + /* > + * We are now in compatibility mode with a default operand size of > + * 32 bits. First disable paging. > + */ > + movl %cr0, %eax > + andl $~X86_CR0_PG, %eax > + movl %eax, %cr0 > + > + /* Invalidate TLB */ > + xorl %eax, %eax > + movl %eax, %cr3 > + > + /* Disable Long mode in EFER (Extended Feature Enable Register) */ > + movl $MSR_EFER, %ecx > + rdmsr > + btr $_EFER_LME, %eax > + wrmsr > + > + /* Set up table pointer for _x86boot_start */ > + mov %ebx, %ecx > + > + /* Jump to the required target */ > + pushl %edi /* 32-bit code segment */ > + pushl %esi /* 32-bit target address */ > + .byte 0x48 > + retf > diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h > index b96513d..e977045 100644 > --- a/arch/x86/include/asm/cpu.h > +++ b/arch/x86/include/asm/cpu.h > @@ -222,6 +222,15 @@ char *cpu_get_name(char *name); > void cpu_call64(ulong pgtable, ulong setup_base, ulong target); > > /** > + * cpu_call32() - Jump to a 32-bit entry point > + * > + * @code_seg32: 32-bit code segment to use (GDT offset, e.g. 0x20) > + * @target: Pointer to the start of the 32-bit U-Boot image/entry point > + * @table: Pointer to start of info table to pass to U-Boot > + */ > +void cpu_call32(ulong code_seg32, ulong target, ulong table); > + > +/** > * cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel > * > * The kernel is uncompressed and the 64-bit entry point is expected to be > -- Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot