Entering 64bit Mode.
Posted: Sun Oct 24, 2010 12:03 pm
I've recently decided to go 64bit with my kernel. After finding that i was spending a lot of my time writing code that does the same thing just using different features of the processor: interupts/syscall/sysenter, fsave/fxsave/osxsave and PIC/APIC for example.
With long mode i can assume support for a lot of features and be able to support much larger address spaces and ram. And with hobby OS's taking 5-10 years to develop into something useable it seems silly to build a 32bit kernel when typical pc's will be running programs that want far more than 4GB address space. Making my OS obsolete.
I've been looking at http://wiki.osdev.org/User:Stephanvansc ... _Long_Mode which has proved very useful. I've stubbed out the beginning of a kernel that can enter long mode.
At the moment i have 2 GDT's. One is 32bit and one is 64bit each with their own register structure.
What i've figured is that i could use one GDT and just use a different register. Like this:
This works in QEMU-system-x86-64. Is there anything wrong with doing this? Is it ok to have the 64bit flag set when in 32bit mode. If this was run on a 32bit cpu where this flag was reserved would it triple fault? It it considered wrong (qemu allows it though) that the 32bit and 64bit flags are set when in 64 bit mode?
Also as a sidenote from what i know all 64bit instructions have a REX prefix and the immediate and memory operands are twice as big and hence slower. Should all of my code be 32bit where possible and just 64bit operands for pointers and very large numbers?
Thanks.
With long mode i can assume support for a lot of features and be able to support much larger address spaces and ram. And with hobby OS's taking 5-10 years to develop into something useable it seems silly to build a 32bit kernel when typical pc's will be running programs that want far more than 4GB address space. Making my OS obsolete.
I've been looking at http://wiki.osdev.org/User:Stephanvansc ... _Long_Mode which has proved very useful. I've stubbed out the beginning of a kernel that can enter long mode.
At the moment i have 2 GDT's. One is 32bit and one is 64bit each with their own register structure.
What i've figured is that i could use one GDT and just use a different register. Like this:
Code: Select all
;----------
; GDT
;----------
gdt32Register:
dw gdtEnd-gdt-1
dd gdt
gdt64Register:
dw gdtEnd-gdt-1
dq gdt
gdt:
.null:
dq 0 ;Reserved
.kernelCode: ;Flat DPL=0 code selector
dw 0xFFFF ;Limit 0-15
dw 0 ;Base 0-15
db 0 ;Base 16-23
db 10011010b ;Access
db 11101111b ;Limit 16-19, Flags 0-3 (granularity set to 4kb, size set to 32bit, 64bit flag set)
db 0 ;Base 24-31
.kernelData: ;Flat DPL=0 data selector
dw 0xFFFF
dw 0
db 0
db 10010010b
db 11101111b
db 0
gdtEnd:
Also as a sidenote from what i know all 64bit instructions have a REX prefix and the immediate and memory operands are twice as big and hence slower. Should all of my code be 32bit where possible and just 64bit operands for pointers and very large numbers?
Thanks.