1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
.code32 .text
#include <linux/init.h> #include <linux/linkage.h> #include <asm/segment.h> #include <asm/pgtable_types.h> #include <asm/page_types.h> #include <asm/boot.h> #include <asm/msr.h> #include <asm/processor-flags.h> #include <asm/asm-offsets.h>
.code64 .org 0x200 ENTRY(startup_64)
#ifdef CONFIG_EFI_STUB jmp preferred_addr
ENTRY(efi_pe_entry) mov %rcx, %rdi mov %rdx, %rsi pushq %rdi pushq %rsi call make_boot_params cmpq $0,%rax je 1f mov %rax, %rdx popq %rsi popq %rdi
ENTRY(efi_stub_entry) call efi_main movq %rax,%rsi cmpq $0,%rax jne 2f 1: /* EFI init failed, so hang. */ hlt jmp 1b 2: call 3f 3: popq %rax subq $3b, %rax subq BP_pref_address(%rsi), %rax add BP_code32_start(%esi), %eax leaq preferred_addr(%rax), %rax jmp *%rax
preferred_addr: #endif
//段寄存器清零 xorl %eax, %eax movl %eax, %ds movl %eax, %es movl %eax, %ss movl %eax, %fs movl %eax, %gs
/* * 如果kernel是可重定向的,则从2MB addr 对齐的加载地址解压并运行内核, * 否则从 LOAD_PHYSICAL_ADDR 解压并运行内核 */ #ifdef CONFIG_RELOCATABLE leaq startup_32(%rip) /* - $startup_32 */, %rbp movl BP_kernel_alignment(%rsi), %eax decl %eax addq %rax, %rbp notq %rax andq %rax, %rbp #else movq $LOAD_PHYSICAL_ADDR, %rbp #endif
/* * 读取 boot_params.init_size ,得到 kernel initialization size * 减去 _end ,得到起始地址,再加上实际的起始偏移量,得到: * 内核重定位后的起始地址,保存到 rbx */ leaq z_extract_offset(%rbp), %rbx
/* Set up the stack */ leaq boot_stack_end(%rbx), %rsp
/* Zero EFLAGS */ pushq $0 popfq
/* * Copy the compressed kernel to the end of our buffer * where decompression in place becomes safe. */ pushq %rsi leaq (_bss-8)(%rip), %rsi leaq (_bss-8)(%rbx), %rdi movq $_bss /* - $startup_32 */, %rcx shrq $3, %rcx std rep movsq cld popq %rsi
/* * Jump to the relocated address. */ leaq relocated(%rbx), %rax jmp *%rax
.text relocated:
/* * Clear BSS (stack is currently empty) */ xorl %eax, %eax leaq _bss(%rip), %rdi leaq _ebss(%rip), %rcx subq %rdi, %rcx shrq $3, %rcx rep stosq
/* * Adjust our own GOT */ leaq _got(%rip), %rdx leaq _egot(%rip), %rcx 1: cmpq %rcx, %rdx jae 2f addq %rbx, (%rdx) addq $8, %rdx jmp 1b 2: /* * Do the decompression, and jump to the new kernel.. */ pushq %rsi /* Save the real mode argument */ movq %rsi, %rdi /* real mode address */ leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ leaq input_data(%rip), %rdx /* input_data */ movl $z_input_len, %ecx /* input_len */ movq %rbp, %r8 /* output target address */ //调用函数 call decompress_kernel popq %rsi
/* * Jump to the decompressed kernel. */ jmp *%rbp
.code32 no_longmode: /* This isn't an x86-64 CPU so hang */ 1: hlt jmp 1b
#include "../../kernel/verify_cpu.S"
.data gdt: .word gdt_end - gdt .long gdt .word 0 .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x00af9a000000ffff /* __KERNEL_CS */ .quad 0x00cf92000000ffff /* __KERNEL_DS */ .quad 0x0080890000000000 /* TS descriptor */ .quad 0x0000000000000000 /* TS continued */ gdt_end:
/* * Stack and heap for uncompression */ .bss .balign 4 boot_heap: .fill BOOT_HEAP_SIZE, 1, 0 boot_stack: .fill BOOT_STACK_SIZE, 1, 0 boot_stack_end:
/* * Space for page tables (not in .bss so not zeroed) */ .section ".pgtable","a",@nobits .balign 4096 pgtable: .fill 6*4096, 1, 0
|