18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Trampoline.S Derived from Setup.S by Linus Torvalds 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * 4 Jan 1997 Michael Chastain: changed to gnu as. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This is only used for booting secondary CPUs in SMP machine 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Entry: CS:IP point to the start of our code, we are 118c2ecf20Sopenharmony_ci * in real mode with no stack, but the rest of the 128c2ecf20Sopenharmony_ci * trampoline page to make our stack and everything else 138c2ecf20Sopenharmony_ci * is a mystery. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * We jump into arch/x86/kernel/head_32.S. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * On entry to trampoline_start, the processor is in real mode 188c2ecf20Sopenharmony_ci * with 16-bit addressing and 16-bit data. CS has some value 198c2ecf20Sopenharmony_ci * and IP is zero. Thus, we load CS to the physical segment 208c2ecf20Sopenharmony_ci * of the real mode code before doing anything further. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <linux/linkage.h> 248c2ecf20Sopenharmony_ci#include <asm/segment.h> 258c2ecf20Sopenharmony_ci#include <asm/page_types.h> 268c2ecf20Sopenharmony_ci#include "realmode.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci .text 298c2ecf20Sopenharmony_ci .code16 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci .balign PAGE_SIZE 328c2ecf20Sopenharmony_ciSYM_CODE_START(trampoline_start) 338c2ecf20Sopenharmony_ci wbinvd # Needed for NUMA-Q should be harmless for others 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci LJMPW_RM(1f) 368c2ecf20Sopenharmony_ci1: 378c2ecf20Sopenharmony_ci mov %cs, %ax # Code and data in the same place 388c2ecf20Sopenharmony_ci mov %ax, %ds 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci cli # We should be safe anyway 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci movl tr_start, %eax # where we need to go 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci /* 458c2ecf20Sopenharmony_ci * GDT tables in non default location kernel can be beyond 16MB and 468c2ecf20Sopenharmony_ci * lgdt will not be able to load the address as in real mode default 478c2ecf20Sopenharmony_ci * operand size is 16bit. Use lgdtl instead to force operand size 488c2ecf20Sopenharmony_ci * to 32 bit. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ci lidtl tr_idt # load idt with 0, 0 518c2ecf20Sopenharmony_ci lgdtl tr_gdt # load gdt with whatever is appropriate 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci movw $1, %dx # protected mode (PE) bit 548c2ecf20Sopenharmony_ci lmsw %dx # into protected mode 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci ljmpl $__BOOT_CS, $pa_startup_32 578c2ecf20Sopenharmony_ciSYM_CODE_END(trampoline_start) 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci .section ".text32","ax" 608c2ecf20Sopenharmony_ci .code32 618c2ecf20Sopenharmony_ciSYM_CODE_START(startup_32) # note: also used from wakeup_asm.S 628c2ecf20Sopenharmony_ci jmp *%eax 638c2ecf20Sopenharmony_ciSYM_CODE_END(startup_32) 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci .bss 668c2ecf20Sopenharmony_ci .balign 8 678c2ecf20Sopenharmony_ciSYM_DATA_START(trampoline_header) 688c2ecf20Sopenharmony_ci SYM_DATA_LOCAL(tr_start, .space 4) 698c2ecf20Sopenharmony_ci SYM_DATA_LOCAL(tr_gdt_pad, .space 2) 708c2ecf20Sopenharmony_ci SYM_DATA_LOCAL(tr_gdt, .space 6) 718c2ecf20Sopenharmony_ciSYM_DATA_END(trampoline_header) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#include "trampoline_common.S" 74