blob: 066c9b1a55e6d2c73f54e21dd436173ca949e196 [file] [log] [blame]
Bin Meng2b2d6662017-04-21 07:24:35 -07001/*
2 * Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
3 *
4 * From coreboot src/arch/x86/wakeup.S
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 */
8
9#include <asm/acpi_s3.h>
10#include <asm/processor.h>
11#include <asm/processor-flags.h>
12
13#define RELOCATED(x) ((x) - __wakeup + WAKEUP_BASE)
14
15#define CODE_SEG (X86_GDT_ENTRY_16BIT_CS * X86_GDT_ENTRY_SIZE)
16#define DATA_SEG (X86_GDT_ENTRY_16BIT_DS * X86_GDT_ENTRY_SIZE)
17
18 .code32
19 .globl __wakeup
20__wakeup:
21 /* First prepare the jmp to the resume vector */
22 mov 0x4(%esp), %eax /* vector */
23 /* last 4 bits of linear addr are taken as offset */
24 andw $0x0f, %ax
25 movw %ax, (__wakeup_offset)
26 mov 0x4(%esp), %eax
27 /* the rest is taken as segment */
28 shr $4, %eax
29 movw %ax, (__wakeup_segment)
30
31 /* Activate the right segment descriptor real mode */
32 ljmp $CODE_SEG, $RELOCATED(1f)
331:
34 /* 16 bit code from here on... */
35 .code16
36
37 /*
38 * Load the segment registers w/ properly configured segment
39 * descriptors. They will retain these configurations (limits,
40 * writability, etc.) once protected mode is turned off.
41 */
42 mov $DATA_SEG, %ax
43 mov %ax, %ds
44 mov %ax, %es
45 mov %ax, %fs
46 mov %ax, %gs
47 mov %ax, %ss
48
49 /* Turn off protection */
50 movl %cr0, %eax
51 andl $~X86_CR0_PE, %eax
52 movl %eax, %cr0
53
54 /* Now really going into real mode */
55 ljmp $0, $RELOCATED(1f)
561:
57 movw $0x0, %ax
58 movw %ax, %ds
59 movw %ax, %es
60 movw %ax, %ss
61 movw %ax, %fs
62 movw %ax, %gs
63
64 /*
65 * This is a FAR JMP to the OS waking vector.
66 * The C code changes the address to be correct.
67 */
68 .byte 0xea
69
70__wakeup_offset = RELOCATED(.)
71 .word 0x0000
72
73__wakeup_segment = RELOCATED(.)
74 .word 0x0000
75
76 .globl __wakeup_size
77__wakeup_size:
78 .long . - __wakeup