Code: Select all
check_cs(0x0246): conforming code seg descriptor dpl > cpl, dpl=3, cpl=2
Code: Select all
check_cs(0x0246): conforming code seg descriptor dpl > cpl, dpl=3, cpl=2
First, I'd assume your GDT limit is wrong (allowing uninitialised GDT entries to be used).jrhetf4xb wrote:I've just set up my interrupt/exception handling and as soon as I call sti my interrupt handler gets called by catching int no.8 at first and then int no.13 gets caught repeatedly. Bochs is displaying this in the log, which leaves me wondering if the GDT or the IDT is the problem:
Any ideas what is going on?Code: Select all
check_cs(0x0246): conforming code seg descriptor dpl > cpl, dpl=3, cpl=2
You're right, I forgot about the remapping. I did it now by following Bran's kernel dev tutorial.Are you expecting interrupt 8? If not, you should read the FAQ.
Code: Select all
void isr_handler(struct regs32 *regs)
But my handler just calls my kprintf function to display what interrupt was handled, literally a one-liner.so the problem may be that your interrupt handler has messed up the stack
Code: Select all
/* asm part: */
isr_common_stub:
pushal
call isr_handler
popal
addl $8, %esp
sti
iret
/* C part: */
void
isr_handler(struct regs32 *regs)
{
kprintf("Received interrupt: %d\n", regs->intn);
}
Code: Select all
/* with 2 pushes: */
isr0:
cli
pushl $0
pushl $0
jmp isr_common_stub
/* ... */
/*with 1 push */
isr8:
cli
pushl $8
jmp isr_common_stub
/* ... etc */
Code: Select all
struct regs32
{
uint32_t edi, esi, ebp, esp,
ebx, edx, ecx, eax;
uint32_t intn, errc;
uint32_t eip, cs, eflags, usresp, ss;
};
Code: Select all
pushl %esp
call irq_handler
popl %eax
movl %eax, %esp
It looks like you're interpreting text as an integer. Here's what it says:jrhetf4xb wrote:778855790
Code: Select all
nel.
Code: Select all
pushl %esp
call irq_handler
popl %eax
movl %eax, %esp
Code: Select all
if (bootinfo->flags & MBTINFO_CMDLINE) {
kprintf("Command line: %s\n", (char *) bootinfo->cmdline);
}
Code: Select all
Command line: /boot/kernel.bin cmdline=any kernel parameters
Your isr_handler function takes whatever was pushed on to the stack immediately before it was called as a pointer to a regs32 struct. The last thing pushed to the stack is EDI. What do you think will happen if EDI is a pointer to (a copy of) the kernel command line?jrhetf4xb wrote:Sorry, I shouldn't have left that edit as I'm using the code above it (with just push, call, pop).
Zero points. Pushing esp is correct. The problem there is the fourth line: taking that value off the stack (which is not guaranteed to be the same value you pushed!) and then putting it back into the stack pointer. Either it's the same value as before and nothing at all happens, or the value is different and your stack is now corrupt.jrhetf4xb wrote:But to answer your question it pushes the current stack pointer onto the stack, so my struct in the end would read garbage...
Since it's a pointer, it's going to point to the address of the start of the string, which I assume shouldn't interfere with anything... My regs32.edi would contain this address. But it seems to me that the whole string is pushed onto the stack and not the address itself so when I read regs32.intn I'm just getting a portion of the string?What do you think will happen if EDI is a pointer to (a copy of) the kernel command line?
Code: Select all
void example_a(struct regs32 regs)
void example_b(struct regs32 *regs)
What's the difference between these two function prototypes?
Lol I can't believe what I did I followed Bran's Kernel Development tutorial and this bit was totally misleading as his regs structure is a pointer in the handler.However, I noticed my handler's parameter was wrong as it did not take a pointer, so I fixed it to this:
Thanks for the tip, for now I do a simple regs.eip += 4; and I get away with repetitive interrupt calling.A lot of exception interrupts will immediately be re-thrown after you iret from the interrupt handler.
This is bad. Instructions on x86 are variable length, and are between 1 and 15 bytes (except for very strange and odd circumstances). Chances are you're now getting a totally different exception because you've iret-ed into the middle of an instruction!jrhetf4xb wrote:Thanks for the tip, for now I do a simple egs.eip += 4; and I get away with repetitive interrupt calling.
But are all instructions 4 bytes long?
You can force a general protection fault by a myriad of different ways (such as triggering an interrupt outside the IDT limit or referencing a null descriptor). You can trigger a segment not present fault by loading a selector with its present bit set to 0 into a segment (or a stack segment fault if you load it into SS). There's an instruction called UD2 that is reserved by Intel to be an invalid opcode.jrhetf4xb wrote:Thanks for keeping up with my lame mistakes. Last question, how can I force any of the other interrupts except divide by 0? Or should I assume everything is fine for now?
I'm pushing this too much but is there a straightforward way to know how to jump to the next instruction then (if they are all of variable length)?Kazinsal wrote:This is bad. Instructions on x86 are variable length, and are between 1 and 15 bytes (except for very strange and odd circumstances).