/* SPDX-License-Identifier: GPL-2.0 */1#include <linux/linkage.h>2#include <asm/desc_defs.h>3#include <asm/segment.h>4#include <asm/page_types.h>5#include <asm/processor-flags.h>6#include <asm/msr-index.h>7#include "realmode.h"89/*10* The following code and data reboots the machine by switching to real11* mode and jumping to the BIOS reset entry point, as if the CPU has12* really been reset. The previous version asked the keyboard13* controller to pulse the CPU reset line, which is more thorough, but14* doesn't work with at least one type of 486 motherboard. It is easy15* to stop this code working; hence the copious comments.16*17* This code is called with the restart type (0 = BIOS, 1 = APM) in18* the primary argument register (%eax for 32 bit, %edi for 64 bit).19*/20.section ".text32", "ax"21.code3222SYM_CODE_START(machine_real_restart_asm)2324#ifdef CONFIG_X86_6425/* Switch to trampoline GDT as it is guaranteed < 4 GiB */26movl $__KERNEL_DS, %eax27movl %eax, %ds28lgdtl pa_tr_gdt2930/* Disable paging to drop us out of long mode */31movl %cr0, %eax32andl $~X86_CR0_PG, %eax33movl %eax, %cr034ljmpl $__KERNEL32_CS, $pa_machine_real_restart_paging_off3536SYM_INNER_LABEL(machine_real_restart_paging_off, SYM_L_GLOBAL)37xorl %eax, %eax38xorl %edx, %edx39movl $MSR_EFER, %ecx40wrmsr4142movl %edi, %eax4344#endif /* CONFIG_X86_64 */4546/* Set up the IDT for real mode. */47lidtl pa_machine_real_restart_idt4849/*50* Set up a GDT from which we can load segment descriptors for real51* mode. The GDT is not used in real mode; it is just needed here to52* prepare the descriptors.53*/54lgdtl pa_machine_real_restart_gdt5556/*57* Load the data segment registers with 16-bit compatible values58*/59movl $16, %ecx60movl %ecx, %ds61movl %ecx, %es62movl %ecx, %fs63movl %ecx, %gs64movl %ecx, %ss65ljmpw $8, $1f66SYM_CODE_END(machine_real_restart_asm)6768/*69* This is 16-bit protected mode code to disable paging and the cache,70* switch to real mode and jump to the BIOS reset code.71*72* The instruction that switches to real mode by writing to CR0 must be73* followed immediately by a far jump instruction, which set CS to a74* valid value for real mode, and flushes the prefetch queue to avoid75* running instructions that have already been decoded in protected76* mode.77*78* Clears all the flags except ET, especially PG (paging), PE79* (protected-mode enable) and TS (task switch for coprocessor state80* save). Flushes the TLB after paging has been disabled. Sets CD and81* NW, to disable the cache on a 486, and invalidates the cache. This82* is more like the state of a 486 after reset. I don't know if83* something else should be done for other chips.84*85* More could be done here to set up the registers as if a CPU reset had86* occurred; hopefully real BIOSs don't assume much. This is not the87* actual BIOS entry point, anyway (that is at 0xfffffff0).88*89* Most of this work is probably excessive, but it is what is tested.90*/91.text92.code169394.balign 1695machine_real_restart_asm16:961:97xorl %ecx, %ecx98movl %cr0, %edx99andl $0x00000011, %edx100orl $0x60000000, %edx101movl %edx, %cr0102movl %ecx, %cr3103movl %cr0, %edx104testl $0x60000000, %edx /* If no cache bits -> no wbinvd */105jz 2f106wbinvd1072:108andb $0x10, %dl109movl %edx, %cr0110LJMPW_RM(3f)1113:112andw %ax, %ax113jz bios114115apm:116movw $0x1000, %ax117movw %ax, %ss118movw $0xf000, %sp119movw $0x5307, %ax120movw $0x0001, %bx121movw $0x0003, %cx122int $0x15123/* This should never return... */124125bios:126ljmpw $0xf000, $0xfff0127128.section ".rodata", "a"129130.balign 16131SYM_DATA_START(machine_real_restart_idt)132.word 0xffff /* Length - real mode default value */133.long 0 /* Base - real mode default value */134SYM_DATA_END(machine_real_restart_idt)135136.balign 16137SYM_DATA_START(machine_real_restart_gdt)138/* Self-pointer */139.word 0xffff /* Length - real mode default value */140.long pa_machine_real_restart_gdt141.word 0142143/*144* 16-bit code segment pointing to real_mode_seg145* Selector value 8146*/147.word 0xffff /* Limit */148.long 0x9b000000 + pa_real_mode_base149.word 0150151/*152* 16-bit data segment with the selector value 16 = 0x10 and153* base value 0x100; since this is consistent with real mode154* semantics we don't have to reload the segments once CR0.PE = 0.155*/156.quad GDT_ENTRY(DESC_DATA16, 0x100, 0xffff)157SYM_DATA_END(machine_real_restart_gdt)158159160