Page 1 of 1

Confused about a structure (segment descriptor)

Posted: Wed Aug 29, 2007 1:54 pm
by jerryleecooper
Hello, I try since yesterday to have a tss in my multitasking code so I can have protection (ring 3 => ring 0), but I get a protection fault when I do. I think I targeted the problem and it is that the busy bit in the tss segment descriptor is set. I tried do remove it, but there's still GP exceptions. That's when I tought that probably, my segmentdescriptor struct declaration was probably wrong. Take a look:

Code: Select all

typedef struct segmentdescriptor {
	unsigned short	limit1500;
	unsigned short	base1500;
	unsigned char	base2316;
	
	unsigned		type	:	4;
	unsigned		desctype:	1;
	unsigned		dpl		:	2;
	unsigned		present	:	1;
	
	unsigned		avl		:	1;
	unsigned		l		:	1;
	unsigned		db		:	1;
	unsigned		g		:	1;
	unsigned		limit1916:	4;
	
	unsigned char	base3124;
} __attribute__ ((packed)) segmentdescriptor;
Is there's something wrong with it? If I follow the intel manual, the limit1916 field should be before avl, but if I do this, the Virtual PC machine does'nt like that.

Posted: Wed Aug 29, 2007 4:42 pm
by Combuster
Try running your kernel in Bochs - it will likely complain about unusual errors sources (like loading a tss). Use the resulting message to diagnose the reason of the #GP.

Posted: Wed Aug 29, 2007 6:11 pm
by Kevin McGuire
The structure looks correct, but I have never used bit fields much so I can not say that they are not being interpreted correctly.

Posted: Wed Aug 29, 2007 6:31 pm
by jerryleecooper
Thank oyu two for your replies . I changed the placement of the limit1916 field, to where it was supposed to be, and now I still get #GP fault and not "virtual machine error must close" from Virtual PC, so it's good.

Here's my refreshed structure:

Code: Select all

typedef struct segmentdescriptor {
	unsigned short	limit1500;
	unsigned short	base1500;
	unsigned char	base2316;
	
	unsigned		type	:	4;
	unsigned		desctype:	1;
	unsigned		dpl		:	2;
	unsigned		present	:	1;
	
	unsigned		limit1916:	4;
	unsigned		avl		:	1;
	unsigned		l		:	1;
	unsigned		db		:	1;
	unsigned		g		:	1;

	unsigned char	base3124;
} __attribute__ ((packed)) segmentdescriptor;
I don't use bitfield generally, but if the feature exist, why not using it? And it makes the code, cleaner? Bitfields makes C a higher level language than requested, imho.

Now...

Code: Select all

movw $0x10, %ax
    movw %ax, %ds
	movw %ax, %es
    movw %ax, %fs
    movw %ax, %gs
    movw %ax, %ss
Is this code right? Because I think Ive found the problem. It's about segment selectors. They have the segment, the TI bit, and the RPL, but I don't use that when adressing my segment registers. Do I need to? Because my code works correctly without. :?

Posted: Thu Aug 30, 2007 3:47 am
by JamesM
You must always use the RPL. So, if your descriptors are as follows (standard layout)

Code: Select all

0x00 : null descriptor
0x08 : kernel CS
0x10 : kernel DS/SS
0x18 : user CS
0x20 : user DS/SS
Then, you would reference them like this:

Code: Select all

0x00 : bleh, never reference it
0x08 : RPL=0
0x10: RPL=0
0x1b: RPL=3
0x23: RPL=3
.

Posted: Thu Aug 30, 2007 7:51 am
by jerryleecooper
Thank you. Ive set the selector given to ltr to 5<<3 and now it works. So I understand, the selector need to be an index, and not an index * 8. That was my error. :oops:

Posted: Thu Aug 30, 2007 2:37 pm
by jerryleecooper
Everythings is working right, now! :) I can now implement the v8086 thing so I can get VBE and a graphical GUI. youppi! 8)