Page 1 of 1

x86 setup paging before entering long mode

Posted: Wed May 08, 2013 12:27 pm
by teodori
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

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

Re: x86 setup paging before entering long mode

Posted: Thu May 09, 2013 3:03 am
by Combuster
load CR3 with PML4
And now the code? It looks like you forgot something :wink:

Re: x86 setup paging before entering long mode

Posted: Thu May 09, 2013 3:17 am
by teodori
I know that I have to load CR3 with the PML4, but I don't know how to setup PML4, etc.
I want to know how those table look like...

Re: x86 setup paging before entering long mode

Posted: Thu May 09, 2013 3:30 am
by Combuster
RTFM? Wiki?

Re: x86 setup paging before entering long mode

Posted: Thu May 09, 2013 7:20 am
by Mikemk
Combuster wrote:RTFM? Wiki?
Other forum threads? Call scholastic? Go up in space? Shoot a nuclear missile across the planet?

OK, maybe only the first of those should be done. (Don't do the last one, I can't be held liable.)