Page 1 of 1

GPF error codes?

Posted: Tue Jul 24, 2007 8:29 am
by mmiikkee12
I'm getting a GPF, but I'm not quite sure how to decode the error code. The Intel manual says that it's the selector that caused the error, but how do I know what exactly went wrong? General protection fault is just too... general.

(The GPF occured when I tried to load 0x04 into CS, and error code was 0x04... there doesn't seem to be any extra info in it.)

Posted: Tue Jul 24, 2007 8:48 am
by AJ
Very often, the GPF error code does just contain a faulting segment descriptor.

If you are in pmode, I suspect you want 0x20 rather than 0x04, as you load segment registers with a byte offset in to the GDT and each GDT entry is 0x08 bytes long. The NULL segment is 0x00 and the first useable segment is 0x08.

HTH,
Adam

Posted: Tue Jul 24, 2007 8:53 am
by mmiikkee12
If you are in pmode, I suspect you want 0x20 rather than 0x04, as you load segment registers with a byte offset in to the GDT and each GDT entry is 0x08 bytes long. The NULL segment is 0x00 and the first useable segment is 0x08.
No, 0x04 is the first segment in the LDT.

Posted: Tue Jul 24, 2007 9:01 am
by AJ
Oops :oops: . I never use a LDT.

In that case, Bochs is often quite useful in this case. Just above the register dump, it will often give you the reason for a GPF (such as CS = 0 not valid, or TSS invalid, or something else...)

Cheers,
Adam

Posted: Tue Jul 24, 2007 9:07 am
by mmiikkee12
Ah, that 'make btest' target I never use... :)
00037724205e[CPU0 ] fetch_raw_descriptor: LDT: index (7)0 > limit (0)
So, what I got from that: A random number, and then an error occured on CPU 0, and the LDT's limit is set to 0. (What does the 7 in parentheses mean?)

That LDT limit is probably a problem. Checking that out now.

Posted: Tue Jul 24, 2007 9:30 am
by Candy
mmiikkee12 wrote: (What does the 7 in parentheses mean?)
That's probably the byte it tried to read, on which it failed.

Posted: Tue Jul 24, 2007 2:54 pm
by JamesM
If you're confused about bochs' error/panic messages (They can sometimes be quite cryptic) a quick grep of the source code can maybe help decipher it. (it's online and has a search function). It'll let you know what each random number means! (Incidentally the first long number is bochs' system timestamp).

JamesM

Re: GPF error codes?

Posted: Tue Jul 24, 2007 3:52 pm
by pcmattman
mmiikkee12 wrote:I'm getting a GPF, but I'm not quite sure how to decode the error code. The Intel manual says that it's the selector that caused the error, but how do I know what exactly went wrong? General protection fault is just too... general.

(The GPF occured when I tried to load 0x04 into CS, and error code was 0x04... there doesn't seem to be any extra info in it.)
Try this (r->err_code is the error code of the GPF):

Code: Select all

			union errcodedat {
				struct {
					unsigned int ext : 1;
					unsigned int idt : 1;
					unsigned int ti : 1;
					unsigned int sel : 13;
					unsigned int rsvd : 16;
				} errcode;
				unsigned int err_code;
			} myerrcode = { r->err_code };
			kprintf( "Error code: 0x%x [Sel=0x%x, External: %s, Selector is an IDT entry: %s, LDT: %s]\n", r->err_code, myerrcode.errcode.sel, myerrcode.errcode.ext ? "yes" : "no", myerrcode.errcode.idt ? "yes" : "no", myerrcode.errcode.ti ? "yes" : "no" );
That can help you get some information from your error code.

Posted: Wed Jul 25, 2007 7:23 am
by mmiikkee12

Code: Select all

Error code: 0x4 [Sel=0x0, External: no, IDT: no, [b]LDT: no[/b], reserved bits: 0]
That's weird... doesn't 0x4 mean selector 0 from the LDT?

Posted: Wed Jul 25, 2007 9:25 am
by mmiikkee12
Just ran it through GDB.
[quote][mike in ~/code/popcorn/trunk/src/kernel]$ gdb
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu".
0x00008789 in ?? ()
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) break Panic::_panic
Breakpoint 1 at 0x102074: file Panic.cpp, line 66.
(gdb) c
Continuing.

Breakpoint 1, Panic::_panic (message=0x1049ef "General Protection Fault", file=0x104913 "[unknown file]", line=0) at Panic.cpp:66
66 void _panic(const char *message, const char *file, uint_32 line)
(gdb) set print pretty on
(gdb) print Tasks::tasks[0].ldt
$1 = {{
limit_low = 65535,
base_low = 0,
base_middle = 0 '\0',
access = 154 '\232',
granularity = 207 'Ã

Posted: Wed Jul 25, 2007 11:12 am
by JamesM
I take it you are actually loading the LDT? As in, as well as calling lgdt, you're calling the lldt instruction as well?

obvious stuff but worth checking anyway :P

I don't do much segmentation (not supported well on x64 systems) so I can't be much help I'm afraid!

Sorry!

JamesM

Posted: Wed Jul 25, 2007 12:06 pm
by mmiikkee12
JamesM wrote:I take it you are actually loading the LDT? As in, as well as calling lgdt, you're calling the lldt instruction as well?
Yes (not at the same time as lgdt though, it's later when I set up multitasking.)
obvious stuff but worth checking anyway :P
Yeah... sometimes it's the obvious things that crash stuff :)
I don't do much segmentation (not supported well on x64 systems)
Bah... who cares about x64 anyway :)

Edit: I came up with a function to dump all the flags in a GDT descriptor. Here's what it gave me for the first LDT:
base 11f7d4, limit 17, type 2(s), dpl 0, present, 32-bit, granularity 0