OS crashes whenever I press a key

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
User avatar
obiwac
Member
Member
Posts: 149
Joined: Fri Jan 27, 2017 12:15 pm
Libera.chat IRC: obiwac
Location: Belgium

OS crashes whenever I press a key

Post by obiwac »

Whenever I press a key, instead of sending irq 1, it crashes my os with a triple fault. It does the same with the PIT, so I have disabled it for now. I have tried to do it manually with asm("int $1"), but it still crashes. I am compiling with gcc & nasm. Here are my codes:

irq.c:

Code: Select all


#include "irq.h"

void* irq_routines[16] = {
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0
	
};

void irq_add_handler(int irq, void (*handler) (struct registers* r)) {
	irq_routines[irq] = handler;
	
}

void irq_remove_handler(int irq) {
	irq_routines[irq] = 0;
	
}

void irq_remap(void) {
	outportb(0x20, 0x11);
	outportb(0xA0, 0x11);
	
	outportb(0x21, 0x20);
	outportb(0xA1, 0x28);
	outportb(0x21, 0x04);
	outportb(0xA1, 0x02);
	outportb(0x21, 0x01);
	outportb(0xA1, 0x01);
	outportb(0x21, 0x0);
	outportb(0xA1, 0x0);
	
}

void irq_init(void) {
	irq_remap();
	
	set_idt_gate(32, (unsigned) irq0);
	set_idt_gate(33, (unsigned) irq1);
	set_idt_gate(34, (unsigned) irq2);
	set_idt_gate(35, (unsigned) irq3);
	set_idt_gate(36, (unsigned) irq4);
	set_idt_gate(37, (unsigned) irq5);
	set_idt_gate(38, (unsigned) irq6);
	set_idt_gate(39, (unsigned) irq7);
	set_idt_gate(40, (unsigned) irq8);
	set_idt_gate(41, (unsigned) irq9);
	set_idt_gate(42, (unsigned) irq10);
	set_idt_gate(43, (unsigned) irq11);
	set_idt_gate(44, (unsigned) irq12);
	set_idt_gate(45, (unsigned) irq13);
	set_idt_gate(46, (unsigned) irq14);
	set_idt_gate(47, (unsigned) irq15);
	
}

void irq_handler(struct registers* r) {
	void (*handler) (struct registers* r);
	handler = irq_routines[r->num - 32];
	
	if (handler) {
		handler(r);
		
	} if (r->num >= 40) {
		outportb(0xA0, 0x20);
		
	}
	
	outportb(0x20, 0x20);
	
}
I don't think irq.h is important. Its just some

Code: Select all

extern void irq ... ();
.

keyboard.c

Code: Select all


#include "keyboard_driver.h"

static uint8 press;
static uint8 release;

void keyboard_handler(struct registers* r) {
	uint8 scancode;
	scancode = inportb(0x60);
	
	println("Keypress", 0x07);
	
	if (scancode & 0x80) release = scancode;
	else press = scancode;
	
}

void keyboard_install(void) {
	while (inportb(0x64) & 0x1) {
		inportb(0x60);
		
	}
	
	outportb(0x64, 0xae);
	outportb(0x64, 0x20);
	
	uint8 status = (inportb(0x60) | 1) & ~0x10;
	
	outportb(0x64, 0x60);
	outportb(0x60, status);
	outportb(0x60, 0xf4);
	
	//irq_add_handler(33, keyboard_handler);
	irq_add_handler(1, keyboard_handler);
	
}

uint8 poll_key(void) {
	uint8 temp = press;
	press = 127;
	return temp;
	
}

uint8 poll_key_release(void) {
	uint8 temp = release;
	release = 127;
	return temp;
	
}
idt.c

Code: Select all


static uint8 flags = 0x8E;

void set_idt_gate(int n, uint32 handler) {
	idt[n].high_offset = high_16(handler);
	idt[n].low_offset = low_16(handler);
	idt[n].sel = KERNEL_CS;
	
	idt[n].always0 = 0;
	idt[n].flags = flags; 
	
}

