File tree Expand file tree Collapse file tree 4 files changed +59
-5
lines changed Expand file tree Collapse file tree 4 files changed +59
-5
lines changed Original file line number Diff line number Diff line change 5
5
#include <asm/msr-index.h>
6
6
#include <asm/page.h>
7
7
#include <asm/pgtable.h>
8
+ #include <asm/processor-flags.h>
8
9
9
10
.code16
10
11
.section ".header" , "a"
@@ -24,6 +25,11 @@ pmode_gdt: .quad 0
24
25
realmode_flags: .long 0
25
26
real_magic: .long 0
26
27
trampoline_segment: .word 0
28
+ _pad1: .byte 0
29
+ wakeup_jmp: .byte 0xea /* ljmpw */
30
+ wakeup_jmp_off: .word 3f
31
+ wakeup_jmp_seg: .word 0
32
+ wakeup_gdt: .quad 0 , 0 , 0
27
33
signature: .long 0x51ee1111
28
34
29
35
.text
@@ -34,11 +40,34 @@ _start:
34
40
cli
35
41
cld
36
42
43
+ /* Apparently some dimwit BIOS programmers don't know how to
44
+ program a PM to RM transition, and we might end up here with
45
+ junk in the data segment descriptor registers. The only way
46
+ to repair that is to go into PM and fix it ourselves... */
47
+ movw $16 , %cx
48
+ lgdtl %cs :wakeup_gdt
49
+ movl %cr0 , %eax
50
+ orb $X86_CR0_PE, %al
51
+ movl %eax , %cr0
52
+ jmp 1f
53
+ 1: ljmpw $8 , $2f
54
+ 2:
55
+ movw %cx , %ds
56
+ movw %cx , %es
57
+ movw %cx , %ss
58
+ movw %cx , %fs
59
+ movw %cx , %gs
60
+
61
+ andb $~X86_CR0_PE, %al
62
+ movl %eax , %cr0
63
+ jmp wakeup_jmp
64
+ 3:
37
65
/* Set up segments */
38
66
movw %cs , %ax
39
67
movw %ax , %ds
40
68
movw %ax , %es
41
69
movw %ax , %ss
70
+ lidtl wakeup_idt
42
71
43
72
movl $wakeup_stack_end, %esp
44
73
@@ -98,7 +127,14 @@ bogus_real_magic:
98
127
jmp 1b
99
128
100
129
.data
101
- .balign 4
130
+ .balign 8
131
+
132
+ /* This is the standard real-mode IDT */
133
+ wakeup_idt:
134
+ .word 0xffff /* limit */
135
+ .long 0 /* address */
136
+ .word 0
137
+
102
138
.globl HEAP, heap_end
103
139
HEAP:
104
140
.long wakeup_heap
Original file line number Diff line number Diff line change @@ -24,6 +24,11 @@ struct wakeup_header {
24
24
u32 realmode_flags ;
25
25
u32 real_magic ;
26
26
u16 trampoline_segment ; /* segment with trampoline code, 64-bit only */
27
+ u8 _pad1 ;
28
+ u8 wakeup_jmp ;
29
+ u16 wakeup_jmp_off ;
30
+ u16 wakeup_jmp_seg ;
31
+ u64 wakeup_gdt [3 ];
27
32
u32 signature ; /* To check we have correct structure */
28
33
} __attribute__((__packed__ ));
29
34
Original file line number Diff line number Diff line change @@ -50,6 +50,20 @@ int acpi_save_state_mem(void)
50
50
51
51
header -> video_mode = saved_video_mode ;
52
52
53
+ header -> wakeup_jmp_seg = acpi_wakeup_address >> 4 ;
54
+ /* GDT[0]: GDT self-pointer */
55
+ header -> wakeup_gdt [0 ] =
56
+ (u64 )(sizeof (header -> wakeup_gdt ) - 1 ) +
57
+ ((u64 )(acpi_wakeup_address +
58
+ ((char * )& header -> wakeup_gdt - (char * )acpi_realmode ))
59
+ << 16 );
60
+ /* GDT[1]: real-mode-like code segment */
61
+ header -> wakeup_gdt [1 ] = (0x009bULL << 40 ) +
62
+ ((u64 )acpi_wakeup_address << 16 ) + 0xffff ;
63
+ /* GDT[2]: real-mode-like data segment */
64
+ header -> wakeup_gdt [2 ] = (0x0093ULL << 40 ) +
65
+ ((u64 )acpi_wakeup_address << 16 ) + 0xffff ;
66
+
53
67
#ifndef CONFIG_64BIT
54
68
store_gdt ((struct desc_ptr * )& header -> pmode_gdt );
55
69
@@ -111,7 +125,7 @@ void __init acpi_reserve_bootmem(void)
111
125
return ;
112
126
}
113
127
114
- acpi_wakeup_address = acpi_realmode ;
128
+ acpi_wakeup_address = virt_to_phys (( void * ) acpi_realmode ) ;
115
129
}
116
130
117
131
Original file line number Diff line number Diff line change @@ -36,9 +36,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
36
36
if (!acpi_wakeup_address ) {
37
37
return - EFAULT ;
38
38
}
39
- acpi_set_firmware_waking_vector ((acpi_physical_address )
40
- virt_to_phys ((void * )
41
- acpi_wakeup_address ));
39
+ acpi_set_firmware_waking_vector (
40
+ (acpi_physical_address )acpi_wakeup_address );
42
41
43
42
}
44
43
ACPI_FLUSH_CPU_CACHE ();
You can’t perform that action at this time.
0 commit comments