GDT Entry

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
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

GDT Entry

Post by BMW »

I have got myself so confused over GDT entries and endianness......

http://wiki.osdev.org/Global_Descriptor_Table

Is this a correct GDT Entry structure (Language: C, Architecture: x86_32)?

Code: Select all

struct GDTEntry
{
   uint16_t LimitLow;
   uint16_t BaseLow;
   uint8_t BaseMid;
   uint8_t Access;
   uint8_t LimitHigh : 4;
   uint8_t Flags : 4;
   uint8_t BaseHigh;
} __attribute__((packed));
Do I place the items with the least significant bits in first due to Little Endianness? (for example the LimitLow occupies bits 0-15 so I put it first)

Would this work with a CPU using Big Endian?
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
Kazinsal
Member
Member
Posts: 559
Joined: Wed Jul 13, 2011 7:38 pm
Libera.chat IRC: Kazinsal
Location: Vancouver
Contact:

Re: GDT Entry

Post by Kazinsal »

BMW wrote:Would this work with a CPU using Big Endian?
The GDT is an x86 concept. No big endian CPUs have the structure.
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: GDT Entry

Post by BMW »

Blacklight wrote:
BMW wrote:Would this work with a CPU using Big Endian?
The GDT is an x86 concept. No big endian CPUs have the structure.
Ah. That makes sense. Thanks. So my structure is right?
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
iansjack
Member
Member
Posts: 4711
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: GDT Entry

Post by iansjack »

The GDT entries are just 32-bit (or 64-bit numbers). So the easy way to answer your question is just to look at memory and see what has been put there by your code.
walfud
Posts: 2
Joined: Tue Jun 04, 2013 8:01 pm

Re: GDT Entry

Post by walfud »

Code: Select all

struct GDTEntry
{
   uint16_t LimitLow;
   uint16_t BaseLow;
   uint8_t BaseMid;
   uint8_t Type : 4; 
   uint8_t S : 1;
   uint8_t DPL : 3;
   uint8_t P : 1;
   uint8_t LimitHigh : 4;
   uint8_t AVL : 1;
   uint8_t L : 1;
   uint8_t DB : 1;
   uint8_t G : 1;
   uint8_t BaseHigh;
} __attribute__((packed));
I'd like to split 'Access' and 'Flags' into individual field.
walfud
Posts: 2
Joined: Tue Jun 04, 2013 8:01 pm

Re: GDT Entry

Post by walfud »

Oh, I see a definition from here: http://www.osdever.net/tutorials/view/b ... t-tutorial

Code: Select all

struct gdt_entry
{
    unsigned short limit_low;
    unsigned short base_low;
    unsigned char base_middle;
    unsigned char access;
    unsigned char granularity;
    unsigned char base_high;
} __attribute__((packed));
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: GDT Entry

Post by sortie »

Your structure will be endian-dependent the moment you use data types larger than uint8_t or you use bit fields. Note that the bit fields layout order is also endian-dependent, which may be tricky to get right if you don't understand endianness that well. Personally, I am not that happy with bit fields and just assemble the values with shifts and or, such as gdt->foo = bar << 4 | qux << 0.
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: GDT Entry

Post by BMW »

sortie wrote:Your structure will be endian-dependent the moment you use data types larger than uint8_t or you use bit fields. Note that the bit fields layout order is also endian-dependent, which may be tricky to get right if you don't understand endianness that well. Personally, I am not that happy with bit fields and just assemble the values with shifts and or, such as gdt->foo = bar << 4 | qux << 0.
Say if I use 8 1-bit bitfields for a byte, I would just order them from MSB to LSB aye?
e.g. is this correct?

Code: Select all

struct GDTEntry
{
	uint16_t LimitLow;
	uint16_t BaseLow;
	uint8_t BaseMid;
	uint8_t PresentBit : 1;
	uint8_t RingLevel : 2;
	uint8_t One : 1;
	uint8_t ExecutableBit : 1;
	uint8_t DCBit : 1;
	uint8_t RWBit : 1;
	uint8_t AccessedBit : 1;
	uint8_t LimitHigh : 4;
	uint8_t GranularityBit : 1;
	uint8_t SizeBit : 1;
	uint8_t Zero : 2;
	uint8_t BaseHigh;
} __attribute__((packed));
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: GDT Entry

