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/msr-index.h>
8#include <asm/processor-flags.h>
9
10	/*
11	 * rdi - 32-bit code segment selector
12	 * rsi - target address
13	 * rdx - table address (0 if none)
14	 */
15.code64
16.globl cpu_call32
17cpu_call32:
18	cli
19
20	/* Save table pointer */
21	mov	%edx, %ebx
22
23	/*
24	 * Debugging option, this outputs characters to the console UART
25	 * mov	$0x3f8,%edx
26	 * mov	$'a',%al
27	 * out	%al,(%dx)
28	 */
29
30	pushf
31	push	%rdi	/* 32-bit code segment */
32	lea	compat(%rip), %rax
33	push	%rax
34	retfq
35.code32
36compat:
37	/*
38	 * We are now in compatibility mode with a default operand size of
39	 * 32 bits. First disable paging.
40	 */
41	movl	%cr0, %eax
42	andl	$~X86_CR0_PG, %eax
43	movl	%eax, %cr0
44
45	/* Invalidate TLB */
46	xorl	%eax, %eax
47	movl	%eax, %cr3
48
49	/* Disable Long mode in EFER (Extended Feature Enable Register) */
50	movl	$MSR_EFER, %ecx
51	rdmsr
52	btr	$_EFER_LME, %eax
53	wrmsr
54
55	/* Set up table pointer for _x86boot_start */
56	mov	%ebx, %ecx
57
58	/* Jump to the required target */
59	pushl	%edi	/* 32-bit code segment */
60	pushl	%esi	/* 32-bit target address */
61	retfl
62