trouble with 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
elkvis
Posts: 5
Joined: Sun Apr 13, 2008 4:40 pm
Location: River Falls, WI, USA

trouble with gdt

Post by elkvis »

I have a kernel, written in C and NASM, that boots up and I can print to the screen with a printf-like command, complete with \n support and scrolling, etc.

I am having trouble with it rebooting when I try to jump to the new code segment.

my segment descriptor structure looks like this:

Code: Select all

typedef struct
{
  uint limit_0_15:16 __attribute__((__packed__));
  uint base_0_23:24 __attribute__((__packed__));
  uint accessed:1 __attribute__((__packed__));
  uint read_write:1 __attribute__((__packed__));
  uint expand_conform:1 __attribute__((__packed__));
  uint code:1 __attribute__((__packed__));
  uint system:1 __attribute__((__packed__));
  uint dpl:2 __attribute__((__packed__));
  uint present:1 __attribute__((__packed__));
  uint limit_16_19:4 __attribute__((__packed__));
  uint long_mode:1 __attribute__((__packed__));
  uint default_op:1 __attribute__((__packed__));
  uint granularity:1 __attribute__((__packed__));
  uint base_24_31:8 __attribute__((__packed__));
} segment_descriptor;
I have verified through printf(... sizeof(segment_descriptor)) that this structure is 8 bytes, and after setting the values to what I want, and printing out the contents, it appears correct.

I am able to LGDT with my array of 8192 descriptors, but when I try to jump into my new code segment (selector 0x08), it reboots.

the code for jumping to the new code segment is pretty typical, in NASM:

Code: Select all

jump_to_new_segment:
  jmp 0x08:new_seg
new_seg:
  mov eax, 0x10
  mov ds, eax
  mov ss, eax
  mov es, eax
  mov fs, eax
  mov gs, eax
  ret
I'm sure I'm missing something very simple, but after looking through forums and web pages for hours, I have come up with nothing useful.

any help will be very appreciated.

thanks in advance.

Andy
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Post by neon »

Just that I asked as it is very simple to mess:

You have disabled interrupts before jumping to pmode, right? (cli instruction)

Also, new_seg should be inside 32 bit code (use bits 32):

Code: Select all

  cli
  jmp 0x08:new_seg

bits 32

new_seg:
  mov eax, 0x10
  mov ds, eax
  mov ss, eax
  mov es, eax
  mov fs, eax
  mov gs, eax
User avatar
Zenith
Member
Member
Posts: 224
Joined: Tue Apr 10, 2007 4:42 pm

Post by Zenith »

I think the problem is that

Code: Select all

uint limit_0_15:16 __attribute__((__packed__));
uint base_0_23:24 __attribute__((__packed__));
this part will not produced the desired effect as GCC would just see 16 bits + 24 bits not fitting into uint (assuming it is 32 bits), so that it would do

Code: Select all

uint #1
limit_0_15 [16 bits]
padding [16 bits]
uint #2
base_0_23 [24 bits]
accessed [1 bit]
etc...
throwing off the alignment. Do:

Code: Select all

  uint limit_0_15:16;
  uint base_0_15:16;
  uint base_16_24:8;
Also, for readability's sake, drop the "__attribute__((__packed__));"s - just put one at the end of the struct definition. :wink:

And for <powerful diety>'s sake, people (note that this is not directly at the OP, but to half of the people who post here looking for instant help), where has the art of debugging gone to?
If you're using an emulator like Bochs, what output does it give?
Did you inspect the memory location the GDT is loaded at - are the values right?
Did you put the right values into the entry in the first place?
And if you're not using an emulator, then I strongly advise you to do so immediately.

Peace, and hope this helps,
J.S.
"Sufficiently advanced stupidity is indistinguishable from malice."
elkvis
Posts: 5
Joined: Sun Apr 13, 2008 4:40 pm
Location: River Falls, WI, USA

Post by elkvis »

neon:
I am already in PMode when I do this. I forgot to mention that I'm using GRUB to load my kernel, and that I'm just trying to reload a new GDT that I can manipulate however I want.

karekare0:
Why would using a 24-bit field throw of alignment? I thought that was the purpose of using __attribute__((__packed__)) - so that it would NOT pad the structure for alignment. I am using an emulator - sort of. I've been using vmware, but as I'm sure you know, it does not provide any kind of debugging output. this bochs debugger you're talking about - is it commercial softwar? because I'm all about open source software, and don't really want to spend any money on this project.
User avatar
Zenith
Member
Member
Posts: 224
Joined: Tue Apr 10, 2007 4:42 pm

Post by Zenith »

Before doubting me, can you at least try my suggestion?

The 4th post at
this topic might be of some help understanding why... :wink:

And Bochs and QEMU are free and open source! I'd say they're vital to OSDev... They'll give you debugging output, register values, disassembly, etc.
"Sufficiently advanced stupidity is indistinguishable from malice."
elkvis
Posts: 5
Joined: Sun Apr 13, 2008 4:40 pm
Location: River Falls, WI, USA

Post by elkvis »

karekare0 wrote:Before doubting me, can you at least try my suggestion?

The 4th post at
this topic might be of some help understanding why... :wink:

And Bochs and QEMU are free and open source! I'd say they're vital to OSDev... They'll give you debugging output, register values, disassembly, etc.
not doubting you.... if you recall, I said "why would a 24-bit field throw off alignment?" it was a question. an attempt to understand better. I can see how you could misinterpret though, given the large number of less-than-highly-skilled coders that may tend to have questions like these. after reading the post you suggested, I understand better now.

so let me see if I got this right... if I use some sort of 64-bit integer, will it work the way I have it, since the structure is 64 bits (8 bytes) long? or should I switch to using fields that are multiples of whole bytes?
iammisc
Member
Member
Posts: 269
Joined: Thu Nov 09, 2006 6:23 pm

Post by iammisc »

Your structure definition is really shaky. You never know exactly how gcc is going to align anything like that. Personally, I would either break the structure up into integer fields and do any bitwise operations manually so you can be absolutely sure that gcc is not doing anything wrong.

Also, if you don't want to do this, then just look at the assembler gcc is producing there has to be something wrong. In addition, could you please post the code that creates your segments? How do you know that your code segment is even valid?
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Post by 01000101 »

I believe there was an earlier thread about the inefficiency and inconsistency of gcc bitfield declarations
elkvis
Posts: 5
Joined: Sun Apr 13, 2008 4:40 pm
Location: River Falls, WI, USA

Post by elkvis »

perhaps I'll just redo my structures with no bitfields and do the bit by bit manipulation manually... it seems the lesser of the two evils.
Post Reply