Setting up GDT breaks code

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.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Setting up GDT breaks code

Post by Combuster »

check_cs(0x0008): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0
Here's your GPF: apparently your GDT has DPL=3 for the second entry - or rather, the GDT is in the wrong location.

Furthermore, your stack is in reserved memory and your code contains a lot of other bits of garbage though that say you don't understand what you're were doing in the first place:
gdt_install:
movw $23, gdtr /* sizeof (gdt) */
movl $1, %edi
movw $0, gdtr(, %edi, 2)
movl $2, %edi
movw gdt, %ax
movw %ax, gdtr(, %edi, 2)
For instance, you could trivially have done that in two instructions, and zero if you think about it properly.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

Re: Setting up GDT breaks code

Post by jrhetf4xb »

Combuster wrote:
check_cs(0x0008): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0
Here's your GPF: apparently your GDT has DPL=3 for the second entry - or rather, the GDT is in the wrong location.
I really don't understand how it's in the wrong location then... Did I put it wrong in gdtr? I tried about 20 variations of table entries as well, now I get another type of error: fetch_raw_descriptor: GDT: index (f) 1 > limit (0). All of the solutions I found we're the sorts of "I found it, it was the GDT, fixed", without specifying what exactly in the GDT...
For instance, you could trivially have done that in two instructions, and zero if you think about it properly.
The only way I thought of is gdtr: .word 23 .long gdt, is this what you had in mind?
Practice makes perfect.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Setting up GDT breaks code

Post by Combuster »

All of the solutions I found we're the sorts of "I found it, it was the GDT, fixed", without specifying what exactly in the GDT...
Did you read the comments leading up to the closing post? You'll see that many of them will mention segmentation - yet another thing which is broken in your case, and by the looks of it, never properly understood as well. What's the difference between virtual and physical memory? What's the difference between CS, CS.base and the far jump address?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

Re: Setting up GDT breaks code

Post by jrhetf4xb »

Alright, I tried to read up on these topics once again so correct me if I'm wrong in my understanding.
In real mode, linear addresses are computed by the segment:offset pair corresponding to the data you want to get. There are separate segment registers for code (%ss) and data (%ds), with the additional extra segments. The address is then the result of the value in the segment register multiplied by 16 (shifted left by 4), plus the offset.
In protected mode segmentation works by referencing a global (or local) descriptor table. This table has 64-bit entries, which contain information about a segment. A special 48-bit register, the GDT register, contains the size of this table, as well as the base address from where the structure begins. The segment selectors now contain an offset into the GDT register, so if the code segment is the second entry into the GDT, it would contain the value of 8, because the descriptor starts at the eighth byte.

I can't see why my segmentation would be broken as I checked that my GDT entries are correct and ensured that at least most of my code complies with the examples given in numerous places... But it actually is broken and I really can't understand why and it's driving me crazy.
From my latest code edit I get a new type of error: jump_protected: gate type 0 unsupported

Code: Select all

.section .data
	gdt: .quad 0
		 .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00
		 .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 
	gdtr: .word 23
		  .long gdt

.code16
.section .text
	.globl boot1
	
boot1:
	cli
	
	/* re-set the stack and segments */
	xorw %ax, %ax
	movw %ax, %es
	movw %ax, %ds
	
	movw $0x7C00, %ax
	movw %ax, %ss
	movw $0x7CDF, %sp
	
	sti
	
	/* enable A20 line */
	movw $0x2401, %ax
	int $0x15

	/* load the kernel */
	
	/* set up for protected mode */
	cli
	movl $2, %edi
	movw gdt, %eax 
	orw $0x0100, %eax 
	movl %eax, gdtr(, %edi, 2)
	
	/* enter protected mode */
	lgdt gdtr 
	movl %cr0, %eax
	orl $1, %eax
	movl %eax, %cr0
	ljmp $0x08, $protected_mode

.code32
protected_mode:
	/* update segments */
	movw $0x10, %ax
	movw %ax, %ds
	movw %ax, %es
	movw %ax, %gs
	movw %ax, %fs
	movw %ax, %ss
	movl $0x0001000, %esp
	
	
	//call kmain
	/* NOTREACHED */
  halt:
	hlt
	jmp halt
