101 lines
2.8 KiB
NASM
101 lines
2.8 KiB
NASM
;kernel.asm
|
|
;Author: Josh Holtrop
|
|
;Modified: 10/30/03
|
|
|
|
%define GDT_P 0x100000; ;1mb physical - Global Descriptor Table space
|
|
%define GDT_V GDT_P+0xC0000000
|
|
%define IDT_P 0x102000 ;1mb+8kb - Interrupt Descriptor Table space
|
|
%define IDT_V IDT_P+0xC0000000
|
|
%define PDBR_P 0x104000 ;1mb+16kb - Page Directory Base Register (first PD)
|
|
%define PDBR_V PDBR_P+0xC0000000
|
|
%define LOPT_P 0x105000 ;1mb+20kb - LOw Page Table for mapping first 4mb
|
|
%define LOPT_V LOPT_P+0xC0000000
|
|
%define KERNEL_P 0x106000 ;1mb+24kb - the kernel's physical address
|
|
%define KERNEL_V KERNEL_P+0xC0000000 ;3gb+1mb+24kb, the virtual address of the kernel
|
|
|
|
[global start]
|
|
[extern _isr]
|
|
[extern _k_init]
|
|
|
|
bits 32
|
|
|
|
;This is where the kernel begins execution
|
|
;At this point, the temporary gdt is set up to "map" 0xC000_0000 to 0x0.
|
|
;We must enable paging with the first 4mb mapped 1:1 virtual:physical
|
|
; and with the 4mb starting at 0xC000_0000 mapped to the first 4mb physical.
|
|
;Then we can start using our "real" gdt, then unmap the lower 4mb.
|
|
start:
|
|
cli ;if they weren't already off
|
|
|
|
xor eax, eax
|
|
mov edi, PDBR_V
|
|
mov ecx, 1024 ;clear the PDBR
|
|
rep stosd
|
|
mov [PDBR_V], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
|
|
mov [PDBR_V+0xC00], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table (read/write, present)
|
|
|
|
mov edi, LOPT_V
|
|
mov ecx, 1024
|
|
mov eax, 0x03 ;starting physical address = 0x0 (read/write, present flags)
|
|
fill_lopt_loop: ;fill the page table
|
|
stosd
|
|
add eax, 4096 ;increment next phsyical address by 4kb
|
|
loop fill_lopt_loop
|
|
|
|
mov eax, PDBR_P
|
|
mov cr3, eax ;store the Page Directory Base Address
|
|
mov eax, cr0
|
|
or eax, 0x80000000 ;set page enable bit
|
|
mov cr0, eax ;now paging is active!
|
|
|
|
|
|
mov edi, GDT_V
|
|
mov esi, gdt
|
|
mov ecx, gdt_end-gdt
|
|
copy_gdt:
|
|
lodsb
|
|
stosb
|
|
loop copy_gdt
|
|
|
|
mov edi, IDT_V ;destination
|
|
mov esi, isr_0 ;address of isr0
|
|
mov edx, isr_1-isr_0 ;distance between isr labels
|
|
mov ecx, 50 ;number of isrlabels
|
|
fill_idt:
|
|
mov ebx, esi
|
|
mov ax, si
|
|
stosw ;0 offset 15:0
|
|
mov ax, KERNEL_CODE
|
|
stosw ;2 selector 15:0
|
|
mov ax, 0x8E00
|
|
stosw ;4 [P][DPL][0][TYPE][0][0][0][0][0][0][0][0]
|
|
shr esi, 16
|
|
mov ax, si
|
|
stosw ;6 offset 31:16
|
|
mov esi, ebx
|
|
add esi, edx
|
|
loop fill_idt
|
|
mov word [IDT_V+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges
|
|
|
|
lgdt [gdtr] ;load gdt
|
|
jmp KERNEL_CODE:newgdtcontinue
|
|
newgdtcontinue:
|
|
mov ax, KERNEL_DATA
|
|
mov es, ax
|
|
mov ds, ax
|
|
mov gs, ax
|
|
mov fs, ax
|
|
mov ss, ax
|
|
mov esp, 0xc01ffffc ;stack just under 3gb+2mb, moves downward
|
|
lidt [idtr] ;load idt
|
|
|
|
call _k_init
|
|
haltit:
|
|
hlt ;halt processor when k_init is done
|
|
jmp haltit ;shouldn't get here...
|
|
|
|
%include "gdt.inc"
|
|
%include "idt.inc"
|
|
|
|
|