Page 1 of 1
outb to 0x1F7 causes GPF
Posted: Mon Jun 30, 2014 2:27 pm
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
Re: outb to 0x1F7 causes GPF
Posted: Mon Jun 30, 2014 3:01 pm
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.
Re: outb to 0x1F7 causes GPF
Posted: Mon Jun 30, 2014 3:03 pm
by Combuster
Just to make sure, did you read and fix everything in
Bran's known bugs and
Posting Checklist
Re: outb to 0x1F7 causes GPF
Posted: Mon Jun 30, 2014 4:29 pm
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); ).
Re: outb to 0x1F7 causes GPF
Posted: Tue Jul 01, 2014 6:06 am
by Candy
Can you post some form of IDT? A hexdump would be OK for me...
Re: outb to 0x1F7 causes GPF
Posted: Tue Jul 01, 2014 9:35 am
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.
Re: outb to 0x1F7 causes GPF
Posted: Tue Jul 01, 2014 1:14 pm
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
Re: outb to 0x1F7 causes GPF
Posted: Tue Jul 01, 2014 1:51 pm
by xenos
In bochs debugger it's even easier: you can enter info idt to show the contents of the IDT.
Re: outb to 0x1F7 causes GPF
Posted: Thu Jul 03, 2014 7:15 pm
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.