luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

boot.s (4064B)


      1 /* Multiboot1 header for 32-bit kernel */
      2 .section .multiboot
      3 .align 4
      4     .long 0x1BADB002                /* magic */
      5     .long 0x00000007                /* flags: PAGE_ALIGN | MEMORY_INFO | VIDEO_MODE */
      6     .long -(0x1BADB002 + 0x00000007) /* checksum */
      7 
      8     /* Video mode fields (for flag bit 2) */
      9     .long 0                         /* header_addr (unused) */
     10     .long 0                         /* load_addr (unused) */
     11     .long 0                         /* load_end_addr (unused) */
     12     .long 0                         /* bss_end_addr (unused) */
     13     .long 0                         /* entry_addr (unused) */
     14 
     15     /* Video mode preference */
     16     .long 0                         /* mode_type: 0 = linear graphics mode */
     17     .long 1024                      /* width: 1024 pixels */
     18     .long 768                       /* height: 768 pixels */
     19     .long 32                        /* depth: 32 bits per pixel */
     20 
     21 /* Allocate the initial stack */
     22 .section .bss
     23 .align 16
     24 kernel_stack_bottom:
     25 .skip 16384 # 16 KiB kernel stack
     26 kernel_stack_top:
     27 
     28 .align 16
     29 user_stack_bottom:
     30 .skip 524288 # 512 KiB user stack (LuaJIT needs more stack space)
     31 user_stack_top:
     32 
     33 /* TSS (Task State Segment) */
     34 .section .bss
     35 .align 16
     36 .global tss
     37 .global kernel_stack_top
     38 tss:
     39     .skip 104  /* TSS structure (104 bytes) */
     40 
     41 /* GDT */
     42 .section .data
     43 .align 16
     44 .global gdt_start
     45 gdt_start:
     46     .quad 0x0000000000000000    /* 0x00: Null descriptor */
     47     .quad 0x00CF9A000000FFFF    /* 0x08: Kernel code (ring 0) */
     48     .quad 0x00CF92000000FFFF    /* 0x10: Kernel data (ring 0) */
     49     .quad 0x00CFFA000000FFFF    /* 0x18: User code (ring 3) */
     50     .quad 0x00CFF3000000FFFF    /* 0x20: User data (ring 3) - readable+writable, expand-up */
     51     .quad 0x0000000000000000    /* 0x28: TSS descriptor (filled at runtime) */
     52     .quad 0x00CFF3000000FFFF    /* 0x30: User TLS data segment (FS) - ring 3 */
     53     .quad 0x00CFF3000000FFFF    /* 0x38: User TLS data segment (GS) - ring 3 */
     54 gdt_end:
     55 
     56 gdt_descriptor:
     57     .word gdt_end - gdt_start - 1
     58     .long gdt_start
     59 
     60 /* Store multiboot info pointer */
     61 .section .bss
     62 .global multiboot_info_ptr
     63 multiboot_info_ptr:
     64     .long 0
     65 
     66 /* Entry point */
     67 .section .text
     68 .global _start
     69 .type _start, @function
     70 _start:
     71     /* Save multiboot info pointer (EBX contains it) */
     72     movl %ebx, multiboot_info_ptr
     73 
     74     /* Set up the kernel stack */
     75     mov $kernel_stack_top, %esp
     76 
     77     /* Load our GDT */
     78     lgdt gdt_descriptor
     79 
     80     /* Reload segment registers */
     81     mov $0x10, %ax      /* Kernel data segment */
     82     mov %ax, %ds
     83     mov %ax, %es
     84     mov %ax, %fs
     85     mov %ax, %gs
     86     mov %ax, %ss
     87 
     88     /* Far jump to reload CS */
     89     ljmp $0x08, $gdt_loaded
     90 
     91 gdt_loaded:
     92     /* Call the kernel main function */
     93     call kernel_main
     94 
     95     /* Hang if kernel_main returns */
     96     cli
     97 1:  hlt
     98     jmp 1b
     99 
    100 .size _start, . - _start
    101 
    102 /* Function to transition to user mode */
    103 .global enter_usermode
    104 .type enter_usermode, @function
    105 enter_usermode:
    106     /* Get the entry point from parameter (before we push things) */
    107     mov 4(%esp), %eax   /* entry_point parameter */
    108 
    109     /* Disable interrupts during transition */
    110     cli
    111 
    112     /* Build stack frame for iret (iret expects: EIP, CS, EFLAGS, ESP, SS) */
    113     /* Push SS (user data segment) */
    114     pushl $0x23         /* User data segment (0x20 | 3 for RPL=3) */
    115 
    116     /* Push ESP (user stack pointer) - ensure 16-byte alignment */
    117     movl $user_stack_top, %edx
    118     andl $-16, %edx         /* Align to 16 bytes */
    119     pushl %edx
    120 
    121     /* Push EFLAGS with IOPL=3 and IF=1 to allow usermode I/O and interrupts */
    122     pushf
    123     popl %edx
    124     orl $0x3200, %edx       /* Set IOPL=3 (bits 12-13) and IF=1 (bit 9) */
    125     pushl %edx
    126 
    127     /* Push CS (user code segment) */
    128     pushl $0x1B         /* User code segment (0x18 | 3 for RPL=3) */
    129 
    130     /* Push EIP (entry point) */
    131     pushl %eax
    132 
    133     /* DON'T set user segments here - we're still in kernel mode!
    134      * The iret will set CS and SS. We'll set DS/ES/FS/GS in user code. */
    135 
    136     /* Execute iret to jump to user mode */
    137     iret
    138 
    139 .size enter_usermode, . - enter_usermode