outb to 0x1F7 causes GPF

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
tcsullivan
Posts: 5
Joined: Mon Jun 30, 2014 11:03 am

outb to 0x1F7 causes GPF

Post by tcsullivan »

Hello,

I'm trying to write a simple ATA driver using PIO. I've written out code to run the IDENTIFY command, however when I run it I get a General Protection Fault.

Bochs says:

Code: Select all

fetch_raw_descriptor: GDT: index (a7) 14 > limit (17)
I guess the GDT has to be the problem, but I don't see any errors in my GDT.

This is where the error occurs in the code:

Code: Select all

outb(0x1F6,0xA0);
outb(0x1F2,0);
outb(0x1F3,0);
outb(0x1F4,0);
outb(0x1F5,0);
outb(0x1F7,0xEC); // Causes the GPF
If I comment out that last line the code works fine, but that line needs to be there (it sends the IDENTIFY command). I've also tried sending other commands to 0x1F7, but they all result in a GPF. Does anybody know what the problem is?

Here's some of the code for my GDT:

Code: Select all

#define GDT_ENTRIES 3

typedef struct {
	uint16_t limit_l;
	uint16_t base_l;
	uint8_t  base_m;
	uint8_t  type;
	uint8_t  gran;
	uint8_t  base_h;
} __attribute__((packed)) gdt_entry;

typedef struct {
	uint16_t limit;
	uint32_t base;
} __attribute__((packed)) gdt_pointer;

gdt_pointer gp;
gdt_entry   gdt[GDT_ENTRIES];

void gdt_set_entry(uint16_t n,uint32_t base,uint32_t limit,uint8_t type,uint8_t gran){
	gdt[n].base_l=base & 0xFFFF;
	gdt[n].base_m=(base>>16)  & 0x00FF;
	gdt[n].base_h=(base>>24)  & 0x00FF;
	gdt[n].limit_l=limit & 0xFFFF;
	gdt[n].gran =(limit>>16) & 0x000F;
   gdt[n].gran |= gran & 0x00F0;
	gdt[n].type = type;
}

extern void gdt_load();

void GDT_init(void){
	gp.limit=sizeof(gdt_entry)*GDT_ENTRIES-1;
   gp.base =(uint32_t)&gdt;
	gdt_set_entry(0,0,0x00000000,0x00,0x00);
	gdt_set_entry(1,0,0xFFFFFFFF,0x9A,0xCF);
	gdt_set_entry(2,0,0xFFFFFFFF,0x92,0xCF);
	gdt_load();
}
The gdt_load() function:

Code: Select all

global gdt_load
extern gp
gdt_load:
   lgdt [gp]
   mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	jmp 0x08:.flush
.flush:
	ret
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: outb to 0x1F7 causes GPF

Post by Gigasoft »

The GDT is fine, but chances are that your IDT is not. For example, there might be a problem with the entry that corresponds to IRQ14. Or, there could be a bug in your IRQ handler that makes it go somewhere it shouldn't.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: outb to 0x1F7 causes GPF

Post by Combuster »

Just to make sure, did you read and fix everything in Bran's known bugs and Posting Checklist
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
tcsullivan
Posts: 5
Joined: Mon Jun 30, 2014 11:03 am

Re: outb to 0x1F7 causes GPF

Post by tcsullivan »

I've looked through my IDT and compared it to the ones in Bran and jmolloy's tutorials, and it looks fine (if you want to see the code I can post it). According to the Posting Checklist I didn't post all the information I should have, so I'll share a bit more info here.

My OS boots with GRUB 1.99 (2?), I'm using the most recent version of Bochs, and I'm in protected mode when I get the error.

Here is what Bochs says when I close it:

Code: Select all

>>PANIC<< User requested shutdown.
00086356000i[CPU0 ] CPU is in protected mode (active)
00086356000i[CPU0 ] CS.d_b = 32 bit
00086356000i[CPU0 ] SS.d_b = 32 bit
00086356000i[CPU0 ] EFER   = 0x00000000
00086356000i[CPU0 ] | RAX=0000000000000000  RBX=00000000000000a0
00086356000i[CPU0 ] | RCX=0000000000000140  RDX=0000000000000140
00086356000i[CPU0 ] | RSP=0000000000107e14  RBP=0000000000000000
00086356000i[CPU0 ] | RSI=0000000000000000  RDI=0000000000000000
00086356000i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00086356000i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00086356000i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00086356000i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00086356000i[CPU0 ] | IOPL=0 ID vip vif ac vm rf nt of df if tf sf zf AF PF cf
00086356000i[CPU0 ] | SEG selector     base    limit G D
00086356000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00086356000i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00086356000i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00086356000i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00086356000i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00086356000i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00086356000i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00086356000i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00086356000i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00086356000i[CPU0 ] | RIP=0000000000101190 (0000000000101190)
00086356000i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00086356000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00086356000i[CPU0 ] 0x0000000000101190>> jmp .-2 (0x00101190) : EBFE
00086356000i[CMOS ] Last time is 1404167237 (Mon Jun 30 18:27:17 2014)
00086356000i[     ] restoring default signal behavior
00086356000i[CTRL ] quit_sim called with exit code 1
BTW when I get the GPF I enter an infinite loop ( while(1); ).
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re: outb to 0x1F7 causes GPF

Post by Candy »

Can you post some form of IDT? A hexdump would be OK for me...
tcsullivan
Posts: 5
Joined: Mon Jun 30, 2014 11:03 am

Re: outb to 0x1F7 causes GPF

Post by tcsullivan »

I'm not sure how to get a hexdump of the IDT, if you can tell me how I will. I've gotten this to work before, I was just starting from scratch again because my old code was too long, messy and hard to understand. I tried putting my old working code in to my new design but that didn't work, instead I think I'll just work with the old version and try to clean that up.

Thanks for the help that's already been given, I never knew about the Posting Guidelines page or Bran's known bugs.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re: outb to 0x1F7 causes GPF

Post by Candy »

If you recompile Bochs with debugger support you can use the following commands:

- Ctrl-c : interrupt it to the debugger

In the debugger:

- c : continue execution
- s : step one instruction, or step into a call
- n : step one instruction, or step across a call
- x /Nxb <address> : dump logical address. N is how many bytes (so like "x /64xb 0x20030")
- xp /Nxb <address> : dump physical address. N is how many bytes.
- regs : dump regular registers
- sreg: dump system registers
- creg: dump CR registers
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: outb to 0x1F7 causes GPF

Post by xenos »

In bochs debugger it's even easier: you can enter info idt to show the contents of the IDT.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
tcsullivan
Posts: 5
Joined: Mon Jun 30, 2014 11:03 am

Re: outb to 0x1F7 causes GPF

Post by tcsullivan »

Alright, after an hour or two of troubleshooting I got the bochs source to build with debugging enabled. I ran "info idt" as soon as my code crashed and I got a bunch of entries that looked like this:

Code: Select all

IDT[0x00]=32-Bit Interrupt Gate target=0x0008:0x00100045, DPL=0
As I mentioned before, I switched back to my older code that worked. After running "info idt" there, the only difference between I could find was that all the entries' targets were 0x20 lower. For example:

Working IDT:

Code: Select all

IDT[0x00]=32-Bit Interrupt Gate target=0x0008:0x00100065, DPL=0
Not working IDT:

Code: Select all

IDT[0x00]=32-Bit Interrupt Gate target=0x0008:0x00100045, DPL=0
I'm not sure why this happens, but I don't really need to know. I've cleaned up my older IDT code and things are working fine now.
Post Reply