github.com/icexin/eggos@v0.4.2-0.20220216025428-78b167e4f349/boot/boot64.S (about)

     1  .code32
     2  
     3  .global _start
     4  _start:
     5  
     6  # zero 4 pages for our bootstrap page tables
     7    xor %eax, %eax
     8    mov $0x1000, %edi
     9    mov $0x5000, %ecx
    10    rep stosb
    11  
    12  # P4ML[0] -> 0x2000 (PDPT-A)
    13    mov $(0x2000 | 3), %eax
    14    mov %eax, 0x1000
    15  
    16  # P4ML[511] -> 0x3000 (PDPT-B)
    17    mov $(0x3000 | 3), %eax
    18    mov %eax, 0x1FF8
    19  
    20  # PDPT-A[0] -> 0x4000 (PD)
    21    mov $(0x4000 | 3), %eax
    22    mov %eax, 0x2000
    23  
    24  # PDPT-B[510] -> 0x4000 (PD)
    25    mov $(0x4000 | 3), %eax
    26    mov %eax, 0x3FF0
    27  
    28  # PD[0..511] -> 0..1022MB
    29    mov $0x83, %eax
    30    mov $0x4000, %ebx
    31    mov $512, %ecx
    32  ptbl_loop:
    33    mov %eax, (%ebx)
    34    add $0x200000, %eax # 2 MB
    35    add $0x8, %ebx
    36    dec %ecx
    37    jnz ptbl_loop
    38  
    39  # Clear ebx for initial processor boot.
    40  # When secondary processors boot, they'll call through
    41  # entry32mp (from entryother), but with a nonzero ebx.
    42  # We'll reuse these bootstrap pagetables and GDT.
    43    xor %ebx, %ebx
    44  
    45  .global entry32mp
    46  entry32mp:
    47  # CR3 -> 0x1000 (P4ML)
    48    mov $0x1000, %eax
    49    mov %eax, %cr3
    50  
    51    lgdt (gdtr64)
    52  
    53  # Enable PAE - CR4.PAE=1
    54    mov %cr4, %eax
    55    bts $5, %eax
    56    mov %eax, %cr4
    57  
    58  # enable long mode - EFER.LME=1
    59    mov $0xc0000080, %ecx
    60    rdmsr
    61    bts $8, %eax
    62    wrmsr
    63  
    64  # enable paging
    65    mov %cr0, %eax
    66    bts $31, %eax
    67    mov %eax, %cr0
    68  
    69  # shift to 64bit segment
    70    ljmp $8,$(entry64low)
    71  
    72  .align 16
    73  gdtr64:
    74    .word gdt64_end - gdt64_begin - 1;
    75    .quad gdt64_begin
    76  
    77  .align 16
    78  gdt64_begin:
    79    .long 0x00000000 # 0: null desc
    80    .long 0x00000000
    81    .long 0x00000000 # 1: Code, R/X, Nonconforming
    82    .long 0x00209800
    83    .long 0x00000000 # 2: Data, R/W, Expand Down
    84    .long 0x00009000
    85  gdt64_end:
    86  
    87  .align 16
    88  .code64
    89  entry64low:
    90    movq $entry64high, %rax
    91    jmp *%rax
    92  
    93  entry64high:
    94  
    95  # ensure data segment registers are sane
    96    xor %rax, %rax
    97    mov %ax, %ss
    98    mov %ax, %ds
    99    mov %ax, %es
   100    mov %ax, %fs
   101    mov %ax, %gs
   102  
   103  // # check to see if we're booting a secondary core
   104  //   test %ebx, %ebx
   105  //   jnz entry64mp
   106  
   107  # setup initial stack
   108  //   mov $0xFFFFFFFF80010000, %rax
   109  //   mov %rax, %rsp
   110  
   111  # enter boot64main()
   112  // %rdi, %rsi, %rdx, %rcx, %r8 and %r9 are args
   113    movl 4(%rsp), %edi
   114    movl 8(%rsp), %esi
   115    movl 12(%rsp), %edx
   116    jmp boot64main
   117  
   118  .global __deadloop
   119  __deadloop:
   120  # we should never return here...
   121    jmp .
   122  
   123  // entry64mp:
   124  // # obtain kstack from data block before entryother
   125  //   mov $0x7000, %rax
   126  //   mov -16(%rax), %rsp
   127  //   jmp mpenter
   128  
   129  .global wrmsr
   130  wrmsr:
   131    mov %rdi, %rcx     # arg0 -> msrnum
   132    mov %rsi, %rax     # val.low -> eax
   133    shr $32, %rsi
   134    mov %rsi, %rdx     # val.high -> edx
   135    wrmsr
   136    retq