Page 1 of 1

GDT Problem

Posted: Wed Sep 23, 2009 2:18 am
by oib111
Ever since I put in code for the GDT I've had problems. Eventually I decided, temporarily, it'd just be easier to use the GDT setup by the bootloader. But now I'm coming towards the point where having a GDT is necessary, but I just don't know what's going on. I tried using the GDT code from the demo's but that didn't work either. That lead me to believe that perhaps the IDT was the problem, except everything is fine if I just use the bootloader's GDT, so I ruled out the IDT as the source of the problem. At this point, I'm thinking perhaps it's my gdt_flush() function:

Code: Select all

void gdt_flush() {
	#ifdef _MSC_VER
		_asm lgdt[gp]
	#endif
}
I don't really see anything wrong with that though :?

Re: GDT Problem

Posted: Wed Sep 23, 2009 10:09 am
by Andyhhp
can you post all related code again please?

Re: GDT Problem

Posted: Wed Sep 23, 2009 2:26 pm
by oib111
Ok.

from gdt.h

Code: Select all

// gdt entry structure
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;
};

// pointer to gdt (needed for lgdt instruction)
struct gdt_ptr
{
    unsigned short limit;
    unsigned int base;
};
from gdt.c

Code: Select all

// define three entries (NULL entry, code descriptor, data descriptor)
struct gdt_entry gdt[3];
struct gdt_ptr gp;

// this will load our gdt
void gdt_flush() {
	#ifdef _MSC_VER
		_asm lgdt[gp]
	#endif
}

void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) {
	gdt[num].base_low = (base & 0xFFFF);
    gdt[num].base_middle = ((base >> 16) & 0xFF);
    gdt[num].base_high = ((base >> 24) & 0xFF);

    gdt[num].limit_low = (limit & 0xFFFF);
    gdt[num].granularity = ((limit >> 16) & 0x0F);

    gdt[num].granularity |= (gran & 0xF0);
    gdt[num].access = access;
}

void gdt_install() {
	unsigned short csval, dsval, ssval, esval, fsval, gsval;
	gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
	gp.base = gdt;
	 
	gdt_set_gate(0, 0, 0, 0, 0);
	// access 0x1A = 00011010 (bit 47-40)
	// granularity 0xCF = 11001111 (bit 55-48)
	gdt_set_gate(1, 0, 0xFFFFF, 0x1A, 0xCF);
	// access 0x12 = 00010010 (bit 47-40)
	// granularity 0xCF = 11001111 (bit 55-48)
	gdt_set_gate(2, 0, 0xFFFFF, 0x12, 0xCF);

	// load our GDT
	 
	gdt_flush();
}

Re: GDT Problem

Posted: Wed Sep 23, 2009 10:31 pm
by Mike
Hello,

Are the structures in gdt.h byte aligned?

Re: GDT Problem

Posted: Wed Sep 23, 2009 10:46 pm
by oib111
Yeah.

EDIT:

Fixed it...set the present bit in the GDT entries...not sure why that's a problem though. The tutorial describes that bit as only being used in Virtual Memory and just to ignore it and set it to 0. Oh well. Although, I'm having a problem with the memory maps, if anyone could take a look at that thread :)

Re: GDT Problem

Posted: Thu Sep 24, 2009 12:41 pm
by Andyhhp
Hmm - the present bit tells the CPU whether the desctiptor is to be used or not. Can you find where in the tutorial it says to leave the present bit as 0?

~Andrew

Re: GDT Problem

Posted: Thu Sep 24, 2009 2:11 pm
by oib111
Bit 7 (Bit 47 in GDT): Used to indicate the segment is in memory (Used with virtual memory). Set to zero for now, since we are not using virtual memory yet

Re: GDT Problem

Posted: Thu Sep 24, 2009 5:51 pm
by Andyhhp
lol - thats supposed to be the present bit in the Page Table Entries, not the GDT.

That would explain the problems

Re: GDT Problem

Posted: Thu Sep 24, 2009 8:43 pm
by oib111
Lol...ok, can anyone look at that memory problem though?

Re: GDT Problem

Posted: Thu Sep 24, 2009 10:47 pm
by Mike
Hello,

That bit in the GDT tells the processor if the segment is in memory or not. If it is 0, the segment is not in memory and thus cannot be used. If it is 1 (should be), the segment is in memory and can be used. It is an error in the tutorial - it should be 1 if it is in memory in all cases and will be corrected. :)

Re: GDT Problem

Posted: Fri Sep 25, 2009 12:01 am
by oib111
Thanks! I have a question about the memory detection though. What is it really detecting? I thought it was detecting the total amount of RAM installed in the system, and then certain areas were available and some were reserved (as designated by the memory map). But it seems that it's getting some random value and the memory map contains the real info (all types that can be used combined equals the total memory)? Or does Bochs treat the amount of RAM you specify as the amount of usable memory and not total memory?

EDIT:

Just realized I had some memory holes. It seems Bochs gives me 4GB of RAM but the parts I can actually use are 128MB. So I have around 3968MB worth of memory holes (there are two). Now here's a question, is it safe to set those memory holes as in use as well or are they bad memory? Because it's going to be very annoying if I have to keep track of where and how big the holes are and then rewrite my functions to compensate for them. Also, will this happen on a real computer, or is it just because I'm using an emulator (I read up on wiki.osdev.org that memory size and maps seem to be problematic on emulators/VMs)?

Re: GDT Problem

Posted: Fri Sep 25, 2009 9:19 pm
by Andyhhp
Memory holes are literally holes in memory - it is unsafe to use them normally

In some cases, they are there for backward compatability; in other cases, they are memory mapped hardware that must be used carefully.

AFAIR, all modern computers have a whole between 15-16MB of physical memory and one for the graphics card (on a 32bit computer without PAE, this is why 4GB of ram only shows up as 3.5GB usable etc.)

Re: GDT Problem

Posted: Fri Sep 25, 2009 10:59 pm
by oib111
I don't see a memory hole between 15-16MB?
0x0-0x9f000 (total size 0x9f000)
0x9f000-0xa0000 (total size 0x1000)
non contiguous by 0x48000 bytes
0xe8000-0x100000 (total size 0x18000)
0x100000-0x7ff0000 (total size 0x7ef0000)
non contiguous by 0xf7fd0000 bytes
0xfffc0000-0x100000000 (total size 0x40000)
Couple questions.

1. If I'm reporting memory to the user, would it be better to report the amount of memory I can use initially or all memory (including the reserved areas).
2. Does the memory map go from lowest to highest address, and if it does, is the last region described in the memory map always end at the last physical address of memory?
3. Is there any way to get GRUB to pass me the size of my kernel in bytes or sectors?