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-2012 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$
   30  */
   31 
   32 #include <machine/asmacros.h>
   33 #include <machine/ppireg.h>
   34 #include <machine/specialreg.h>
   35 #include <machine/timerreg.h>
   36 
   37 #include "assym.inc"
   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         .code16
   58 wakeup_start:
   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         mov     %cs, %ax                /* copy %cs to %ds.  Remember these */
   65         mov     %ax, %ds                /* are offsets rather than selectors */
   66         mov     %ax, %ss
   67         movw    $PAGE_SIZE, %sp
   68         xorw    %ax, %ax
   69         pushw   %ax
   70         popfw
   71 
   72         /* To debug resume hangs, beep the speaker if the user requested. */
   73         testb   $~0, resume_beep - wakeup_start
   74         jz      1f
   75         movb    $0, resume_beep - wakeup_start
   76 
   77         /* Set PIC timer2 to beep. */
   78         movb    $(TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT), %al
   79         outb    %al, $TIMER_MODE
   80 
   81         /* Turn on speaker. */
   82         inb     $IO_PPI, %al
   83         orb     $PIT_SPKR, %al
   84         outb    %al, $IO_PPI
   85 
   86         /* Set frequency. */
   87         movw    $0x4c0, %ax
   88         outb    %al, $TIMER_CNTR2
   89         shrw    $8, %ax
   90         outb    %al, $TIMER_CNTR2
   91 1:
   92 
   93         /* Re-initialize video BIOS if the reset_video tunable is set. */
   94         testb   $~0, reset_video - wakeup_start
   95         jz      1f
   96         movb    $0, reset_video - wakeup_start
   97         lcall   $0xc000, $3
   98 
   99         /* When we reach here, int 0x10 should be ready.  Hide cursor. */
  100         movb    $0x01, %ah
  101         movb    $0x20, %ch
  102         int     $0x10
  103 
  104         /* Re-start in case the previous BIOS call clobbers them. */
  105         jmp     wakeup_start
  106 1:
  107 
  108         /*
  109          * Find relocation base and patch the gdt descript and ljmp targets
  110          */
  111         xorl    %ebx, %ebx
  112         mov     %cs, %bx
  113         sall    $4, %ebx                /* %ebx is now our relocation base */
  114 
  115         /*
  116          * Load the descriptor table pointer.  We'll need it when running
  117          * in 16-bit protected mode.
  118          */
  119         lgdtl   bootgdtdesc - wakeup_start
  120 
  121         /* Enable protected mode */
  122         movl    $CR0_PE, %eax
  123         mov     %eax, %cr0
  124 
  125         /*
  126          * Now execute a far jump to turn on protected mode.  This
  127          * causes the segment registers to turn into selectors and causes
  128          * %cs to be loaded from the gdt.
  129          *
  130          * The following instruction is:
  131          * ljmpl $bootcode32 - bootgdt, $wakeup_32 - wakeup_start
  132          * but gas cannot assemble that.  And besides, we patch the targets
  133          * in early startup and its a little clearer what we are patching.
  134          */
  135 wakeup_sw32:
  136         .byte   0x66                    /* size override to 32 bits */
  137         .byte   0xea                    /* opcode for far jump */
  138         .long   wakeup_32 - wakeup_start /* offset in segment */
  139         .word   bootcode32 - bootgdt    /* index in gdt for 32 bit code */
  140 
  141         /*
  142          * At this point, we are running in 32 bit legacy protected mode.
  143          */
  144         ALIGN_TEXT
  145         .code32
  146 wakeup_32:
  147 
  148         mov     $bootdata32 - bootgdt, %eax
  149         mov     %ax, %ds
  150 
  151         /*
  152          * Turn on the PAE bit and optionally the LA57 bit for when paging
  153          * is later enabled.
  154          */
  155         mov     %cr4, %eax
  156         orl     $CR4_PAE, %eax
  157         leal    wakeup_pagetables - wakeup_start(%ebx), %ecx
  158         movl    (%ecx), %ecx
  159         testl   $0x1, %ecx
  160         je      1f
  161         orl     $CR4_LA57, %eax
  162 1:      mov     %eax, %cr4
  163 
  164         /*
  165          * Enable EFER.LME so that we get long mode when all the prereqs are
  166          * in place.  In this case, it turns on when CR0_PG is finally enabled.
  167          * Also it picks up a few other EFER bits that we'll use need we're
  168          * here, like SYSCALL and NX enable.
  169          */
  170         movl    $MSR_EFER, %ecx
  171         movl    wakeup_efer - wakeup_start(%ebx), %eax
  172         movl    wakeup_efer + 4 - wakeup_start(%ebx), %edx
  173         wrmsr
  174 
  175         /*
  176          * Point to the embedded page tables for startup.  Note that this
  177          * only gets accessed after we're actually in 64 bit mode, however
  178          * we can only set the bottom 32 bits of %cr3 in this state.  This
  179          * means we are required to use a temporary page table that is below
  180          * the 4GB limit.  %ebx is still our relocation base.  We could just
  181          * subtract 3 * PAGE_SIZE, but that would be too easy.
  182          */
  183         leal    wakeup_pagetables - wakeup_start(%ebx), %eax
  184         movl    (%eax), %eax
  185         andl    $~0x1, %eax
  186         mov     %eax, %cr3
  187 
  188         /*
  189          * Finally, switch to long bit mode by enabling paging.  We have
  190          * to be very careful here because all the segmentation disappears
  191          * out from underneath us.  The spec says we can depend on the
  192          * subsequent pipelined branch to execute, but *only if* everything
  193          * is still identity mapped.  If any mappings change, the pipeline
  194          * will flush.
  195          */
  196         mov     %cr0, %eax
  197         orl     $CR0_PG, %eax
  198         mov     %eax, %cr0
  199 
  200         /*
  201          * At this point paging is enabled, and we are in "compatibility" mode.
  202          * We do another far jump to reload %cs with the 64 bit selector.
  203          * %cr3 points to a 4-level page table page.
  204          * We cannot yet jump all the way to the kernel because we can only
  205          * specify a 32 bit linear address.  So, yet another trampoline.
  206          *
  207          * The following instruction is:
  208          * ljmp $bootcode64 - bootgdt, $wakeup_64 - wakeup_start
  209          * but gas cannot assemble that.  And besides, we patch the targets
  210          * in early startup and its a little clearer what we are patching.
  211          */
  212 wakeup_sw64:
  213         .byte   0xea                    /* opcode for far jump */
  214         .long   wakeup_64 - wakeup_start /* offset in segment */
  215         .word   bootcode64 - bootgdt    /* index in gdt for 64 bit code */
  216 
  217         /*
  218          * Yeehar!  We're running in 64-bit mode!  We can mostly ignore our
  219          * segment registers, and get on with it.
  220          * Note that we are running at the correct virtual address, but with
  221          * a 1:1 1GB mirrored mapping over entire address space.  We had better
  222          * switch to a real %cr3 promptly so that we can get to the direct map
  223          * space. Remember that jmp is relative and that we've been relocated,
  224          * so use an indirect jump.
  225          */
  226         ALIGN_TEXT
  227         .code64
  228 wakeup_64:
  229         mov     $bootdata64 - bootgdt, %eax
  230         mov     %ax, %ds
  231 
  232         /* Restore arguments. */
  233         movq    wakeup_pcb - wakeup_start(%rbx), %rdi
  234         movq    wakeup_ret - wakeup_start(%rbx), %rax
  235 
  236         /* Restore GDT. */
  237         lgdt    wakeup_gdt - wakeup_start(%rbx)
  238 
  239         /* Jump to return address. */
  240         jmp     *%rax
  241 
  242         .data
  243 
  244 resume_beep:
  245         .byte   0
  246 reset_video:
  247         .byte   0
  248 
  249         ALIGN_DATA
  250 bootgdt:
  251         .long   0x00000000
  252         .long   0x00000000
  253         .long   0x00000000
  254         .long   0x00000000
  255         .long   0x00000000
  256         .long   0x00000000
  257         .long   0x00000000
  258         .long   0x00000000
  259 
  260 bootcode64:
  261         .long   0x0000ffff
  262         .long   0x00af9b00
  263 
  264 bootdata64:
  265         .long   0x0000ffff
  266         .long   0x00af9300
  267 
  268 bootcode32:
  269         .long   0x0000ffff
  270         .long   0x00cf9b00
  271 
  272 bootdata32:
  273         .long   0x0000ffff
  274         .long   0x00cf9300
  275 bootgdtend:
  276 
  277 wakeup_pagetables:
  278         .long   0
  279 
  280 bootgdtdesc:
  281         .word   bootgdtend - bootgdt    /* Length */
  282         .long   bootgdt - wakeup_start  /* Offset plus %ds << 4 */
  283 
  284         ALIGN_DATA
  285 wakeup_pcb:
  286         .quad   0
  287 wakeup_ret:
  288         .quad   0
  289 wakeup_efer:
  290         .quad   0
  291 wakeup_gdt:
  292         .word   0
  293         .quad   0
  294 dummy:

Cache object: 6f90130fcd0d1a0ed8815022f50983fb


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