~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/realmode/rm/wakeup_asm.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 /*
  3  * ACPI wakeup real mode startup stub
  4  */
  5 #include <linux/linkage.h>
  6 #include <asm/segment.h>
  7 #include <asm/msr-index.h>
  8 #include <asm/page_types.h>
  9 #include <asm/pgtable_types.h>
 10 #include <asm/processor-flags.h>
 11 #include "realmode.h"
 12 #include "wakeup.h"
 13 
 14         .code16
 15 
 16 /* This should match the structure in wakeup.h */
 17         .section ".data", "aw"
 18 
 19         .balign 16
 20 SYM_DATA_START(wakeup_header)
 21         video_mode:     .short  0       /* Video mode number */
 22         pmode_entry:    .long   0
 23         pmode_cs:       .short  __KERNEL_CS
 24         pmode_cr0:      .long   0       /* Saved %cr0 */
 25         pmode_cr3:      .long   0       /* Saved %cr3 */
 26         pmode_cr4:      .long   0       /* Saved %cr4 */
 27         pmode_efer:     .quad   0       /* Saved EFER */
 28         pmode_gdt:      .quad   0
 29         pmode_misc_en:  .quad   0       /* Saved MISC_ENABLE MSR */
 30         pmode_behavior: .long   0       /* Wakeup behavior flags */
 31         realmode_flags: .long   0
 32         real_magic:     .long   0
 33         signature:      .long   WAKEUP_HEADER_SIGNATURE
 34 SYM_DATA_END(wakeup_header)
 35 
 36         .text
 37         .code16
 38 
 39         .balign 16
 40 SYM_CODE_START(wakeup_start)
 41         cli
 42         cld
 43 
 44         LJMPW_RM(3f)
 45 3:
 46         /* Apparently some dimwit BIOS programmers don't know how to
 47            program a PM to RM transition, and we might end up here with
 48            junk in the data segment descriptor registers.  The only way
 49            to repair that is to go into PM and fix it ourselves... */
 50         movw    $16, %cx
 51         lgdtl   %cs:wakeup_gdt
 52         movl    %cr0, %eax
 53         orb     $X86_CR0_PE, %al
 54         movl    %eax, %cr0
 55         ljmpw   $8, $2f
 56 2:
 57         movw    %cx, %ds
 58         movw    %cx, %es
 59         movw    %cx, %ss
 60         movw    %cx, %fs
 61         movw    %cx, %gs
 62 
 63         andb    $~X86_CR0_PE, %al
 64         movl    %eax, %cr0
 65         LJMPW_RM(3f)
 66 3:
 67         /* Set up segments */
 68         movw    %cs, %ax
 69         movw    %ax, %ss
 70         movl    $rm_stack_end, %esp
 71         movw    %ax, %ds
 72         movw    %ax, %es
 73         movw    %ax, %fs
 74         movw    %ax, %gs
 75 
 76         lidtl   .Lwakeup_idt
 77 
 78         /* Clear the EFLAGS */
 79         pushl $0
 80         popfl
 81 
 82         /* Check header signature... */
 83         movl    signature, %eax
 84         cmpl    $WAKEUP_HEADER_SIGNATURE, %eax
 85         jne     bogus_real_magic
 86 
 87         /* Check we really have everything... */
 88         movl    end_signature, %eax
 89         cmpl    $REALMODE_END_SIGNATURE, %eax
 90         jne     bogus_real_magic
 91 
 92         /* Call the C code */
 93         calll   main
 94 
 95         /* Restore MISC_ENABLE before entering protected mode, in case
 96            BIOS decided to clear XD_DISABLE during S3. */
 97         movl    pmode_behavior, %edi
 98         btl     $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %edi
 99         jnc     1f
100 
101         movl    pmode_misc_en, %eax
102         movl    pmode_misc_en + 4, %edx
103         movl    $MSR_IA32_MISC_ENABLE, %ecx
104         wrmsr
105 1:
106 
107         /* Do any other stuff... */
108 
109 #ifndef CONFIG_64BIT
110         /* This could also be done in C code... */
111         movl    pmode_cr3, %eax
112         movl    %eax, %cr3
113 
114         btl     $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi
115         jnc     1f
116         movl    pmode_cr4, %eax
117         movl    %eax, %cr4
118 1:
119         btl     $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi
120         jnc     1f
121         movl    pmode_efer, %eax
122         movl    pmode_efer + 4, %edx
123         movl    $MSR_EFER, %ecx
124         wrmsr
125 1:
126 
127         lgdtl   pmode_gdt
128 
129         /* This really couldn't... */
130         movl    pmode_entry, %eax
131         movl    pmode_cr0, %ecx
132         movl    %ecx, %cr0
133         ljmpl   $__KERNEL_CS, $pa_startup_32
134         /* -> jmp *%eax in trampoline_32.S */
135 #else
136         jmp     trampoline_start
137 #endif
138 SYM_CODE_END(wakeup_start)
139 
140 bogus_real_magic:
141 1:
142         hlt
143         jmp     1b
144 
145         .section ".rodata","a"
146 
147         /*
148          * Set up the wakeup GDT.  We set these up as Big Real Mode,
149          * that is, with limits set to 4 GB.  At least the Lenovo
150          * Thinkpad X61 is known to need this for the video BIOS
151          * initialization quirk to work; this is likely to also
152          * be the case for other laptops or integrated video devices.
153          */
154 
155         .balign 16
156 SYM_DATA_START(wakeup_gdt)
157         .word   3*8-1           /* Self-descriptor */
158         .long   pa_wakeup_gdt
159         .word   0
160 
161         .word   0xffff          /* 16-bit code segment @ real_mode_base */
162         .long   0x9b000000 + pa_real_mode_base
163         .word   0x008f          /* big real mode */
164 
165         .word   0xffff          /* 16-bit data segment @ real_mode_base */
166         .long   0x93000000 + pa_real_mode_base
167         .word   0x008f          /* big real mode */
168 SYM_DATA_END(wakeup_gdt)
169 
170         .section ".rodata","a"
171         .balign 8
172 
173         /* This is the standard real-mode IDT */
174         .balign 16
175 SYM_DATA_START_LOCAL(.Lwakeup_idt)
176         .word   0xffff          /* limit */
177         .long   0               /* address */
178         .word   0
179 SYM_DATA_END(.Lwakeup_idt)

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php