void set_idt(void) {
	idt_reg.limit = (uint32) &idt;
	idt_reg.base = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
	__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
	
}

void set_idt_flags(uint8 _flags) {
	flags = _flags;
	
}
and the assembly for interrupts:

Code: Select all

global irq0
continues up to...
global irq15

irq0:
	cli
	push byte 0
	push byte 32
	jmp irq_common

irq1:
	cli
	push byte 0
	push byte 33
	jmp irq_common .. and so on...

extern irq_handler
irq_common:
	pusha
	push ds
	push es
	push fs
	push gs
	
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	
	mov eax, esp
	push eax
	mov eax, irq_handler
	call eax
	pop eax
	
	pop gs
	pop fs
	pop es
	pop ds
	popa
		
	add esp, 8
	iret
Thanks in advance!
Last edited by obiwac on Wed Apr 05, 2017 11:36 am, edited 1 time in total.
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: OS crashes whenever I press a key

Post by LtG »

Did I read this wrong or did you mix these two up?

Code: Select all

   idt_reg.limit = (uint32) &idt;
   idt_reg.base = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
Also, would be useful if you'd do some troubleshooting first and tell us what you found, like single stepping with a debugger.. To some debuggers are intimidating but with OS dev you pretty much have to get used to it.
User avatar
obiwac
Member
Member
Posts: 149
Joined: Fri Jan 27, 2017 12:15 pm
Libera.chat IRC: obiwac
Location: Belgium

Re: OS crashes whenever I press a key

Post by obiwac »

Thanks for your help!

Code: Select all

dbf event: Fatal error! (hyper)
.eax=00000000 .ebx=00000000 .ecx=00000000 .edx=00000000 .esi=00000000 .edi=00000000
.eip=00000000 .esp=ff920000 .ebp=00000000 .iopl=0 nv up di pl nz na pe nc
.cs=0000 .ds=0000 .es=0000 .fs=0000 .gs=0000 .ss=0000              .eflags=00000000
u: error: DBGCCmdHlpVarToDbgfAddr failed on '0000:00000000 L 0': VERR_SELECTOR_NOT_PRESENT
So I get this in the virtualbox debugger. I don't really know what this means though.
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: OS crashes whenever I press a key

Post by LtG »

obiwac wrote:Thanks for your help!

Code: Select all

dbf event: Fatal error! (hyper)
.eax=00000000 .ebx=00000000 .ecx=00000000 .edx=00000000 .esi=00000000 .edi=00000000
.eip=00000000 .esp=ff920000 .ebp=00000000 .iopl=0 nv up di pl nz na pe nc
.cs=0000 .ds=0000 .es=0000 .fs=0000 .gs=0000 .ss=0000              .eflags=00000000
u: error: DBGCCmdHlpVarToDbgfAddr failed on '0000:00000000 L 0': VERR_SELECTOR_NOT_PRESENT
So I get this in the virtualbox debugger. I don't really know what this means though.
Don't know much about vbox, I prefer qemu and bochs. What exactly did you do and what happens?

Based on the error I would assume it's because your seg registers are all 0x0 (I'm assuming you're using protected mode):
.cs=0000 .ds=0000 .es=0000 .fs=0000 .gs=0000 .ss=0000 .eflags=00000000

You need use valid segment descriptors, not sure why they're all zero, did you set them all to zero?

Also, if this is your first go at osdev, I might recommend going thru the bare bones tutorial to get something working and then moving from there and when ever you get an issue you can easily roll back a couple of small changes getting back to working code and then figure out what exactly you did wrong. That is assuming you use version control, which you should =)
User avatar
obiwac
Member
Member
Posts: 149
Joined: Fri Jan 27, 2017 12:15 pm
Libera.chat IRC: obiwac
Location: Belgium

Re: OS crashes whenever I press a key

Post by obiwac »

But I do set them in the assembly irq_common label... And I don't set them to 0, I set them to ax which is set to 16.
Ankeraout
Member
Member
Posts: 25
Joined: Tue Feb 28, 2017 10:22 am

Re: OS crashes whenever I press a key

