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.
KrotovOSdev wrote:
Even gdb doesn't work with my kernel. When I add -g option for GCC and NASM and use GCC remote debugger with qemu, it says that there is no symbol table so I can't set breakpoints...
You need to load the symbol table from your kernel image.
You need to send the EOI before you switch tasks, but I don't see any problems that would cause #GP. Why do you think the problem is in this part of your code? What is the CPU state when the exception occurs? (QEMU with "-d int" will log the CPU state.)
Octocontrabass wrote:You need to send the EOI before you switch tasks, but I don't see any problems that would cause #GP. Why do you think the problem is in this part of your code? What is the CPU state when the exception occurs? (QEMU with "-d int" will log the CPU state.)
I send EOI after the if statement because I don't switch tasks on every INT0.
Not the timer ISR throws GPF but the Page Fault handler. The "iret" instruction at the end of ISR throws PF. I think it tries to return to the wrong address but I don't know why it happens after the second timer interrupt.
KrotovOSdev wrote:I send EOI after the if statement because I don't switch tasks on every INT0.
You know, you can just send the EOI before the if statement. It doesn't change anything in the CPU, only in the PIC. Also, and this is getting into advanced territory here, you can program the PIT to interrupt you when you actually want to do something. Rather than counting interrupts, just get the interrupt when you need it. Unless you are bumping up against the frequency limit of the PIT, but the lowest the PIT can go is ca. 18Hz, and if you were dividing this by 10, you'd get to 1.8Hz, which would feel real sluggish.
KrotovOSdev wrote:The "iret" instruction at the end of ISR throws PF.
Weird. The code looks alright. Try logging ESP on entry and exit.
KrotovOSdev wrote:I send EOI after the if statement because I don't switch tasks on every INT0.
You still need to send the EOI before you switch tasks. The new task will not send an EOI, so you will not receive any more timer interrupts.
KrotovOSdev wrote:Not the timer ISR throws GPF but the Page Fault handler. The "iret" instruction at the end of ISR throws PF. I think it tries to return to the wrong address but I don't know why it happens after the second timer interrupt.
What is the #PF error code? What address is in CR2? What are the contents of the stack?
KrotovOSdev wrote:Now I send EOI before if statement. The #PF error code is 0, CR2 value is 0x2badb0f7 which is a bit strange. Looks like something wrong with esp.
So error code 0 means the page fault was caused by a memory read in kernel mode. If you are not using the NX feature, the memory read could also be an instruction fetch. The CR2 address looks suspiciously close to the multiboot magic value of 0x2badb002, which is in EAX when the bootloader passes control to your kernel. Is it possible that you only ever overwrote AL in your kernel, and your ESP at the IRET instruction ends up pointing to the EAX value rather than EIP?
Again, I would print ESP on entry and exit of the handler.
The #PF happens without switching tasks. I want to switch tasks every 50 ms (every 5 timer interrupts). Is this a good practice to switch tasks not every single timer interrupt. The #PF happens after the second timer interrupt.
The ESP is 0x44FC when the #PF happens which is okay in my OS. The previous interrupt's (timer interrupt) ESP is 0x44F8. Looks like I miss some important thing:)
nullplan wrote:[So error code 0 means the page fault was caused by a memory read in kernel mode. If you are not using the NX feature, the memory read could also be an instruction fetch. The CR2 address looks suspiciously close to the multiboot magic value of 0x2badb002, which is in EAX when the bootloader passes control to your kernel. Is it possible that you only ever overwrote AL in your kernel, and your ESP at the IRET instruction ends up pointing to the EAX value rather than EIP?
Again, I would print ESP on entry and exit of the handler.
I was thinking about it. Maybe I use the stack wrong.
The next strange thing is that if I add while(1) at the end of the kmain() function, timer interrupts work fine. But I still can't switch tasks.
Maybe I know the way how to fix that.
nullplan wrote:[So error code 0 means the page fault was caused by a memory read in kernel mode. If you are not using the NX feature, the memory read could also be an instruction fetch. The CR2 address looks suspiciously close to the multiboot magic value of 0x2badb002, which is in EAX when the bootloader passes control to your kernel. Is it possible that you only ever overwrote AL in your kernel, and your ESP at the IRET instruction ends up pointing to the EAX value rather than EIP?
Again, I would print ESP on entry and exit of the handler.
I was thinking about it. Maybe I use the stack wrong.
The next strange thing is that if I add while(1) at the end of the kmain() function, timer interrupts work fine. But I still can't switch tasks.
Maybe I know the way how to fix that.
I would perhaps suggest starting small, create multiple tasks, and switch between them purely cooperatively, without involving timer interrupts. You need to make sure your task switching is solid before trying to add any pre-emption.
In fact, start with interrupts disabled, and handle only faults such as GPF and page faults, which you can explicitly control.
Once you're confident your exception handling code is working correctly, then you can install interrupt handlers. Perhaps start with keyboard handler, so you can control when the interrupts happen as well as providing some input.
thewrongchristian wrote:
Once you're confident your exception handling code is working correctly, then you can install interrupt handlers. Perhaps start with keyboard handler, so you can control when the interrupts happen as well as providing some input.
My keyboard handler works fine. Hm
Octocontrabass wrote:
That's a very unusual place to put your stack.
It sounds like the problem is in the code that calls kmain().
I put stack to 0x4500 during the init process, when paging is not enabled. Should I put it to another address?
If kmain() function returns, my code just execute "cli; hlt".