xref: /openbmc/u-boot/arch/x86/cpu/call32.S (revision e8f80a5a)
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * (C) Copyright 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
7#include <asm/global_data.h>
8#include <asm/msr-index.h>
9#include <asm/processor-flags.h>
10
11	/*
12	 * rdi - 32-bit code segment selector
13	 * rsi - target address
14	 * rdx - table address (0 if none)
15	 */
16.code64
17.globl cpu_call32
18cpu_call32:
19	cli
20
21	/* Save table pointer */
22	mov	%edx, %ebx
23
24	/*
25	 * Debugging option, this outputs characters to the console UART
26	 * mov	$0x3f8,%edx
27	 * mov	$'a',%al
28	 * out	%al,(%dx)
29	 */
30
31	pushf
32	push	%rdi	/* 32-bit code segment */
33	lea	compat(%rip), %rax
34	push	%rax
35	.byte	0x48	/* REX prefix to force 64-bit far return */
36	retf
37.code32
38compat:
39	/*
40	 * We are now in compatibility mode with a default operand size of
41	 * 32 bits. First disable paging.
42	 */
43	movl	%cr0, %eax
44	andl	$~X86_CR0_PG, %eax
45	movl	%eax, %cr0
46
47	/* Invalidate TLB */
48	xorl	%eax, %eax
49	movl	%eax, %cr3
50
51	/* Disable Long mode in EFER (Extended Feature Enable Register) */
52	movl	$MSR_EFER, %ecx
53	rdmsr
54	btr	$_EFER_LME, %eax
55	wrmsr
56
57	/* Set up table pointer for _x86boot_start */
58	mov	%ebx, %ecx
59
60	/* Jump to the required target */
61	pushl	%edi	/* 32-bit code segment */
62	pushl	%esi	/* 32-bit target address */
63	retf
64