| .. | .. |
|---|
| 10 | 10 | * needs to be able to service interrupts. |
|---|
| 11 | 11 | * |
|---|
| 12 | 12 | * On the plus side, we don't have to worry about mangling 64-bit |
|---|
| 13 | | - * addresses into 32-bits because we're executing with an identify |
|---|
| 13 | + * addresses into 32-bits because we're executing with an identity |
|---|
| 14 | 14 | * mapped pagetable and haven't transitioned to 64-bit virtual addresses |
|---|
| 15 | 15 | * yet. |
|---|
| 16 | 16 | */ |
|---|
| .. | .. |
|---|
| 23 | 23 | |
|---|
| 24 | 24 | .code64 |
|---|
| 25 | 25 | .text |
|---|
| 26 | | -ENTRY(efi64_thunk) |
|---|
| 26 | +SYM_FUNC_START(__efi64_thunk) |
|---|
| 27 | 27 | push %rbp |
|---|
| 28 | 28 | push %rbx |
|---|
| 29 | 29 | |
|---|
| 30 | | - subq $8, %rsp |
|---|
| 31 | | - leaq efi_exit32(%rip), %rax |
|---|
| 32 | | - movl %eax, 4(%rsp) |
|---|
| 33 | | - leaq efi_gdt64(%rip), %rax |
|---|
| 34 | | - movl %eax, (%rsp) |
|---|
| 35 | | - movl %eax, 2(%rax) /* Fixup the gdt base address */ |
|---|
| 30 | + leaq 1f(%rip), %rbp |
|---|
| 36 | 31 | |
|---|
| 37 | 32 | movl %ds, %eax |
|---|
| 38 | 33 | push %rax |
|---|
| .. | .. |
|---|
| 48 | 43 | movl %esi, 0x0(%rsp) |
|---|
| 49 | 44 | movl %edx, 0x4(%rsp) |
|---|
| 50 | 45 | movl %ecx, 0x8(%rsp) |
|---|
| 51 | | - movq %r8, %rsi |
|---|
| 52 | | - movl %esi, 0xc(%rsp) |
|---|
| 53 | | - movq %r9, %rsi |
|---|
| 54 | | - movl %esi, 0x10(%rsp) |
|---|
| 46 | + movl %r8d, 0xc(%rsp) |
|---|
| 47 | + movl %r9d, 0x10(%rsp) |
|---|
| 55 | 48 | |
|---|
| 56 | | - sgdt save_gdt(%rip) |
|---|
| 57 | | - |
|---|
| 58 | | - leaq 1f(%rip), %rbx |
|---|
| 59 | | - movq %rbx, func_rt_ptr(%rip) |
|---|
| 49 | + leaq 0x14(%rsp), %rbx |
|---|
| 50 | + sgdt (%rbx) |
|---|
| 60 | 51 | |
|---|
| 61 | 52 | /* |
|---|
| 62 | 53 | * Switch to gdt with 32-bit segments. This is the firmware GDT |
|---|
| 63 | 54 | * that was installed when the kernel started executing. This |
|---|
| 64 | 55 | * pointer was saved at the EFI stub entry point in head_64.S. |
|---|
| 56 | + * |
|---|
| 57 | + * Pass the saved DS selector to the 32-bit code, and use far return to |
|---|
| 58 | + * restore the saved CS selector. |
|---|
| 65 | 59 | */ |
|---|
| 66 | 60 | leaq efi32_boot_gdt(%rip), %rax |
|---|
| 67 | 61 | lgdt (%rax) |
|---|
| 68 | 62 | |
|---|
| 69 | | - pushq $__KERNEL_CS |
|---|
| 63 | + movzwl efi32_boot_ds(%rip), %edx |
|---|
| 64 | + movzwq efi32_boot_cs(%rip), %rax |
|---|
| 65 | + pushq %rax |
|---|
| 70 | 66 | leaq efi_enter32(%rip), %rax |
|---|
| 71 | 67 | pushq %rax |
|---|
| 72 | 68 | lretq |
|---|
| 73 | 69 | |
|---|
| 74 | 70 | 1: addq $32, %rsp |
|---|
| 75 | | - |
|---|
| 76 | | - lgdt save_gdt(%rip) |
|---|
| 71 | + movq %rdi, %rax |
|---|
| 77 | 72 | |
|---|
| 78 | 73 | pop %rbx |
|---|
| 79 | 74 | movl %ebx, %ss |
|---|
| .. | .. |
|---|
| 81 | 76 | movl %ebx, %es |
|---|
| 82 | 77 | pop %rbx |
|---|
| 83 | 78 | movl %ebx, %ds |
|---|
| 79 | + /* Clear out 32-bit selector from FS and GS */ |
|---|
| 80 | + xorl %ebx, %ebx |
|---|
| 81 | + movl %ebx, %fs |
|---|
| 82 | + movl %ebx, %gs |
|---|
| 84 | 83 | |
|---|
| 85 | 84 | /* |
|---|
| 86 | 85 | * Convert 32-bit status code into 64-bit. |
|---|
| 87 | 86 | */ |
|---|
| 88 | | - test %rax, %rax |
|---|
| 89 | | - jz 1f |
|---|
| 90 | | - movl %eax, %ecx |
|---|
| 91 | | - andl $0x0fffffff, %ecx |
|---|
| 92 | | - andl $0xf0000000, %eax |
|---|
| 93 | | - shl $32, %rax |
|---|
| 94 | | - or %rcx, %rax |
|---|
| 95 | | -1: |
|---|
| 96 | | - addq $8, %rsp |
|---|
| 87 | + roll $1, %eax |
|---|
| 88 | + rorq $1, %rax |
|---|
| 89 | + |
|---|
| 97 | 90 | pop %rbx |
|---|
| 98 | 91 | pop %rbp |
|---|
| 99 | | - ret |
|---|
| 100 | | -ENDPROC(efi64_thunk) |
|---|
| 101 | | - |
|---|
| 102 | | -ENTRY(efi_exit32) |
|---|
| 103 | | - movq func_rt_ptr(%rip), %rax |
|---|
| 104 | | - push %rax |
|---|
| 105 | | - mov %rdi, %rax |
|---|
| 106 | | - ret |
|---|
| 107 | | -ENDPROC(efi_exit32) |
|---|
| 92 | + RET |
|---|
| 93 | +SYM_FUNC_END(__efi64_thunk) |
|---|
| 108 | 94 | |
|---|
| 109 | 95 | .code32 |
|---|
| 110 | 96 | /* |
|---|
| .. | .. |
|---|
| 112 | 98 | * |
|---|
| 113 | 99 | * The stack should represent the 32-bit calling convention. |
|---|
| 114 | 100 | */ |
|---|
| 115 | | -ENTRY(efi_enter32) |
|---|
| 116 | | - movl $__KERNEL_DS, %eax |
|---|
| 117 | | - movl %eax, %ds |
|---|
| 118 | | - movl %eax, %es |
|---|
| 119 | | - movl %eax, %ss |
|---|
| 101 | +SYM_FUNC_START_LOCAL(efi_enter32) |
|---|
| 102 | + /* Load firmware selector into data and stack segment registers */ |
|---|
| 103 | + movl %edx, %ds |
|---|
| 104 | + movl %edx, %es |
|---|
| 105 | + movl %edx, %fs |
|---|
| 106 | + movl %edx, %gs |
|---|
| 107 | + movl %edx, %ss |
|---|
| 120 | 108 | |
|---|
| 121 | 109 | /* Reload pgtables */ |
|---|
| 122 | 110 | movl %cr3, %eax |
|---|
| .. | .. |
|---|
| 144 | 132 | */ |
|---|
| 145 | 133 | cli |
|---|
| 146 | 134 | |
|---|
| 147 | | - movl 56(%esp), %eax |
|---|
| 148 | | - movl %eax, 2(%eax) |
|---|
| 149 | | - lgdtl (%eax) |
|---|
| 135 | + lgdtl (%ebx) |
|---|
| 150 | 136 | |
|---|
| 151 | 137 | movl %cr4, %eax |
|---|
| 152 | 138 | btsl $(X86_CR4_PAE_BIT), %eax |
|---|
| .. | .. |
|---|
| 163 | 149 | xorl %eax, %eax |
|---|
| 164 | 150 | lldt %ax |
|---|
| 165 | 151 | |
|---|
| 166 | | - movl 60(%esp), %eax |
|---|
| 167 | 152 | pushl $__KERNEL_CS |
|---|
| 168 | | - pushl %eax |
|---|
| 153 | + pushl %ebp |
|---|
| 169 | 154 | |
|---|
| 170 | 155 | /* Enable paging */ |
|---|
| 171 | 156 | movl %cr0, %eax |
|---|
| 172 | 157 | btsl $X86_CR0_PG_BIT, %eax |
|---|
| 173 | 158 | movl %eax, %cr0 |
|---|
| 174 | 159 | lret |
|---|
| 175 | | -ENDPROC(efi_enter32) |
|---|
| 160 | +SYM_FUNC_END(efi_enter32) |
|---|
| 176 | 161 | |
|---|
| 177 | 162 | .data |
|---|
| 178 | 163 | .balign 8 |
|---|
| 179 | | - .global efi32_boot_gdt |
|---|
| 180 | | -efi32_boot_gdt: .word 0 |
|---|
| 181 | | - .quad 0 |
|---|
| 182 | | - |
|---|
| 183 | | -save_gdt: .word 0 |
|---|
| 184 | | - .quad 0 |
|---|
| 185 | | -func_rt_ptr: .quad 0 |
|---|
| 186 | | - |
|---|
| 187 | | - .global efi_gdt64 |
|---|
| 188 | | -efi_gdt64: |
|---|
| 189 | | - .word efi_gdt64_end - efi_gdt64 |
|---|
| 190 | | - .long 0 /* Filled out by user */ |
|---|
| 164 | +SYM_DATA_START(efi32_boot_gdt) |
|---|
| 191 | 165 | .word 0 |
|---|
| 192 | | - .quad 0x0000000000000000 /* NULL descriptor */ |
|---|
| 193 | | - .quad 0x00af9a000000ffff /* __KERNEL_CS */ |
|---|
| 194 | | - .quad 0x00cf92000000ffff /* __KERNEL_DS */ |
|---|
| 195 | | - .quad 0x0080890000000000 /* TS descriptor */ |
|---|
| 196 | | - .quad 0x0000000000000000 /* TS continued */ |
|---|
| 197 | | -efi_gdt64_end: |
|---|
| 166 | + .quad 0 |
|---|
| 167 | +SYM_DATA_END(efi32_boot_gdt) |
|---|
| 168 | + |
|---|
| 169 | +SYM_DATA_START(efi32_boot_cs) |
|---|
| 170 | + .word 0 |
|---|
| 171 | +SYM_DATA_END(efi32_boot_cs) |
|---|
| 172 | + |
|---|
| 173 | +SYM_DATA_START(efi32_boot_ds) |
|---|
| 174 | + .word 0 |
|---|
| 175 | +SYM_DATA_END(efi32_boot_ds) |
|---|