162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Trampoline.S Derived from Setup.S by Linus Torvalds 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * 4 Jan 1997 Michael Chastain: changed to gnu as. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This is only used for booting secondary CPUs in SMP machine 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Entry: CS:IP point to the start of our code, we are 1162306a36Sopenharmony_ci * in real mode with no stack, but the rest of the 1262306a36Sopenharmony_ci * trampoline page to make our stack and everything else 1362306a36Sopenharmony_ci * is a mystery. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * We jump into arch/x86/kernel/head_32.S. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * On entry to trampoline_start, the processor is in real mode 1862306a36Sopenharmony_ci * with 16-bit addressing and 16-bit data. CS has some value 1962306a36Sopenharmony_ci * and IP is zero. Thus, we load CS to the physical segment 2062306a36Sopenharmony_ci * of the real mode code before doing anything further. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <linux/linkage.h> 2462306a36Sopenharmony_ci#include <asm/segment.h> 2562306a36Sopenharmony_ci#include <asm/page_types.h> 2662306a36Sopenharmony_ci#include "realmode.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci .text 2962306a36Sopenharmony_ci .code16 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci .balign PAGE_SIZE 3262306a36Sopenharmony_ciSYM_CODE_START(trampoline_start) 3362306a36Sopenharmony_ci wbinvd # Needed for NUMA-Q should be harmless for others 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci LJMPW_RM(1f) 3662306a36Sopenharmony_ci1: 3762306a36Sopenharmony_ci mov %cs, %ax # Code and data in the same place 3862306a36Sopenharmony_ci mov %ax, %ds 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci cli # We should be safe anyway 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci movl tr_start, %eax # where we need to go 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* 4562306a36Sopenharmony_ci * GDT tables in non default location kernel can be beyond 16MB and 4662306a36Sopenharmony_ci * lgdt will not be able to load the address as in real mode default 4762306a36Sopenharmony_ci * operand size is 16bit. Use lgdtl instead to force operand size 4862306a36Sopenharmony_ci * to 32 bit. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci lidtl tr_idt # load idt with 0, 0 5162306a36Sopenharmony_ci lgdtl tr_gdt # load gdt with whatever is appropriate 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci movw $1, %dx # protected mode (PE) bit 5462306a36Sopenharmony_ci lmsw %dx # into protected mode 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci ljmpl $__BOOT_CS, $pa_startup_32 5762306a36Sopenharmony_ciSYM_CODE_END(trampoline_start) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci .section ".text32","ax" 6062306a36Sopenharmony_ci .code32 6162306a36Sopenharmony_ciSYM_CODE_START(startup_32) # note: also used from wakeup_asm.S 6262306a36Sopenharmony_ci jmp *%eax 6362306a36Sopenharmony_ciSYM_CODE_END(startup_32) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci .bss 6662306a36Sopenharmony_ci .balign 8 6762306a36Sopenharmony_ciSYM_DATA_START(trampoline_header) 6862306a36Sopenharmony_ci SYM_DATA_LOCAL(tr_start, .space 4) 6962306a36Sopenharmony_ci SYM_DATA_LOCAL(tr_gdt_pad, .space 2) 7062306a36Sopenharmony_ci SYM_DATA_LOCAL(tr_gdt, .space 6) 7162306a36Sopenharmony_ciSYM_DATA_END(trampoline_header) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#include "trampoline_common.S" 74