OSDev.org https://forum.osdev.org/ |
|
[Solved] Interrupt descriptor table problem https://forum.osdev.org/viewtopic.php?f=1&t=33091 |
Page 1 of 1 |
Author: | Matt1223 [ Mon Jul 30, 2018 3:27 am ] |
Post subject: | [Solved] Interrupt descriptor table problem |
Hi, I have a problem because my interrupts doesn't works. I set IDT and then divide by 0 to get interrupt. Unfortunately it gets triple fault instead. I run my OS on bochs. It's 32 bits OS. I use Nasm inline assembly by adding -masm=intel while compilation. Here are the source files: _____________________kernel.c________________________ Code: #include "kernel.h" void _start(void) { term = New_TerminalB8000(); T_Clear(term); idt_init(); int a = 5; int b = 0; T_Print(term, "%d", a/b); for(;;); } _____________________idt.h________________________ Code: #pragma once #include "common.h" #include "int_handlers.h" #include "terminal.h" #include "kernel.h" struct IDTEntry { uint16_t offset_0_15; // offset bits 0..15 uint16_t selector; // a code segment selector in GDT or LDT uint8_t zero; // unused, set to 0 uint8_t flags; // type and attributes, see below uint16_t offset_16_31; // offset bits 16..31 }__attribute__((packed)); struct IDTR { uint16_t limit; uint32_t base; }__attribute__((packed)); typedef struct IDTEntry IDTEntry; typedef struct IDTR IDTR; void idt_init(); _____________________idt.c________________________ Code: #include "idt.h" #define SETIDTDESCR(d, offset) { \ d.offset_0_15 = ((uint32_t)offset & 0xffff); \ d.selector = 0x8; \ d.zero = 0; \ d.flags = 0x8E; \ d.offset_16_31 = (((uint32_t)offset >> 16) & 0xffff); \ } IDTEntry IDT[256]; void idt_init() { for(int i=0; i<=32; i++) SETIDTDESCR(IDT[i], interrupt_handler); IDTR ptr = { (uint16_t)((256 * 8 ) - 1), (uint32_t)&IDT }; __asm("lidt [0]" : : "m"(ptr)); } _____________________int_handlers.h________________________ Code: #pragma once #include "common.h" #include "kernel.h" void interrupt_handler(); _____________________int_handlers.c________________________ Code: #include "int_handlers.h" void interrupt_handler() { T_Print(term, "Interrupt"); for(;;); } Please help me! |
Author: | frabert [ Mon Jul 30, 2018 3:58 am ] |
Post subject: | Re: Interrupt descriptor table problem |
You can use [ code ] tags to show your source listings so they are nicer to read. That being said, have you read this? You can't simply use a standard C function as an ISR, it does not have the correct cleanup/return procedure. |
Author: | quirck [ Mon Jul 30, 2018 4:01 am ] |
Post subject: | Re: Interrupt descriptor table problem |
Shouldn't Code: __asm("lidt [0]" : : "m"(ptr)); be Code: __asm("lidt [%0]" : : "m"(ptr)); instead?Also, what error does Bochs print? |
Author: | Matt1223 [ Mon Jul 30, 2018 8:19 am ] |
Post subject: | Re: Interrupt descriptor table problem |
frabert wrote: You can use [ code ] tags to show your source listings so they are nicer to read. That being said, have you read this? You can't simply use a standard C function as an ISR, it does not have the correct cleanup/return procedure. Thanks for the tip with [ code ] ! I know that I can't use standard C function as an ISR, this is temporarily solution. I want to make IDT working and then I will make proper ISR. |
Author: | Matt1223 [ Mon Jul 30, 2018 8:26 am ] |
Post subject: | Re: Interrupt descriptor table problem |
quirck wrote: Shouldn't Code: __asm("lidt [0]" : : "m"(ptr)); be Code: __asm("lidt [%0]" : : "m"(ptr)); instead?Also, what error does Bochs print? Code: __asm("lidt [%0]" : : "m"(ptr)); It doesn't work, while compiling I get this message:C:\Users\Admin\AppData\Local\Temp\ccQPDoTR.s: Assembler messages: C:\Users\Admin\AppData\Local\Temp\ccQPDoTR.s:44: Error: unsupported instruction `lidt' Bochs doesn't show any message, it's just reseting. It's called Triple Fault. By the way, I use Nasm assembly by adding -masm=intel while compilation. |
Author: | frabert [ Mon Jul 30, 2018 8:50 am ] |
Post subject: | Re: Interrupt descriptor table problem |
Add reset_on_triple_fault=0 to your cpu configuration in Bochs to keep it running after a triple fault. Also, run Bochs via a terminal so you can see its output. |
Author: | quirck [ Mon Jul 30, 2018 9:01 am ] |
Post subject: | Re: Interrupt descriptor table problem |
Matt1223 wrote: Code: __asm("lidt [0]" : : "m"(ptr)); It doesn't work, while compiling I get this message:C:\Users\Admin\AppData\Local\Temp\ccQPDoTR.s: Assembler messages: C:\Users\Admin\AppData\Local\Temp\ccQPDoTR.s:44: Error: unsupported instruction `lidt' Hm, it's tricky to get gcc to work with lidt using intel syntax. I can't get rid of "QWORD PTR" in assembly, and lidt QWORD PTR ... is obviously wrong, hence the error. Using AT&T syntax, it's Code: __asm("lidt %0" : : "m"(ptr)); With intel syntax, I managed to get the right output only using a register: Code: __asm("lidt [%0]" : : "r"(&ptr)); Anyway, "lidt [0]" tries to load the idtr from address 0, and ptr is not used at all. |
Author: | Matt1223 [ Mon Jul 30, 2018 9:53 am ] |
Post subject: | Re: Interrupt descriptor table problem |
frabert wrote: Add reset_on_triple_fault=0 to your cpu configuration in Bochs to keep it running after a triple fault. Also, run Bochs via a terminal so you can see its output. I set it and it gives this message: "exception(): 3rd (13) exception with no resolution" There is nothing printed in terminal. |
Author: | Matt1223 [ Mon Jul 30, 2018 9:58 am ] |
Post subject: | Re: Interrupt descriptor table problem |
quirck wrote: Matt1223 wrote: Code: __asm("lidt [0]" : : "m"(ptr)); It doesn't work, while compiling I get this message:C:\Users\Admin\AppData\Local\Temp\ccQPDoTR.s: Assembler messages: C:\Users\Admin\AppData\Local\Temp\ccQPDoTR.s:44: Error: unsupported instruction `lidt' Hm, it's tricky to get gcc to work with lidt using intel syntax. I can't get rid of "QWORD PTR" in assembly, and lidt QWORD PTR ... is obviously wrong, hence the error. Using AT&T syntax, it's Code: __asm("lidt %0" : : "m"(ptr)); With intel syntax, I managed to get the right output only using a register: Code: __asm("lidt [%0]" : : "r"(&ptr)); Anyway, "lidt [0]" tries to load the idtr from address 0, and ptr is not used at all. You're right. I check it in IDA and it was reffering to 0. I changed it to: Code: __asm("lidt [%0]" : : "r"(&ptr)); but it still doesn't work. From what I see in IDA it should. It's really weird!IDA shows that: mov eax, offset unk_402000 lidt fword ptr [eax] |
Author: | quirck [ Mon Jul 30, 2018 10:27 am ] |
Post subject: | Re: Interrupt descriptor table problem |
Matt1223 wrote: frabert wrote: Add reset_on_triple_fault=0 to your cpu configuration in Bochs to keep it running after a triple fault. Also, run Bochs via a terminal so you can see its output. I set it and it gives this message: "exception(): 3rd (13) exception with no resolution" There is nothing printed in terminal. What is in bochs log? If you configured it, of course: Code: log: bochsout.txt One more question: is the code loaded at the address it expects? For example, does this work? Code: asm volatile ( "call %0" : : "r"(interrupt_handler) );
|
Author: | Matt1223 [ Mon Jul 30, 2018 10:48 am ] |
Post subject: | Re: Interrupt descriptor table problem |
quirck wrote: Matt1223 wrote: frabert wrote: Add reset_on_triple_fault=0 to your cpu configuration in Bochs to keep it running after a triple fault. Also, run Bochs via a terminal so you can see its output. I set it and it gives this message: "exception(): 3rd (13) exception with no resolution" There is nothing printed in terminal. What is in bochs log? If you configured it, of course: Code: log: bochsout.txt One more question: is the code loaded at the address it expects? For example, does this work? Code: asm volatile ( "call %0" : : "r"(interrupt_handler) ); It's really huge file so I can't send all of it. Tell me which part should I send. Code: asm volatile ( "call %0" : : "r"(interrupt_handler) ); This code works. |
Author: | quirck [ Mon Jul 30, 2018 10:54 am ] |
Post subject: | Re: Interrupt descriptor table problem |
Well, the lines around "3rd (13) exception with no resolution" There should be the register dump, and usually there is some indication of what went wrong before it. Take a look at this post for example. One more idea: try using pack pragmas around structure definitions like: Code: #pragma pack(push,1) In other words, verify that their sizes are correct. GCC I'm using ignored the __attribute__((packed)) and padded the base field.
struct IDTR { uint16_t limit; uint32_t base; }; #pragma pack(pop) |
Author: | Matt1223 [ Mon Jul 30, 2018 12:06 pm ] |
Post subject: | Re: Interrupt descriptor table problem |
quirck wrote: Well, the lines around "3rd (13) exception with no resolution" There should be the register dump, and usually there is some indication of what went wrong before it. Take a look at this post for example. One more idea: try using pack pragmas around structure definitions like: Code: #pragma pack(push,1) In other words, verify that their sizes are correct. GCC I'm using ignored the __attribute__((packed)) and padded the base field.struct IDTR { uint16_t limit; uint32_t base; }; #pragma pack(pop) Thank you very much! These pragmas worked! Do you have any idea why this attribute was ignored? Anyway can I reward you somehow on this forum? |
Author: | quirck [ Mon Jul 30, 2018 12:16 pm ] |
Post subject: | Re: Interrupt descriptor table problem |
As an alternative to the pragma, -mno-ms-bitfields switch can be used to make __attribute__((packed)) behave as expected. GCC documentation says it is done for windows compatibility. |
Author: | Matt1223 [ Mon Jul 30, 2018 12:20 pm ] |
Post subject: | Re: Interrupt descriptor table problem |
quirck wrote: As an alternative to the pragma, -mno-ms-bitfields switch can be used to make __attribute__((packed)) behave as expected. GCC documentation says it is done for windows compatibility. Ok, thanks a lot! |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |