The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/amd64/acpica/acpi_wakecode.S

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
    3  * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
    4  * Copyright (c) 2003 Peter Wemm
    5  * Copyright (c) 2008-2009 Jung-uk Kim <jkim@FreeBSD.org>
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * $FreeBSD: releng/8.0/sys/amd64/acpica/acpi_wakecode.S 190635 2009-04-02 00:23:56Z jkim $
   30  */
   31 
   32 #define LOCORE
   33 
   34 #include <machine/asmacros.h>
   35 #include <machine/specialreg.h>
   36 
   37 #include "assym.s"
   38 
   39 /*
   40  * Resume entry point for real mode.
   41  *
   42  * If XFirmwareWakingVector is zero and FirmwareWakingVector is non-zero
   43  * in FACS, the BIOS enters here in real mode after POST with CS set to
   44  * (FirmwareWakingVector >> 4) and IP set to (FirmwareWakingVector & 0xf).
   45  * Depending on the previous sleep state, we may need to initialize more
   46  * of the system (i.e., S3 suspend-to-RAM vs. S4 suspend-to-disk).
   47  *
   48  * Note: If XFirmwareWakingVector is non-zero, it should disable address
   49  * translation/paging and interrupts, load all segment registers with
   50  * a flat 4 GB address space, and set EFLAGS.IF to zero.  Currently
   51  * this mode is not supported by this code.
   52  */
   53 
   54         .data                           /* So we can modify it */
   55 
   56         ALIGN_TEXT
   57 wakeup_start:
   58         .code16
   59         /*
   60          * Set up segment registers for real mode, a small stack for
   61          * any calls we make, and clear any flags.
   62          */
   63         cli                             /* make sure no interrupts */
   64         cld
   65         mov     %cs, %ax                /* copy %cs to %ds.  Remember these */
   66         mov     %ax, %ds                /* are offsets rather than selectors */
   67         mov     %ax, %ss
   68         movw    $PAGE_SIZE - 8, %sp
   69         xorw    %ax, %ax
   70         pushw   %ax
   71         popfw
   72 
   73         /* To debug resume hangs, beep the speaker if the user requested. */
   74         testb   $~0, resume_beep - wakeup_start
   75         jz      1f
   76         movb    $0, resume_beep - wakeup_start
   77         movb    $0xc0, %al
   78         outb    %al, $0x42
   79         movb    $0x04, %al
   80         outb    %al, $0x42
   81         inb     $0x61, %al
   82         orb     $0x3, %al
   83         outb    %al, $0x61
   84 1:
   85 
   86         /* Re-initialize video BIOS if the reset_video tunable is set. */
   87         testb   $~0, reset_video - wakeup_start
   88         jz      1f
   89         movb    $0, reset_video - wakeup_start
   90         lcall   $0xc000, $3
   91 
   92         /* Re-start in case the previous BIOS call clobbers them. */
   93         jmp     wakeup_start
   94 1:
   95 
   96         /*
   97          * Find relocation base and patch the gdt descript and ljmp targets
   98          */
   99         xorl    %ebx, %ebx
  100         mov     %cs, %bx
  101         sall    $4, %ebx                /* %ebx is now our relocation base */
  102 
  103         /*
  104          * Load the descriptor table pointer.  We'll need it when running
  105          * in 16-bit protected mode.
  106          */
  107         lgdtl   bootgdtdesc - wakeup_start
  108 
  109         /* Enable protected mode */
  110         movl    $CR0_PE, %eax
  111         mov     %eax, %cr0
  112 
  113         /*
  114          * Now execute a far jump to turn on protected mode.  This
  115          * causes the segment registers to turn into selectors and causes
  116          * %cs to be loaded from the gdt.
  117          *
  118          * The following instruction is:
  119          * ljmpl $bootcode32 - bootgdt, $wakeup_32 - wakeup_start
  120          * but gas cannot assemble that.  And besides, we patch the targets
  121          * in early startup and its a little clearer what we are patching.
  122          */
  123 wakeup_sw32:
  124         .byte   0x66                    /* size override to 32 bits */
  125         .byte   0xea                    /* opcode for far jump */
  126         .long   wakeup_32 - wakeup_start /* offset in segment */
  127         .word   bootcode32 - bootgdt    /* index in gdt for 32 bit code */
  128 
  129         /*
  130          * At this point, we are running in 32 bit legacy protected mode.
  131          */
  132         .code32
  133 wakeup_32:
  134 
  135         mov     $bootdata32 - bootgdt, %eax
  136         mov     %ax, %ds
  137 
  138         /* Turn on the PAE and PSE bits for when paging is enabled */
  139         mov     %cr4, %eax
  140         orl     $(CR4_PAE | CR4_PSE), %eax
  141         mov     %eax, %cr4
  142 
  143         /*
  144          * Enable EFER.LME so that we get long mode when all the prereqs are
  145          * in place.  In this case, it turns on when CR0_PG is finally enabled.
  146          * Pick up a few other EFER bits that we'll use need we're here.
  147          */
  148         movl    $MSR_EFER, %ecx
  149         rdmsr
  150         orl     $EFER_LME | EFER_SCE, %eax
  151         wrmsr
  152 
  153         /*
  154          * Point to the embedded page tables for startup.  Note that this
  155          * only gets accessed after we're actually in 64 bit mode, however
  156          * we can only set the bottom 32 bits of %cr3 in this state.  This
  157          * means we are required to use a temporary page table that is below
  158          * the 4GB limit.  %ebx is still our relocation base.  We could just
  159          * subtract 3 * PAGE_SIZE, but that would be too easy.
  160          */
  161         leal    wakeup_pagetables - wakeup_start(%ebx), %eax
  162         movl    (%eax), %eax
  163         mov     %eax, %cr3
  164 
  165         /*
  166          * Finally, switch to long bit mode by enabling paging.  We have
  167          * to be very careful here because all the segmentation disappears
  168          * out from underneath us.  The spec says we can depend on the
  169          * subsequent pipelined branch to execute, but *only if* everthing
  170          * is still identity mapped.  If any mappings change, the pipeline
  171          * will flush.
  172          */
  173         mov     %cr0, %eax
  174         orl     $CR0_PG, %eax
  175         mov     %eax, %cr0
  176 
  177         /*
  178          * At this point paging is enabled, and we are in "compatability" mode.
  179          * We do another far jump to reload %cs with the 64 bit selector.
  180          * %cr3 points to a 4-level page table page.
  181          * We cannot yet jump all the way to the kernel because we can only
  182          * specify a 32 bit linear address.  So, yet another trampoline.
  183          *
  184          * The following instruction is:
  185          * ljmp $bootcode64 - bootgdt, $wakeup_64 - wakeup_start
  186          * but gas cannot assemble that.  And besides, we patch the targets
  187          * in early startup and its a little clearer what we are patching.
  188          */
  189 wakeup_sw64:
  190         .byte   0xea                    /* opcode for far jump */
  191         .long   wakeup_64 - wakeup_start /* offset in segment */
  192         .word   bootcode64 - bootgdt    /* index in gdt for 64 bit code */
  193 
  194         /*
  195          * Yeehar!  We're running in 64-bit mode!  We can mostly ignore our
  196          * segment registers, and get on with it.
  197          * Note that we are running at the correct virtual address, but with
  198          * a 1:1 1GB mirrored mapping over entire address space.  We had better
  199          * switch to a real %cr3 promptly so that we can get to the direct map
  200          * space. Remember that jmp is relative and that we've been relocated,
  201          * so use an indirect jump.
  202          */
  203         ALIGN_TEXT
  204         .code64
  205 wakeup_64:
  206         mov     $bootdata64 - bootgdt, %eax
  207         mov     %ax, %ds
  208 
  209         /* Restore arguments and return. */
  210         movq    wakeup_ctx - wakeup_start(%rbx), %rdi
  211         movq    wakeup_kpml4 - wakeup_start(%rbx), %rsi
  212         movq    wakeup_retaddr - wakeup_start(%rbx), %rax
  213         jmp     *%rax
  214 
  215         .data
  216 
  217 resume_beep:
  218         .byte   0
  219 reset_video:
  220         .byte   0
  221 
  222         ALIGN_DATA
  223 bootgdt:
  224         .long   0x00000000
  225         .long   0x00000000
  226         .long   0x00000000
  227         .long   0x00000000
  228         .long   0x00000000
  229         .long   0x00000000
  230         .long   0x00000000
  231         .long   0x00000000
  232 
  233 bootcode64:
  234         .long   0x0000ffff
  235         .long   0x00af9b00
  236 
  237 bootdata64:
  238         .long   0x0000ffff
  239         .long   0x00af9300
  240 
  241 bootcode32:
  242         .long   0x0000ffff
  243         .long   0x00cf9b00
  244 
  245 bootdata32:
  246         .long   0x0000ffff
  247         .long   0x00cf9300
  248 bootgdtend:
  249 
  250 wakeup_pagetables:
  251         .long   0
  252 
  253 bootgdtdesc:
  254         .word   bootgdtend - bootgdt    /* Length */
  255         .long   bootgdt - wakeup_start  /* Offset plus %ds << 4 */
  256 
  257         ALIGN_DATA
  258 wakeup_retaddr:
  259         .quad   0
  260 wakeup_kpml4:
  261         .quad   0
  262 
  263 wakeup_ctx:
  264         .quad   0
  265 wakeup_xpcb:
  266         .quad   0
  267 wakeup_gdt:
  268         .word   0
  269         .quad   0
  270 
  271         ALIGN_DATA
  272 wakeup_efer:
  273         .quad   0
  274 wakeup_pat:
  275         .quad   0
  276 wakeup_star:
  277         .quad   0
  278 wakeup_lstar:
  279         .quad   0
  280 wakeup_cstar:
  281         .quad   0
  282 wakeup_sfmask:
  283         .quad   0
  284 wakeup_cpu:
  285         .long   0
  286 dummy:

Cache object: 06289c4bedfc03b5c32a0e3c98948514


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.