^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <asm/segment.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <asm/page_types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <asm/processor-flags.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <asm/msr-index.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "realmode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * The following code and data reboots the machine by switching to real
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * mode and jumping to the BIOS reset entry point, as if the CPU has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * really been reset. The previous version asked the keyboard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * controller to pulse the CPU reset line, which is more thorough, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * doesn't work with at least one type of 486 motherboard. It is easy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * to stop this code working; hence the copious comments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * This code is called with the restart type (0 = BIOS, 1 = APM) in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * the primary argument register (%eax for 32 bit, %edi for 64 bit).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) .section ".text32", "ax"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) .code32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) SYM_CODE_START(machine_real_restart_asm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #ifdef CONFIG_X86_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* Switch to trampoline GDT as it is guaranteed < 4 GiB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) movl $__KERNEL_DS, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) movl %eax, %ds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) lgdtl pa_tr_gdt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* Disable paging to drop us out of long mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) movl %cr0, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) andl $~X86_CR0_PG, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) movl %eax, %cr0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ljmpl $__KERNEL32_CS, $pa_machine_real_restart_paging_off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) SYM_INNER_LABEL(machine_real_restart_paging_off, SYM_L_GLOBAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) xorl %eax, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) xorl %edx, %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) movl $MSR_EFER, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) wrmsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) movl %edi, %eax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #endif /* CONFIG_X86_64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Set up the IDT for real mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) lidtl pa_machine_real_restart_idt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * Set up a GDT from which we can load segment descriptors for real
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * mode. The GDT is not used in real mode; it is just needed here to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * prepare the descriptors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) lgdtl pa_machine_real_restart_gdt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Load the data segment registers with 16-bit compatible values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) movl $16, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) movl %ecx, %ds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) movl %ecx, %es
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) movl %ecx, %fs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) movl %ecx, %gs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) movl %ecx, %ss
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ljmpw $8, $1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) SYM_CODE_END(machine_real_restart_asm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * This is 16-bit protected mode code to disable paging and the cache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * switch to real mode and jump to the BIOS reset code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * The instruction that switches to real mode by writing to CR0 must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * followed immediately by a far jump instruction, which set CS to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * valid value for real mode, and flushes the prefetch queue to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * running instructions that have already been decoded in protected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Clears all the flags except ET, especially PG (paging), PE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * (protected-mode enable) and TS (task switch for coprocessor state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * save). Flushes the TLB after paging has been disabled. Sets CD and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * NW, to disable the cache on a 486, and invalidates the cache. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * is more like the state of a 486 after reset. I don't know if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * something else should be done for other chips.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * More could be done here to set up the registers as if a CPU reset had
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * occurred; hopefully real BIOSs don't assume much. This is not the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * actual BIOS entry point, anyway (that is at 0xfffffff0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Most of this work is probably excessive, but it is what is tested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .code16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .balign 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) machine_real_restart_asm16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) xorl %ecx, %ecx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) movl %cr0, %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) andl $0x00000011, %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) orl $0x60000000, %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) movl %edx, %cr0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) movl %ecx, %cr3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) movl %cr0, %edx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) testl $0x60000000, %edx /* If no cache bits -> no wbinvd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) jz 2f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) wbinvd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) andb $0x10, %dl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) movl %edx, %cr0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) LJMPW_RM(3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) andw %ax, %ax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) jz bios
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) apm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) movw $0x1000, %ax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) movw %ax, %ss
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) movw $0xf000, %sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) movw $0x5307, %ax
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) movw $0x0001, %bx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) movw $0x0003, %cx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int $0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* This should never return... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) bios:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ljmpw $0xf000, $0xfff0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .section ".rodata", "a"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .balign 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) SYM_DATA_START(machine_real_restart_idt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .word 0xffff /* Length - real mode default value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .long 0 /* Base - real mode default value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) SYM_DATA_END(machine_real_restart_idt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .balign 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) SYM_DATA_START(machine_real_restart_gdt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Self-pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .word 0xffff /* Length - real mode default value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .long pa_machine_real_restart_gdt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .word 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * 16-bit code segment pointing to real_mode_seg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * Selector value 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .word 0xffff /* Limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .long 0x9b000000 + pa_real_mode_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .word 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * 16-bit data segment with the selector value 16 = 0x10 and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * base value 0x100; since this is consistent with real mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * semantics we don't have to reload the segments once CR0.PE = 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .quad GDT_ENTRY(0x0093, 0x100, 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) SYM_DATA_END(machine_real_restart_gdt)