Post by Ankeraout »

In irq_common :

Code: Select all

add esp, 8
iret
You forgot to send end of interrupt to the PIC before IRET !

I don't think this will solve the problem.
You should implement int0 - int31 handlers and display the called int number to the screen then sticks in an infinite loop to know what is the first called exception handler, which will tell you what goes wrong according to this page.
User avatar
obiwac
Member
Member
Posts: 149
Joined: Fri Jan 27, 2017 12:15 pm
Libera.chat IRC: obiwac
Location: Belgium

Re: OS crashes whenever I press a key

Post by obiwac »

Thanks! I do have ints 0-31 , and so I get a General Protection fault, and then a triple fault, and then my os crashes.
FusT
Member
Member
Posts: 91
Joined: Wed Sep 19, 2012 3:43 am
Location: The Netherlands

Re: OS crashes whenever I press a key

Post by FusT »

Sounds to me like your IDT isn't set up properly.
Are you sure it's valid and loaded correctly? Could you post a dump (on bochs it's the 'info idt' debugger command)?
Ankeraout
Member
Member
Posts: 25
Joined: Tue Feb 28, 2017 10:22 am

Re: OS crashes whenever I press a key

Post by Ankeraout »

A General Protection Fault may occur for various reasons. The most common are:
- Segment error (privilege, type, limit, read/write rights).
- Executing a privileged instruction while CPL != 0.
- Writing a 1 in a reserved register field.
--> Referencing or accessing a null-descriptor.
The saved instruction pointer points to the instruction which caused the exception.
As LtG said, all of your segment registers are pointing to the null gdt entry. This could be your problem.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: OS crashes whenever I press a key

Post by BenLunt »

obiwac wrote:

Code: Select all

void irq_handler(struct registers* r) {
	void (*handler) (struct registers* r);
	handler = irq_routines[r->num - 32];
I don't think irq.h is important. Its just some

Code: Select all

extern void irq ... ();
.
I think irq.h is important. It probably shows us the 'struct registers' definition.

In your code, the stack looks like:

Code: Select all

 push byte 0  [dword]
 push byte 32 [dword]
 pusha        [8 words]  (note, probably not dwords)
    ; should this be 'pushad'?
 push ds  [dword]
 push es  [dword]
 push fs  [dword]
 push gs  [dword]
 push eax [dword]
 call handler return value [dword]
You save the value in eax of the current stack location before calling the handler. The handler assumes the above format.
What does 'struct registers' look like?

Code: Select all

struct registers {
  dword gs;
  dword fs;
  dword es;
  dword ds;
  word  pusha[8];
  dword num;
  dword zero;
};
I am guessing that you have modified the 'struct registers' and/or the 'push'es in the .asm code and they no longer match.

Then, here is the error I believe you have:

Code: Select all

	handler = irq_routines[r->num - 32];
r->num = 0, so 'handler' above now has a value of 'undefined' since it grabs a value 32 dwords before the list of IRQ handlers you have.
i.e.:

Code: Select all

	handler = irq_routines[0 - 32];
is the same as

Code: Select all

	handler = irq_routines[-32];
which is in error...

Make sure your structure matches your pushes, and check whether the assembler is pushing words or dwords with the 'pusha' instruction. Then make sure your structure matches the pusha/pushad instruction.

Just my guess,
Ben
http://www.fysnet.net/osdesign_book_series.htm
User avatar
obiwac
Member
Member
Posts: 149
Joined: Fri Jan 27, 2017 12:15 pm
Libera.chat IRC: obiwac
Location: Belgium

Re: OS crashes whenever I press a key

Post by obiwac »

Thank you to everyone for having helped! I found out it was just a stupid little mistake. I was messing around once, and I remapped the keyboard interrupt to something else. Sorry for wasting your time! But maybe I should still look more in depth for the registers.

Code: Select all

struct __attribute__((packed)) registers {
	unsigned int gs, fs, es, ds;
	unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
	unsigned int num, err_code;
	unsigned int eip, cs, eflags, useresp, ss;
	
};
Post Reply