xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

bootasm.S (2979B)


      1 #include "asm.h"
      2 #include "memlayout.h"
      3 #include "mmu.h"
      4 
      5 # Start the first CPU: switch to 32-bit protected mode, jump into C.
      6 # The BIOS loads this code from the first sector of the hard disk into
      7 # memory at physical address 0x7c00 and starts executing in real mode
      8 # with %cs=0 %ip=7c00.
      9 
     10 .code16                       # Assemble for 16-bit mode
     11 .globl start
     12 start:
     13   cli                         # BIOS enabled interrupts; disable
     14 
     15   # Zero data segment registers DS, ES, and SS.
     16   xorw    %ax,%ax             # Set %ax to zero
     17   movw    %ax,%ds             # -> Data Segment
     18   movw    %ax,%es             # -> Extra Segment
     19   movw    %ax,%ss             # -> Stack Segment
     20 
     21   # Physical address line A20 is tied to zero so that the first PCs 
     22   # with 2 MB would run software that assumed 1 MB.  Undo that.
     23 seta20.1:
     24   inb     $0x64,%al               # Wait for not busy
     25   testb   $0x2,%al
     26   jnz     seta20.1
     27 
     28   movb    $0xd1,%al               # 0xd1 -> port 0x64
     29   outb    %al,$0x64
     30 
     31 seta20.2:
     32   inb     $0x64,%al               # Wait for not busy
     33   testb   $0x2,%al
     34   jnz     seta20.2
     35 
     36   movb    $0xdf,%al               # 0xdf -> port 0x60
     37   outb    %al,$0x60
     38 
     39   # Switch from real to protected mode.  Use a bootstrap GDT that makes
     40   # virtual addresses map directly to physical addresses so that the
     41   # effective memory map doesn't change during the transition.
     42   lgdt    gdtdesc
     43   movl    %cr0, %eax
     44   orl     $CR0_PE, %eax
     45   movl    %eax, %cr0
     46 
     47 //PAGEBREAK!
     48   # Complete transition to 32-bit protected mode by using long jmp
     49   # to reload %cs and %eip.  The segment descriptors are set up with no
     50   # translation, so that the mapping is still the identity mapping.
     51   ljmp    $(SEG_KCODE<<3), $start32
     52 
     53 .code32  # Tell assembler to generate 32-bit code now.
     54 start32:
     55   # Set up the protected-mode data segment registers
     56   movw    $(SEG_KDATA<<3), %ax    # Our data segment selector
     57   movw    %ax, %ds                # -> DS: Data Segment
     58   movw    %ax, %es                # -> ES: Extra Segment
     59   movw    %ax, %ss                # -> SS: Stack Segment
     60   movw    $0, %ax                 # Zero segments not ready for use
     61   movw    %ax, %fs                # -> FS
     62   movw    %ax, %gs                # -> GS
     63 
     64   # Set up the stack pointer and call into C.
     65   movl    $start, %esp
     66   call    bootmain
     67 
     68   # If bootmain returns (it shouldn't), trigger a Bochs
     69   # breakpoint if running under Bochs, then loop.
     70   movw    $0x8a00, %ax            # 0x8a00 -> port 0x8a00
     71   movw    %ax, %dx
     72   outw    %ax, %dx
     73   movw    $0x8ae0, %ax            # 0x8ae0 -> port 0x8a00
     74   outw    %ax, %dx
     75 spin:
     76   jmp     spin
     77 
     78 # Bootstrap GDT
     79 .p2align 2                                # force 4 byte alignment
     80 gdt:
     81   SEG_NULLASM                             # null seg
     82   SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff)   # code seg
     83   SEG_ASM(STA_W, 0x0, 0xffffffff)         # data seg
     84 
     85 gdtdesc:
     86   .word   (gdtdesc - gdt - 1)             # sizeof(gdt) - 1
     87   .long   gdt                             # address gdt
     88