File Index
Files and directories
Sign in
FILE

la57toggle.S

File preview with syntax highlighting.

linux-6.19.14/arch/x86/boot/startup/la57toggle.S GAS
  1/* SPDX-License-Identifier: GPL-2.0 */
  2
  3#include <linux/linkage.h>
  4#include <asm/segment.h>
  5#include <asm/boot.h>
  6#include <asm/msr.h>
  7#include <asm/processor-flags.h>
  8
  9/*
 10 * This is the 32-bit trampoline that will be copied over to low memory. It
 11 * will be called using the ordinary 64-bit calling convention from code
 12 * running in 64-bit mode.
 13 *
 14 * Return address is at the top of the stack (might be above 4G).
 15 * The first argument (EDI) contains the address of the temporary PGD level
 16 * page table in 32-bit addressable memory which will be programmed into
 17 * register CR3.
 18 */
 19
 20	.section ".rodata", "a", @progbits
 21SYM_CODE_START(trampoline_32bit_src)
 22	/*
 23	 * Preserve callee save 64-bit registers on the stack: this is
 24	 * necessary because the architecture does not guarantee that GPRs will
 25	 * retain their full 64-bit values across a 32-bit mode switch.
 26	 */
 27	pushq	%r15
 28	pushq	%r14
 29	pushq	%r13
 30	pushq	%r12
 31	pushq	%rbp
 32	pushq	%rbx
 33
 34	/* Preserve top half of RSP in a legacy mode GPR to avoid truncation */
 35	movq	%rsp, %rbx
 36	shrq	$32, %rbx
 37
 38	/* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */
 39	pushq	$__KERNEL32_CS
 40	leaq	0f(%rip), %rax
 41	pushq	%rax
 42	lretq
 43
 44	/*
 45	 * The 32-bit code below will do a far jump back to long mode and end
 46	 * up here after reconfiguring the number of paging levels. First, the
 47	 * stack pointer needs to be restored to its full 64-bit value before
 48	 * the callee save register contents can be popped from the stack.
 49	 */
 50.Lret:
 51	shlq	$32, %rbx
 52	orq	%rbx, %rsp
 53
 54	/* Restore the preserved 64-bit registers */
 55	popq	%rbx
 56	popq	%rbp
 57	popq	%r12
 58	popq	%r13
 59	popq	%r14
 60	popq	%r15
 61	retq
 62
 63	.code32
 640:
 65	/* Disable paging */
 66	movl	%cr0, %eax
 67	btrl	$X86_CR0_PG_BIT, %eax
 68	movl	%eax, %cr0
 69
 70	/* Point CR3 to the trampoline's new top level page table */
 71	movl	%edi, %cr3
 72
 73	/* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
 74	movl	$MSR_EFER, %ecx
 75	rdmsr
 76	btsl	$_EFER_LME, %eax
 77	/* Avoid writing EFER if no change was made (for TDX guest) */
 78	jc	1f
 79	wrmsr
 801:
 81	/* Toggle CR4.LA57 */
 82	movl	%cr4, %eax
 83	btcl	$X86_CR4_LA57_BIT, %eax
 84	movl	%eax, %cr4
 85
 86	/* Enable paging again. */
 87	movl	%cr0, %eax
 88	btsl	$X86_CR0_PG_BIT, %eax
 89	movl	%eax, %cr0
 90
 91	/*
 92	 * Return to the 64-bit calling code using LJMP rather than LRET, to
 93	 * avoid the need for a 32-bit addressable stack. The destination
 94	 * address will be adjusted after the template code is copied into a
 95	 * 32-bit addressable buffer.
 96	 */
 97.Ljmp:	ljmpl	$__KERNEL_CS, $(.Lret - trampoline_32bit_src)
 98SYM_CODE_END(trampoline_32bit_src)
 99
100/*
101 * This symbol is placed right after trampoline_32bit_src() so its address can
102 * be used to infer the size of the trampoline code.
103 */
104SYM_DATA(trampoline_ljmp_imm_offset, .word  .Ljmp + 1 - trampoline_32bit_src)
105
106	/*
107         * The trampoline code has a size limit.
108         * Make sure we fail to compile if the trampoline code grows
109         * beyond TRAMPOLINE_32BIT_CODE_SIZE bytes.
110	 */
111	.org	trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE
~/ Read-only file preview.