Separate kernel stack using GDT

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
alix
Posts: 12
Joined: Tue Nov 13, 2012 3:56 pm

Separate kernel stack using GDT

Post by alix »

Hello,

I'm playing a bit with OS programming since some time and currently i'm experimenting with the stack segments. I would like to have the kernel stack starts at physical location 0x200000 (2MB) and grows down up to 0x100000 (1MB). The kernel is loaded at physical address 0x200000 and grows up, no paging yet.

For this i setup the following gdt entries.

Code: Select all

; GDT system code descriptor
gdt_cs:
	dw 0FFFFh		; maximum limit 0FFFFFh (1 meg or 4 gig)
	dw 0			        ; base address; gets patched above
	db 0
	db 9Ah			; present,ring 0,code,non-conforming,readable
	db 0CFh			; page-granular (4 gig limit), 32-bit
	db 0

; GDT system data descriptor
gdt_ds:
	dw 0FFFFh		; maximum limit 0FFFFFh (1 meg or 4 gig)
	dw 0			        ; base address; gets patched above
	db 0
	db 92h			; ring 0, data, expand-up, writable
	db 0CFh			; page-granular (4 gig limit), 32-bit
	db 0
; GDT system stack descriptor
gdt_ss:
	dw 0FFFFh               ; maximum limit 0FFFFFh (1 meg or 4 gig)
	dw 0
	db 0
	db 96h ;                   ; ring 0, data, expand-down, writable
	db 04Fh                   ; page-granular (1 meg limit), 32-bit
	db 0

gdt_end:

gdt:
    dw gdt_end - gdt_begin - 1
    dd gdt_begin
And i'm loading these entries the following way:

Code: Select all

    ....
    ....
    jmp      08h:pmode
[BITS 32]
pmode:
    mov		ax, 0x10		; set data segments to data selector (0x10)
    mov		ds, ax
    mov		es, ax
    mov		gs, ax
    mov		fs, ax
    mov 	        ax, 0x18
    mov		ss, ax
Everything is perfectly working with Qemu. I can trace some C function calls and see how my stack is growing down from the 2MB limit. But bochs is sending me isr 13 (general protection fault) as soon as i execute any code after loading the stack segment select with mov ss, ax
With the same setup if i load the stack descriptor with the same values as for the code (separated as above) everything works in bochs but except that my stack is somewhere else not as i want below 2MB.

Any idea? It is very important for me to understand if i'm doing something wrong.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Separate kernel stack using GDT

Post by gerryg400 »

Expand down segments don't work like that. Actually they aren't very useful unless the stack is at the top of the segment and you intend to modify the size of the stack segment at runtime.

Use an expand-up segment.

If you want your stack to be between phys 0x100000 and 0x200000 and to use segment protection then set the base to 0x100000 and the limit to 0x100000 (actually 0xfffff).

When you initialise the ESP reg set it to 0x100000 also.
If a trainstation is where trains stop, what is a workstation ?
User avatar
alix
Posts: 12
Joined: Tue Nov 13, 2012 3:56 pm

Re: Separate kernel stack using GDT

Post by alix »

Thanks for your reply. It should work as you said and Qemu and Bochs.

Not sure why Qemu behaves the setup described above. But anyway i'll not spend more time on this as there is much much more to learn/do :)
Post Reply