Post by AJ »

Hi,

Why don't you create an instance of that struct and then see what you end up with in memory?

Cheers,
Adam
User avatar
dozniak
Member
Member
Posts: 723
Joined: Thu Jul 12, 2012 7:29 am
Location: Tallinn, Estonia

Re: GDT Entry

Post by dozniak »

BMW wrote: Say if I use 8 1-bit bitfields for a byte, I would just order them from MSB to LSB aye?
e.g. is this correct?
This depends on the compiler and the ABI. I.e. not correct in general case.
Learn to read.
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: GDT Entry

Post by BMW »

dozniak wrote:
BMW wrote: Say if I use 8 1-bit bitfields for a byte, I would just order them from MSB to LSB aye?
e.g. is this correct?
This depends on the compiler and the ABI. I.e. not correct in general case.
Yeah, I am just using bytes as the minimum size and anding and oring stuff together now... less problems.
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

wtf?

Post by BMW »

How come this works?:

Code: Select all

struct GDTInfo gdti;
gdti.size = 8 * descriptorcount - 1;
gdti.address = GDT_ADDRESS;
	
struct GDTInfo* ptr = &gdti;

disable_interrupts();
__asm__ __volatile__("lgdt %0" : : "m" (*ptr));
enable_interrupts();
But that is wrong isn't it? Because it would be passing the value pointed to by ptr to LGDT (which would be the first 4 bytes of the gdti structure...)

If I change it so that I am passing the POINTER to gdti, OS all broken...

This is theoretically correct isn't it?:

Code: Select all

__asm__ __volatile__("lgdt %0" : : "m" (ptr));
EDIT: Sorry if this is a RTFM question, but there is a serious lack of DECENT GCC inline assembly information.
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: GDT Entry

Post by sortie »

BMW wrote: Say if I use 8 1-bit bitfields for a byte, I would just order them from MSB to LSB aye?
e.g. is this correct?
...
Don't assume. If you are doing an ELF-operating system, look up what your compiler generates in the System V ABI (i386 version). Don't pay attention to me. On SysV targets, the bit fields are placed according to the host endianness. That is, struct { unsigned int a1: 1; unsigned int a2: 1; ... unsigned int a32: 1; } will have the exactly opposite order when switching endian (such as going from big endian to little endian). I recommend that you write a test program using bit fields for your host operating system with gcc and use objdump -d to see what the program does.
BMW wrote:EDIT: Sorry if this is a RTFM question, but there is a serious lack of DECENT GCC inline assembly information.
There is such a lack and it's kinda a problem. The root cause is that it's not really a compiler problem, because it depends on the backend and the assembly itself depends on the assembler. If in doubt, write an assembler function in a file instead.
Mikemk
Member
Member
Posts: 409
Joined: Sat Oct 22, 2011 12:27 pm

Re: wtf?

Post by Mikemk »

BMW wrote:

Code: Select all

disable_interrupts();
__asm__ __volatile__("lgdt %0" : : "m" (*ptr));
enable_interrupts();
That is an excellent way to crash.
Programming is 80% Math, 20% Grammar, and 10% Creativity <--- Do not make fun of my joke!
If you're new, check this out.
User avatar
BMW
Member
Member
Posts: 286
Joined: Mon Nov 05, 2012 8:31 pm
Location: New Zealand

Re: wtf?

Post by BMW »

m12 wrote:
BMW wrote:

Code: Select all

disable_interrupts();
__asm__ __volatile__("lgdt %0" : : "m" (*ptr));
enable_interrupts();
That is an excellent way to crash.
Works fine for me.

Please explain...?
Currently developing Lithium OS (LiOS).

Recursive paging saves lives.
"I want to change the world, but they won't give me the source code."
Post Reply