What's the difference between CS, CS.base and the far jump address?
CS has two meanings depending on real/protected mode (like I wrote above, if it's even correct). CS.base specifies the starting address of the segment in protected mode (are you refering to .base in the CS entry in GDT?). The far jump modifies the code segment when jumping to an address. So when I perform a far jump to protected mode, basically CS gets the value of 8 in order to offset the correct entry in the GDT.
Practice makes perfect.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Setting up GDT breaks code

Post by Combuster »

Problems don't simply disappear if you only stare at the screen though. Apart from screensavers, that is.
jrhetf4xb wrote:
What's the difference between CS, CS.base and the far jump address?
CS has two meanings depending on real/protected mode (...)
Take a good look at the logdump you posted earlier, then answer that question again. Where do those values come from, and why are they correct or wrong? Even though you have made some changes, I'm pretty sure you will see roughly the same numbers in your current dump because you have missed the problem so far.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

Re: Setting up GDT breaks code

Post by jrhetf4xb »

00018222607i[CPU0 ] 0x000000000000004f>> jmp far 0008:0554 : EA54050800
As far as I understand, from last page's dump I'm jumping to 0x0554 where the label should be located (0x0050:0x0054 CS:IP pair) and after the jump to protected mode CS gets the value of 0x0008 so it can offset the table. Or am I completely misunderstanding the jump?
Does it assign CS to 0x0008 while in real mode and use real mode addressing (0x0080 + 0x0554 = ... wrong jump)? Or is it after real mode (in protected) but not requiring the 0x0050 offsetting, thus wrongly landing at 0x0554 instead of 0x0054 (again a wrong jump)? Do I have to manipulate the addresses in any way?
Practice makes perfect.
Cjreek
Member
Member
Posts: 70
Joined: Thu May 28, 2009 2:41 pm
Location: Germany

Re: Setting up GDT breaks code

Post by Cjreek »

I'm having a hard time reading AT&T assembler syntax but I'm wondering what those lines are supposed to do:

Code: Select all

 
   movl $2, %edi  
   movw gdt, %eax 
   orw $0x0100, %eax 
   movl %eax, gdtr(, %edi, 2)
I'm pretty sure this messes up your GDTR.

you load the address of your GDT in eax, setting Bit 8 of this to 1 and than you write this value into the base-field of your GDTR (using a very confusing way to calculate this address, why not just gdtr+4?)

Why do you change this bit? Best case this does nothing if your .data section starts beyond 0x7D00. Otherwise the base of your GDTR is just wrong and the processor will read crap instead of your GDT.

I think if you just delete those lines everything might work fine.
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

Re: Setting up GDT breaks code

Post by jrhetf4xb »

Sorry, ignore that part as I was trying some stupid stuff to put the address in the gdtr, it should be like this:

Code: Select all

.section .data
	gdt: .quad 0
		 .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00
		 .byte 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00 
	gdtr: .word 23
		  .long gdt

.code16
.section .text
	.globl boot1
	
boot1:
	cli
	
	/* re-set the stack and segments */
	xorw %ax, %ax
	movw %ax, %es
	movw %ax, %ds
	
	movw $0x7C00, %ax
	movw %ax, %ss
	movw $0x7CDF, %sp
	
	sti
	
	/* enable A20 line */
	movw $0x2401, %ax
	int $0x15

	/* load the kernel */
	
	/* set up for protected mode */
	cli
	
	/* enter protected mode */
	lgdt gdtr 
	movl %cr0, %eax
	orb 1, %al
	movl %eax, %cr0
	ljmp $0x08, $protected_mode

.code32
protected_mode:
	/* update segments */
	movw $0x10, %ax
	movw %ax, %ds
	movw %ax, %es
	movw %ax, %gs
	movw %ax, %fs
	movw %ax, %ss
	movl $0x0001000, %esp
	
	
	//call kmain
	/* NOTREACHED */
  halt:
	hlt
	jmp halt

Practice makes perfect.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Setting up GDT breaks code

Post by Combuster »

jrhetf4xb wrote:
00018222607i[CPU0 ] 0x000000000000004f>> jmp far 0008:0554 : EA54050800
As far as I understand, from last page's dump I'm jumping to 0x0554 where the label should be located (0x0050:0x0054 CS:IP pair) and after the jump to protected mode CS gets the value of 0x0008 so it can offset the table. Or am I completely misunderstanding the jump?
Does it assign CS to 0x0008 while in real mode and use real mode addressing (0x0080 + 0x0554 = ... wrong jump)? Or is it after real mode (in protected) but not requiring the 0x0050 offsetting, thus wrongly landing at 0x0554 instead of 0x0054 (again a wrong jump)? Do I have to manipulate the addresses in any way?
There's actually no such thing as a "jump" to protected mode. If bit 0 of CR0 is set, the segment.base is loaded from the GDT. If it's clear, then segment.base = segment.selector * 16. The jump fails because you already are in protected mode, and there's garbage at the supposed GDT.

All GDT entries in your code have a base of zero, so a jump to 8:554 should set CS.base = GDT[1].base = 0 and IP to 0x554, and thus continue executing at 0x554 physical. Your dump doesn't show GDTR, but the base you have set for it is probably 0x000005xx or 0x000006xx because you will most likely have told your linker to start everything from 0x0500

However, the actual code is somewhere else:

Code: Select all

00018222607i[CPU0 ] |  CS:0500( 0004| 0|  0) 00005000 0000ffff 0 0
00018222607i[CPU0 ] | RIP=000000000000004f
Which physical address is that? What goes wrong here?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
jrhetf4xb
Member
Member
Posts: 38
Joined: Fri May 16, 2014 11:50 am
Location: Bulgaria

Re: Setting up GDT breaks code

Post by jrhetf4xb »

Alright! I tweaked where code should be in my linker script (from 0x0500 to 0x1000) and it works now!! Did I run over BIOS memory and that caused these errors? I really don't understand how it got fixed...
What I did is just tweak the addresses -- I put my kernel from 0x1000 onwards and now everything works like a charm, the segments seem to contain the correct value and code past protected_mode label gets executed.
Attachments
boot1.ld
(525 Bytes) Downloaded 60 times

[The extension s has been deactivated and can no longer be displayed.]

[The extension s has been deactivated and can no longer be displayed.]

Practice makes perfect.
Post Reply