x86 setup paging before entering long mode
Posted: Wed May 08, 2013 12:27 pm
Hello,
I have little problems setting up the PML4, PDPT, PDT and PD in AT&T Assembly because I don't know how those tables are defined.
Can anyone point me to a tutorial about paging in Assembly? I only need a valid one for the setup, the rest is done in my C part of the kernel.
Note:
1) I am not switching directly to long mode, first I jump to Protected Mode.
2) during link rodata is put behind text section, and all other sections are discarded.
3) this part is loaded at physical address 0x500
I have little problems setting up the PML4, PDPT, PDT and PD in AT&T Assembly because I don't know how those tables are defined.
Can anyone point me to a tutorial about paging in Assembly? I only need a valid one for the setup, the rest is done in my C part of the kernel.
Note:
1) I am not switching directly to long mode, first I jump to Protected Mode.
2) during link rodata is put behind text section, and all other sections are discarded.
3) this part is loaded at physical address 0x500
Code: Select all
INITSEG = 0x0050
.section .rodata
gdt:
# Null Descriptor
.word 0x0000, 0x0000
.byte 0x00, 0b00000000, 0b00000000, 0x00
# Code Descriptor
.word 0xffff, (INITSEG * 0x10)
.byte 0x00, 0b10011010, 0b11001111, 0x00
# Data Descriptor
.word 0xffff, (INITSEG * 0x10)
.byte 0x00, 0b10010010, 0b11001111, 0x00
gdt_end:
gdt32ptr:
.word (gdt_end - gdt - 1)
.long (gdt + INITSEG * 0x10)
gdt64ptr:
.word (gdt_end - gdt - 1)
.quad (gdt + INITSEG * 0x10)
idt:
# Fill IDT with 256 ISR
.rept 256
.word ExecISR, 0x0008
.byte 0x00, 0b10101110
.word 0x0000
.endr
idt_end:
idt32ptr:
.word (idt_end - idt - 1)
.long (idt + INITSEG * 0x10)
idt64ptr:
.word (idt_end - idt - 1)
.quad (idt + INITSEG * 0x10)
.section .text
.globl Start
Start:
.code16
# Load Global Descriptor Table and Interrupt Descriptor Table
lgdt gdt32ptr
lidt idt32ptr
# Load Control Register CR0
# Enable Protected Mode (Bit0 in CR0)
# Store Control Register CR0
movl %cr0, %eax
orl $(1<<0), %eax
movl %eax, %cr0
# Setup all Segment Registers
# and reload Code Segment, Instruction Pointer
movw $0x0010, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
ljmp $0x0008, $ReloadCSIP
ReloadCSIP:
.code32
# Load Control Register CR4
# Enable Physical Address Extension (Bit5 in CR4)
# Store Control Register CR4
movl %cr4, %eax
orl $(1<<5), %eax
movl %eax, %cr4
#----------------- load CR3 with PML4 -----------------------------------------------
# Use Model Specific Register 0xC0000080
# Read from Model Specific Register
# Enable Long Mode (Bit8)
# Write to Model Specific Register
movl $0xc0000080, %ecx
rdmsr
orl $(1<<8), %eax
wrmsr
#----------------- halt, next instruction triple faults -----------------------------------------------
hlt
#----------------- halt, next instruction triple faults -----------------------------------------------
# Load Control Register CR0
# Enable Paging (Bit31 in CR0)
# Store Control Register CR0
movl %cr0, %eax
orl $(1<<31), %eax
movl %eax, %cr0
.code64
#-------------------------- ignored for now ---------------------------------
# Load Global Descriptor Table and Interrupt Descriptor Table
lgdt gdt64ptr
lidt idt64ptr
# leal pml4, %ebx
# pushl %ebx
call kmain
# popl %ebx
#-------------------------- ignored for now ---------------------------------
Hang:
# Halt the CPU
# Infinit loop if Halt doesn't work
hlt
jmp Hang
ExecISR:
# Call C Function
# Return from Interrupt Service Routine
call kisr
iret