gillo04
gillo04

Reputation: 98

General protection fault when initializing mouse driver

I'm writing an x86_64 os and testing it on qemu pc. I'm trying to implement a mouse driver, but when I reach the end of the initialization function, I get a general protection fault. Another wierd thing that happens which I'm not sure is normal is that all call to wait_mouse end up timeouting (for testing purpouses I ignore the timeout, also because that is what the code I took did). Here is my code (which seems to be what every single hobby kernel online uses):

const MOUSE_PORT: u16 = 0x60;
const MOUSE_STATUS: u16 = 0x64;
const MOUSE_ABIT: u8 = 0x02;
const MOUSE_BBIT: u8 = 0x01;
const MOUSE_WRITE: u8 = 0xD4;
const MOUSE_F_BIT: u16 = 0x20;
const MOUSE_V_BIT: u16 = 0x08;

pub fn init() -> Result<(), &'static str> {
    let mut status: u8 = 0;

    unsafe {
        asm!("cli");
    }
    mouse_wait(true)?;
    outb(MOUSE_STATUS, 0xA8);
    mouse_wait(true)?;
    outb(MOUSE_STATUS, 0x20);
    mouse_wait(false)?;
    status = inb(0x60) | 2;
    mouse_wait(true)?;
    outb(MOUSE_STATUS, 0x60);
    mouse_wait(true)?;
    outb(MOUSE_PORT, status);
    mouse_write(0xF6)?;
    mouse_read()?;
    mouse_write(0xF4)?;
    mouse_read()?;
    unsafe {
        asm!("sti");
    }

    Ok(())
}

fn mouse_wait(a_type: bool) -> Result<(), &'static str> {
    let mut timeout = 100000;
    if !a_type {
        while timeout > 0 {
            if inb(MOUSE_STATUS) & MOUSE_BBIT == 1 {
                return Ok(());
            }
            timeout -= 1;
        }
    } else {
        while timeout > 0 {
            if inb(MOUSE_STATUS) & MOUSE_ABIT != 0 {
                return Ok(());
            }
            timeout -= 1;
        }
    }
    // Err("Mouse timeout")
    Ok(())
}

fn mouse_write(write: u8) -> Result<(), &'static str> {
    mouse_wait(true)?;
    outb(MOUSE_STATUS, MOUSE_WRITE);
    mouse_wait(true)?;
    outb(MOUSE_PORT, write);
    Ok(())
}

fn mouse_read() -> Result<u8, &'static str> {
    mouse_wait(false)?;
    Ok(inb(MOUSE_PORT))
}

I looked at the instruction pointed to by the RIP saved by the general protection fault, and it appears to be a pop instruction right before the ret of the initialization routine.

Here is what I get from qemu:

Servicing hardware INT=0x21
   221: v=21 e=0000 i=0 cpl=0 IP=0008:000000000e097a07 pc=000000000e097a07 SP=0010:000000000fe96770 env->regs[R_EAX]=0000000000000000
RAX=0000000000000000 RBX=0000000002cbb000 RCX=00000000000186a0 RDX=00000000801b0060
RSI=000000000e0a9118 RDI=0000000000000064 RBP=000000000fe96801 RSP=000000000fe96770
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000064 R13=000000000e98d000 R14=0000111100000000 R15=000000000fe967a8
RIP=000000000e097a07 RFL=00000246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0028 000000000e0ae151 00000067 00008900 DPL=0 TSS64-avl
GDT=     000000000e0af2e8 00000037
IDT=     000000000e0ae1c8 00000fff
CR0=80010033 CR2=0000000000000000 CR3=0000000000449000 CR4=00000668
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000001 CCD=0000000000000001 CCO=CLR
EFER=0000000000000d00
Servicing hardware INT=0x24
   222: v=24 e=0000 i=0 cpl=0 IP=0008:000000000e097a07 pc=000000000e097a07 SP=0010:000000000fe96770 env->regs[R_EAX]=0000000000000000
RAX=0000000000000000 RBX=0000000002cbb000 RCX=00000000000186a0 RDX=00000000801b0060
RSI=000000000e0a9118 RDI=0000000000000064 RBP=000000000fe96801 RSP=000000000fe96770
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000064 R13=000000000e98d000 R14=0000111100000000 R15=000000000fe967a8
RIP=000000000e097a07 RFL=00000246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0028 000000000e0ae151 00000067 00008900 DPL=0 TSS64-avl
GDT=     000000000e0af2e8 00000037
IDT=     000000000e0ae1c8 00000fff
CR0=80010033 CR2=0000000000000000 CR3=0000000000449000 CR4=00000668
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000044 CCD=0000000000000000 CCO=EFLAGS
EFER=0000000000000d00
check_exception old: 0xffffffff new 0xd
   223: v=0d e=0122 i=0 cpl=0 IP=0008:000000000e097a07 pc=000000000e097a07 SP=0010:000000000fe96770 env->regs[R_EAX]=0000000000000000
RAX=0000000000000000 RBX=0000000002cbb000 RCX=00000000000186a0 RDX=00000000801b0060
RSI=000000000e0a9118 RDI=0000000000000064 RBP=000000000fe96801 RSP=000000000fe96770
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000064 R13=000000000e98d000 R14=0000111100000000 R15=000000000fe967a8
RIP=000000000e097a07 RFL=00000246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 0000000000000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0028 000000000e0ae151 00000067 00008900 DPL=0 TSS64-avl
GDT=     000000000e0af2e8 00000037
IDT=     000000000e0ae1c8 00000fff
CR0=80010033 CR2=0000000000000000 CR3=0000000000449000 CR4=00000668
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000044 CCD=0000000000000000 CCO=EFLAGS
EFER=0000000000000d00

I set the interrupt service routine at 44 (32 + 12) before calling the init function. At the moment it just prints "mouse!" and loops forever, without sending any EOI (which shouldn't be needed). Are there mabye any other ps2 configurations I need to do before calling init? Thanks for the help!

Upvotes: 0

Views: 94

Answers (0)

Related Questions