[PATCH] x86-64: wakeup.S misc cleanups
authorVivek Goyal <vgoyal@in.ibm.com>
Wed, 2 May 2007 17:27:07 +0000 (19:27 +0200)
committerAndi Kleen <andi@basil.nowhere.org>
Wed, 2 May 2007 17:27:07 +0000 (19:27 +0200)
o Various cleanups. One of the main purpose of cleanups is that make
  wakeup.S as close as possible to trampoline.S.

o Following are the changes
- Indentations for comments.
- Changed the gdt table to compact form and to resemble the
  one in trampoline.S
- Take the jump to 32bit from real mode using ljmpl. Makes code
  more readable.
- After enabling long mode, directly take a long jump for 64bit
  mode. No need to take an extra jump to "reach_comaptibility_mode"
- Stack is not used after real mode. So don't load stack in
    32 bit mode.
- No need to enable PGE here.
- No need to do extra EFER read, anyway we trash the read contents.
- No need to enable system call (EFER_SCE). Anyway it will be
  enabled when original EFER is restored.
- No need to set MP, ET, NE, WP, AM bits in cr0. Very soon we will
     reload the original cr0 while restroing the processor state.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Vivek Goyal <vgoyal@in.ibm.com>
Signed-off-by: Andi Kleen <ak@suse.de>
arch/x86_64/kernel/acpi/wakeup.S

index 17dbeff64eefb04edaf96346e365f51e410a36d6..bd4c6f1a6f329bbf30d0d9ae3454946d970988ce 100644 (file)
@@ -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
@@ -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:
 
@@ -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:
@@ -96,65 +100,50 @@ 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
@@ -162,11 +151,6 @@ wakeup_32:
                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
@@ -174,24 +158,19 @@ reach_compatibility_mode:
         * 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
@@ -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
@@ -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)
        
@@ -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: