; =============================================================================
;
; Litos - Initialization, protected mode
;
; =============================================================================
CODE_SECTION 32
; -----------------------------------------------------------------------------
; Initialization 2 (jump here from INIT\INIT.ASM)
; -----------------------------------------------------------------------------
; ------------- Initialize data selectors
Start32: mov eax,SYSTEM_DS ; EAX <- data selector
mov ds,eax ; DS <- data selector
mov es,eax ; ES <- data selector
mov fs,eax ; FS <- data selector
mov gs,eax ; GS <- data selector
; ------------- Initialize stack (setting SS temporary disables interrupts)
mov ss,eax ; SS <- data selector (disables int.)
mov esp,BootSystemStack-SYSTEM_ADDR ; ESP <- end of stack
; ------------- One more check A20 gate (now in protected mode)
mov esi,CheckA20Addr-SYSTEM_ADDR ; ESI <- 0 MB
mov edi,CheckA20Addr-SYSTEM_ADDR+100000h ; EDI <- 1 MB
mov eax,0fa5025afh ; EAX <- test value 1
mov ebx,eax ; EBX <- test value 1
not ebx ; EBX <- test value 2
CheckA20: mov [esi],eax ; store test value 1 into 0 MB
mov [edi],ebx ; store test value 2 into 1 MB
cmp eax,[esi] ; check test value 1
jne CheckA20 ; invalid check value 1
cmp ebx,[edi] ; check test value 2
jne CheckA20 ; wait for A20 is enabled
; ------------- Initialize flags
xor eax,eax ; EAX <- 0
push eax ; push EAX (=0)
popf ; clear all flags
; ------------- Initialize page tables
call InitPDE ; initialize page tables
; ------------- Enable paging
mov edx,PageDir-SYSTEM_ADDR ; EDX <- page directory
mov cr3,edx ; CR3 <- set page directory register
mov eax,cr0 ; EAX <- CR0 (control register)
or eax,B31 ; set PG (Paging Enable) bit on
mov cr0,eax ; CR0 <- enable paging
; ------------- Flush instruction queue and jump to kernel copy at high RAM
jmp SYSTEM_CS:FlushInsPage ; flush instruction queue
; ------------- Reinitialize stack into copy of the kernel in high RAM
FlushInsPage: mov eax,SYSTEM_DS ; EAX <- data selector
mov ss,eax ; SS <- data selector (disables int.)
mov esp,BootSystemStack ; ESP <- end of stack
; ------------- Load system global descriptor table
mov esi,BootGDTTab ; ESI <- pattern of SystemGDTTab
mov edi,SystemGDTTab ; EDI <- system GDT table
mov ecx,BOOT_GDT_NUM*GLDT_size/4 ; size of GDT pattern
rep movsd ; copy pattern of GDT table
lgdt [SystemGDT] ; load system global descriptor table
; ------------- Flush instruction queue and load new CS
jmp SYSTEM_CS:FlushInsCS ; flush instruction queue
; ------------- Reload all selectors
FlushInsCS: mov eax,SYSTEM_DS ; EAX <- system data selector
mov ss,eax ; SS <- data selector
mov eax,USER_DS ; EAX <- user data selector
mov ds,eax ; DS <- user data selector
mov es,eax ; ES <- user data selector
xor eax,eax ; EAX <- 0
mov fs,eax ; FS <- NULL selector
mov gs,eax ; GS <- NULL selector
lldt ax ; clear local descriptor
; ------------- Uninitialize bottom part of memory
mov edi,PageDir ; EDI <- page directory
mov eax,(PageEmpty-SYSTEM_ADDR)+PE_PRESENT; EAX <- invalid
mov ecx,SYSTEM_ADDR/4096/1024 ; number of pages
rep stosd ; uninitialize bottom part of directory
mov edx,PageDir-SYSTEM_ADDR ; EDX <- page directory
mov cr3,edx ; CR3 <- reload page directory register
; ------------- Detect and init CPU
call InitCPU ; detect and init CPU
; ------------- Initialize math coprocessor
call InitFPU ; initialize math coprocessor
; ------------- Initialize CPU frequency
call InitCPUFreq ; initialize CPU frequency
; ------------- Initialize system interrupt table (KERNEL\TRAPS.ASM)
call InitIDT ; initialize system interrupt table
; ------------- Start kernel (-> INIT\INIT_SYS.ASM)
jmp StartKernel ; start kernel
; -----------------------------------------------------------------------------
; Initialize page tables
; -----------------------------------------------------------------------------
; ------------- Prepare registers
InitPDE: mov eax,PE_INIT ; EAX <- address 0 + flags (P+R/W+U/S)
mov bl,B0 ; page mask
mov edx,PageDir-SYSTEM_ADDR ; page directory
mov esi,PageMemMap-SYSTEM_ADDR+SYSTEM_SIZE/PAGE_SIZE/8
mov edi,SYSTEM_SIZE ; end of memory
; ------------- Index of page for correction of Intel Pentium F00F bug
; Instructions F0 0F C7 C8 .. F0 0F C7 CF (=LOCK CMPXCHG8B EAX..) should
; generate exception as ilegal instruction, LOCK prefix not used on memory
; operand should generate exception too, in such case CPU freezes.
;
; Solution: Align IDT table such that it spans a 4 KB page boundary
; by placing first entry starting 56 bytes from the end of the first 4 KB
; page. This places the first seven entries (0-6) on the first 4 KB
; page and the reamining entries on the second page. Mark the first 4 KB
; page as non-cacheable (PTE.PCD=1 or PTE.PWT=1).
mov ebp,SystemIDTTab-SYSTEM_ADDR ; EBP <- system IDT table
and ebp,PAGE_MASK ; EBP <- page address with IDT table
or ebp,eax ; EBP <- PTE entry
; ------------- Get next page entry
InitPDE2: sub edi,PAGE_SIZE ; shift address of page
shr bl,1 ; shift bit mask
jnc InitPDE6 ; no overflow
dec esi ; shift address in bit map
mov bl,B7 ; new bit mask
InitPDE6: test [esi],bl ; is this page available?
jz InitPDE2 ; this page is not available
xor [esi],bl ; clear page flag
; ------------- Store address of PTE into page directory
lea ecx,[edi+PE_INIT] ; ECX <- PTE + flags
mov [edx],ecx ; store address of page + flags
mov [edx+SYSTEM_ADDR/PAGE_SIZE/1024*PDE_size],ecx
add edx,byte PDE_size ; address of next page directory
; ------------- Initialize PTE
mov ecx,PAGE_SIZE/PTE_size ; ECX <- number of entries
push edi ; push EDI
InitPDE8: stosd ; store address of memory
cmp eax,ebp ; is it first page with IDT table?
jne InitPDE9 ; it is not page with IDT table
or byte [edi-4],PE_PCD ; disable page cache
InitPDE9: add eax,PAGE_SIZE ; address of next page
loop InitPDE8 ; next page entry
pop edi ; pop EDI
; ------------- Check page address
cmp eax,[MemoryMax-SYSTEM_ADDR] ; check end of memory
jb InitPDE2 ; init next page
ret
; -----------------------------------------------------------------------------
; Data
; -----------------------------------------------------------------------------
DATA_SECTION
; ------------- System global descriptor table
align 4, db 0
dw 0 ; align
SystemGDT: dw SystemGDTTabEnd-SystemGDTTab-1 ; GDT size limit
dd SystemGDTTab ; GDT base address
; -----------------------------------------------------------------------------
; Uninitialized data
; -----------------------------------------------------------------------------
BSS_SECTION
align 4, resb 1
CheckA20Addr: resd 1 ; checked A20 address
|