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-2010 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.4/sys/amd64/acpica/acpi_wakecode.S 237009 2012-06-13 15:25:52Z jhb $
   30  */
   31 
   32 #include <machine/asmacros.h>
   33 #include <machine/specialreg.h>
   34 
   35 #include "assym.s"
   36 
   37 /*
   38  * Resume entry point for real mode.
   39  *
   40  * If XFirmwareWakingVector is zero and FirmwareWakingVector is non-zero
   41  * in FACS, the BIOS enters here in real mode after POST with CS set to
   42  * (FirmwareWakingVector >> 4) and IP set to (FirmwareWakingVector & 0xf).
   43  * Depending on the previous sleep state, we may need to initialize more
   44  * of the system (i.e., S3 suspend-to-RAM vs. S4 suspend-to-disk).
   45  *
   46  * Note: If XFirmwareWakingVector is non-zero, it should disable address
   47  * translation/paging and interrupts, load all segment registers with
   48  * a flat 4 GB address space, and set EFLAGS.IF to zero.  Currently
   49  * this mode is not supported by this code.
   50  */
   51 
   52         .data                           /* So we can modify it */
   53 
   54         ALIGN_TEXT
   55         .code16
   56 wakeup_start:
   57         /*
   58          * Set up segment registers for real mode, a small stack for
   59          * any calls we make, and clear any flags.
   60          */
   61         cli                             /* make sure no interrupts */
   62         mov     %cs, %ax                /* copy %cs to %ds.  Remember these */
   63         mov     %ax, %ds                /* are offsets rather than selectors */
   64         mov     %ax, %ss
   65         movw    $PAGE_SIZE, %sp
   66         xorw    %ax, %ax
   67         pushw   %ax
   68         popfw
   69 
   70         /* To debug resume hangs, beep the speaker if the user requested. */
   71         testb   $~0, resume_beep - wakeup_start
   72         jz      1f
   73         movb    $0, resume_beep - wakeup_start
   74         movb    $0xc0, %al
   75         outb    %al, $0x42
   76         movb    $0x04, %al
   77         outb    %al, $0x42
   78         inb     $0x61, %al
   79         orb     $0x3, %al
   80         outb    %al, $0x61
   81 1:
   82 
   83         /* Re-initialize video BIOS if the reset_video tunable is set. */
   84         testb   $~0, reset_video - wakeup_start
   85         jz      1f
   86         movb    $0, reset_video - wakeup_start
   87         lcall   $0xc000, $3
   88 
   89         /* When we reach here, int 0x10 should be ready.  Hide cursor. */
   90         movb    $0x01, %ah
   91         movb    $0x20, %ch
   92         int     $0x10
   93 
   94         /* Re-start in case the previous BIOS call clobbers them. */
   95         jmp     wakeup_start
   96 1:
   97 
   98         /*
   99          * Find relocation base and patch the gdt descript and ljmp targets
  100          */
  101         xorl    %ebx, %ebx
  102         mov     %cs, %bx
  103         sall    $4, %ebx                /* %ebx is now our relocation base */
  104 
  105         /*
  106          * Load the descriptor table pointer.  We'll need it when running
  107          * in 16-bit protected mode.
  108          */
  109         lgdtl   bootgdtdesc - wakeup_start
  110 
  111         /* Enable protected mode */
  112         movl    $CR0_PE, %eax
  113         mov     %eax, %cr0
  114 
  115         /*
  116          * Now execute a far jump to turn on protected mode.  This
  117          * causes the segment registers to turn into selectors and causes
  118          * %cs to be loaded from the gdt.
  119          *
  120          * The following instruction is:
  121          * ljmpl $bootcode32 - bootgdt, $wakeup_32 - wakeup_start
  122          * but gas cannot assemble that.  And besides, we patch the targets
  123          * in early startup and its a little clearer what we are patching.
  124          */
  125 wakeup_sw32:
  126         .byte   0x66                    /* size override to 32 bits */
  127         .byte   0xea                    /* opcode for far jump */
  128         .long   wakeup_32 - wakeup_start /* offset in segment */
  129         .word   bootcode32 - bootgdt    /* index in gdt for 32 bit code */
  130 
  131         /*
  132          * At this point, we are running in 32 bit legacy protected mode.
  133          */
  134         ALIGN_TEXT
  135         .code32
  136 wakeup_32:
  137 
  138         mov     $bootdata32 - bootgdt, %eax
  139         mov     %ax, %ds
  140 
  141         /* Turn on the PAE and PSE bits for when paging is enabled */
  142         mov     %cr4, %eax
  143         orl     $(CR4_PAE | CR4_PSE), %eax
  144         mov     %eax, %cr4
  145 
  146         /*
  147          * Enable EFER.LME so that we get long mode when all the prereqs are
  148          * in place.  In this case, it turns on when CR0_PG is finally enabled.
  149          * Pick up a few other EFER bits that we'll use need we're here.
  150          */
  151         movl    $MSR_EFER, %ecx
  152         rdmsr
  153         orl     $EFER_LME | EFER_SCE, %eax
  154         wrmsr
  155 
  156         /*
  157          * Point to the embedded page tables for startup.  Note that this
  158          * only gets accessed after we're actually in 64 bit mode, however
  159          * we can only set the bottom 32 bits of %cr3 in this state.  This
  160          * means we are required to use a temporary page table that is below
  161          * the 4GB limit.  %ebx is still our relocation base.  We could just
  162          * subtract 3 * PAGE_SIZE, but that would be too easy.
  163          */
  164         leal    wakeup_pagetables - wakeup_start(%ebx), %eax
  165         movl    (%eax), %eax
  166         mov     %eax, %cr3
  167 
  168         /*
  169          * Finally, switch to long bit mode by enabling paging.  We have
  170          * to be very careful here because all the segmentation disappears
  171          * out from underneath us.  The spec says we can depend on the
  172          * subsequent pipelined branch to execute, but *only if* everthing
  173          * is still identity mapped.  If any mappings change, the pipeline
  174          * will flush.
  175          */
  176         mov     %cr0, %eax
  177         orl     $CR0_PG, %eax
  178         mov     %eax, %cr0
  179 
  180         /*
  181          * At this point paging is enabled, and we are in "compatability" mode.
  182          * We do another far jump to reload %cs with the 64 bit selector.
  183          * %cr3 points to a 4-level page table page.
  184          * We cannot yet jump all the way to the kernel because we can only
  185          * specify a 32 bit linear address.  So, yet another trampoline.
  186          *
  187          * The following instruction is:
  188          * ljmp $bootcode64 - bootgdt, $wakeup_64 - wakeup_start
  189          * but gas cannot assemble that.  And besides, we patch the targets
  190          * in early startup and its a little clearer what we are patching.
  191          */
  192 wakeup_sw64:
  193         .byte   0xea                    /* opcode for far jump */
  194         .long   wakeup_64 - wakeup_start /* offset in segment */
  195         .word   bootcode64 - bootgdt    /* index in gdt for 64 bit code */
  196 
  197         /*
  198          * Yeehar!  We're running in 64-bit mode!  We can mostly ignore our
  199          * segment registers, and get on with it.
  200          * Note that we are running at the correct virtual address, but with
  201          * a 1:1 1GB mirrored mapping over entire address space.  We had better
  202          * switch to a real %cr3 promptly so that we can get to the direct map
  203          * space. Remember that jmp is relative and that we've been relocated,
  204          * so use an indirect jump.
  205          */
  206         ALIGN_TEXT
  207         .code64
  208 wakeup_64:
  209         mov     $bootdata64 - bootgdt, %eax
  210         mov     %ax, %ds
  211 
  212         /* Restore arguments and return. */
  213         movq    wakeup_kpml4 - wakeup_start(%rbx), %rdi
  214         movq    wakeup_ctx - wakeup_start(%rbx), %rsi
  215         movq    wakeup_retaddr - wakeup_start(%rbx), %rax
  216         jmp     *%rax
  217 
  218         .data
  219 
  220 resume_beep:
  221         .byte   0
  222 reset_video:
  223         .byte   0
  224 
  225         ALIGN_DATA
  226 bootgdt:
  227         .long   0x00000000
  228         .long   0x00000000
  229         .long   0x00000000
  230         .long   0x00000000
  231         .long   0x00000000
  232         .long   0x00000000
  233         .long   0x00000000
  234         .long   0x00000000
  235 
  236 bootcode64:
  237         .long   0x0000ffff
  238         .long   0x00af9b00
  239 
  240 bootdata64:
  241         .long   0x0000ffff
  242         .long   0x00af9300
  243 
  244 bootcode32:
  245         .long   0x0000ffff
  246         .long   0x00cf9b00
  247 
  248 bootdata32:
  249         .long   0x0000ffff
  250         .long   0x00cf9300
  251 bootgdtend:
  252 
  253 wakeup_pagetables:
  254         .long   0
  255 
  256 bootgdtdesc:
  257         .word   bootgdtend - bootgdt    /* Length */
  258         .long   bootgdt - wakeup_start  /* Offset plus %ds << 4 */
  259 
  260         ALIGN_DATA
  261 wakeup_retaddr:
  262         .quad   0
  263 wakeup_kpml4:
  264         .quad   0
  265 
  266 wakeup_ctx:
  267         .quad   0
  268 wakeup_pcb:
  269         .quad   0
  270 wakeup_gdt:
  271         .word   0
  272         .quad   0
  273 wakeup_fpusave:
  274         .quad   0
  275 
  276         ALIGN_DATA
  277 wakeup_efer:
  278         .quad   0
  279 wakeup_star:
  280         .quad   0
  281 wakeup_lstar:
  282         .quad   0
  283 wakeup_cstar:
  284         .quad   0
  285 wakeup_sfmask:
  286         .quad   0
  287 wakeup_cpu:
  288         .long   0
  289 dummy:

Cache object: aad62d7372f3469b2db5d23aa3fe43cb


[ 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.