Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 53768
b: refs/heads/master
c: 275f551
h: refs/heads/master
v: v3
  • Loading branch information
Vivek Goyal authored and Andi Kleen committed May 2, 2007
1 parent 464d6d1 commit 5bf2c88
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 73 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7db681d7e4038ad205b5face5cf7f7815633e1b5
refs/heads/master: 275f55170ec2b5d777b070cb8ab9e5d58e65a2a8
112 changes: 40 additions & 72 deletions trunk/arch/x86_64/kernel/acpi/wakeup.S
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ wakeup_code:
cld
# setup data segment
movw %cs, %ax
movw %ax, %ds # Make ds:0 point to wakeup_start
movw %ax, %ds # Make ds:0 point to wakeup_start
movw %ax, %ss
mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board
# Private stack is needed for ASUS board
mov $(wakeup_stack - wakeup_code), %sp

pushl $0 # Kill any dangerous flags
pushl $0 # Kill any dangerous flags
popfl

movl real_magic - wakeup_code, %eax
Expand All @@ -45,7 +46,7 @@ wakeup_code:
jz 1f
lcall $0xc000,$3
movw %cs, %ax
movw %ax, %ds # Bios might have played with that
movw %ax, %ds # Bios might have played with that
movw %ax, %ss
1:

Expand Down Expand Up @@ -75,9 +76,12 @@ wakeup_code:
jmp 1f
1:

.byte 0x66, 0xea # prefix + jmpi-opcode
.long wakeup_32 - __START_KERNEL_map
.word __KERNEL_CS
ljmpl *(wakeup_32_vector - wakeup_code)

.balign 4
wakeup_32_vector:
.long wakeup_32 - __START_KERNEL_map
.word __KERNEL32_CS, 0

.code32
wakeup_32:
Expand All @@ -96,102 +100,77 @@ wakeup_32:
jnc bogus_cpu
movl %edx,%edi

movw $__KERNEL_DS, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movl $__KERNEL_DS, %eax
movl %eax, %ds

movw $__KERNEL_DS, %ax
movw %ax, %ss

mov $(wakeup_stack - __START_KERNEL_map), %esp
movl saved_magic - __START_KERNEL_map, %eax
cmpl $0x9abcdef0, %eax
jne bogus_32_magic

movw $0x0e00 + 'i', %ds:(0xb8012)
movb $0xa8, %al ; outb %al, $0x80;

/*
* Prepare for entering 64bits mode
*/

/* Enable PAE mode and PGE */
/* Enable PAE */
xorl %eax, %eax
btsl $5, %eax
btsl $7, %eax
movl %eax, %cr4

/* Setup early boot stage 4 level pagetables */
movl $(wakeup_level4_pgt - __START_KERNEL_map), %eax
movl %eax, %cr3

/* Setup EFER (Extended Feature Enable Register) */
movl $MSR_EFER, %ecx
rdmsr
/* Fool rdmsr and reset %eax to avoid dependences */
xorl %eax, %eax
/* Enable Long Mode */
xorl %eax, %eax
btsl $_EFER_LME, %eax
/* Enable System Call */
btsl $_EFER_SCE, %eax

/* No Execute supported? */
/* No Execute supported? */
btl $20,%edi
jnc 1f
btsl $_EFER_NX, %eax
1:

/* Make changes effective */
1: movl $MSR_EFER, %ecx
xorl %edx, %edx
wrmsr
wbinvd

xorl %eax, %eax
btsl $31, %eax /* Enable paging and in turn activate Long Mode */
btsl $0, %eax /* Enable protected mode */
btsl $1, %eax /* Enable MP */
btsl $4, %eax /* Enable ET */
btsl $5, %eax /* Enable NE */
btsl $16, %eax /* Enable WP */
btsl $18, %eax /* Enable AM */

/* Make changes effective */
movl %eax, %cr0

/* At this point:
CR4.PAE must be 1
CS.L must be 0
CR3 must point to PML4
Next instruction must be a branch
This must be on identity-mapped page
*/
jmp reach_compatibility_mode
reach_compatibility_mode:
movw $0x0e00 + 'i', %ds:(0xb8012)
movb $0xa8, %al ; outb %al, $0x80;

/*
* At this point we're in long mode but in 32bit compatibility mode
* with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
* EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we load
* the new gdt/idt that has __KERNEL_CS with CS.L = 1.
*/

movw $0x0e00 + 'n', %ds:(0xb8014)
movb $0xa9, %al ; outb %al, $0x80

/* Load new GDT with the 64bit segment using 32bit descriptor */
movl $(pGDT32 - __START_KERNEL_map), %eax
lgdt (%eax)

movl $(wakeup_jumpvector - __START_KERNEL_map), %eax
/* Finally jump in 64bit mode */
ljmp *(%eax)
ljmp *(wakeup_long64_vector - __START_KERNEL_map)

wakeup_jumpvector:
.long wakeup_long64 - __START_KERNEL_map
.word __KERNEL_CS
.balign 4
wakeup_long64_vector:
.long wakeup_long64 - __START_KERNEL_map
.word __KERNEL_CS, 0

.code64

/* Hooray, we are in Long 64-bit mode (but still running in low memory) */
/* Hooray, we are in Long 64-bit mode (but still running in
* low memory)
*/
wakeup_long64:
/*
* We must switch to a new descriptor in kernel space for the GDT
Expand All @@ -201,6 +180,9 @@ wakeup_long64:
*/
lgdt cpu_gdt_descr - __START_KERNEL_map

movw $0x0e00 + 'n', %ds:(0xb8014)
movb $0xa9, %al ; outb %al, $0x80

movw $0x0e00 + 'u', %ds:(0xb8016)

nop
Expand All @@ -227,33 +209,19 @@ wakeup_long64:

.align 64
gdta:
/* Its good to keep gdt in sync with one in trampoline.S */
.word 0, 0, 0, 0 # dummy

.word 0, 0, 0, 0 # unused

.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9B00 # code read/exec. ??? Why I need 0x9B00 (as opposed to 0x9A00 in order for this to work?)
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)

.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
.word 0x9200 # data read/write
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)
# this is 64bit descriptor for code
.word 0xFFFF
.word 0
.word 0x9A00 # code read/exec
.word 0x00AF # as above, but it is long mode and with D=0
/* ??? Why I need the accessed bit set in order for this to work? */
.quad 0x00cf9b000000ffff # __KERNEL32_CS
.quad 0x00af9b000000ffff # __KERNEL_CS
.quad 0x00cf93000000ffff # __KERNEL_DS

idt_48a:
.word 0 # idt limit = 0
.word 0, 0 # idt base = 0L

gdt_48a:
.word 0x8000 # gdt limit=2048,
.word 0x800 # gdt limit=2048,
# 256 GDT entries
.word 0, 0 # gdt base (filled in later)

Expand All @@ -263,7 +231,7 @@ video_mode: .quad 0
video_flags: .quad 0

bogus_real_magic:
movb $0xba,%al ; outb %al,$0x80
movb $0xba,%al ; outb %al,$0x80
jmp bogus_real_magic

bogus_32_magic:
Expand Down

0 comments on commit 5bf2c88

Please sign in to comment.