Page 1 of 1

Interrupts are handled incorrectly while the user space work

Posted: Tue Sep 08, 2020 7:33 am
by mrjbom
Hi.
My scheduler successfully passes control to the user program on Ring 3, but when this function is running in user mode, I get an interrupt from PIT, but there are problems in the handler.
For example, the interrupt number is determined incorrectly, just like other information related to the interrupt.

And now I'll tell you more:
The scheduler calls the scheduler_low_thread_switch() function, which stores data from the interrupted current task in current_thread and starts either a new task(next_thread), this function also determines whether the task is a user mode task.

In my case, it successfully runs a custom task in Ring 3 and it works fine(i go to ring 3 using this function), but there is a 32 interrupt from PIT.
In this case, the handler for the interrupt is called, it successfully calls isr_handler(), but the interrupt number is too large, and all other registers fields are invalid.
In addition, the handler tries to print the number of the unprocessed interrupt, but some problem occurs during its processing and because the handler is not completed correctly, the interrupts remain disabled and the system freezes.

Just in case, I recorded it on video, maybe it will be a little clearer there.
At the end of the video, you can see that this interruption is from PIT.
There are 4 of them after setting up multitasking, each time the task is switched.
0(kernel)->1(kernel)
1(kernel)->2(kernel)
2(kernel)->3(user mode)
3(user mode)->0(kernel) <-this is what is being processed incorrectly(int_num invalid)

What could be the problem?

Re: Interrupts are handled incorrectly while the user space

Posted: Tue Sep 08, 2020 9:23 am
by nullplan

Code: Select all

void isr_handler(registers_t regs)
Well there's your problem, lady! You pass the registers by value instead of passing a pointer to them. I don't precisely know how the ABI for passing a large structure by value works, but apparently not like this. So change this to

Code: Select all

void isr_handler(registers_t *regs)
And then change the calling code to

Code: Select all

pushl %esp
call isr_handler
addl $4, %esp
Your code should probably also save ES, FS, and GS. Also, you can push and pop segment registers directly, you don't need to go through a GPR first.

Re: Interrupts are handled incorrectly while the user space

Posted: Tue Sep 08, 2020 9:36 am
by mrjbom
nullplan wrote:

Code: Select all

void isr_handler(registers_t regs)
Well there's your problem, lady! You pass the registers by value instead of passing a pointer to them. I don't precisely know how the ABI for passing a large structure by value works, but apparently not like this. So change this to

Code: Select all

void isr_handler(registers_t *regs)
And then change the calling code to

Code: Select all

pushl %esp
call isr_handler
addl $4, %esp
Your code should probably also save ES, FS, and GS. Also, you can push and pop segment registers directly, you don't need to go through a GPR first.
I changed the code accordingly, but it doesn't solve the problem.
regs now points to an address that is too large(outside of available memory).
In addition, I don't understand why serial_printf() fails, probably for the same reason why I get the wrong address.

In addition, I found a strange behavior with esp, it is also too large.
ESP in isr_common handler
Image

It is not clear why this problem only occurs when an interrupt is triggered in ring 3.

UPD: I noticed that I had a problem in the user_mode_switch function, it did not set the stack to the user task, I fixed this error, but the ESP in the handler still has a strange value.
I believe that for some reason the handler stack is not configured correctly during the call(this is probably why there are problems in serial_printf()).
In all cases of exception handling(until the user program is running), the ESP in the isr_common handler has the correct value. only when an exception occurs when the user code is running, the ESP is corrupted.

Re: Interrupts are handled incorrectly while the user space

Posted: Tue Sep 08, 2020 11:40 am
by nullplan
Well that would indicate that ESP0 in your TSS is screwed up. Also, if ESP is outside available memory, how did you even get that far? Shouldn't there have been a page fault on the way? Unless you are not using paging, in which case ESP is pointing into some I/O memory. Meaning you just lost your stack, and isr_handler() will be unable to return. That would also explain the funky values you got earlier. Now for the big question: How is your ESP0 screwed up?

Re: Interrupts are handled incorrectly while the user space

Posted: Tue Sep 08, 2020 12:24 pm
by mrjbom
nullplan wrote:Also, if ESP is outside available memory, how did you even get that far? Shouldn't there have been a page fault on the way?
I disabled paging so that it doesn't interfere with debugging.
nullplan wrote:How is your ESP0 screwed up?
I'm also very interested in how this could happen.
Here is my code that configures TSS and I don't see any problems in configuring TSS.
write_tss() loads the normal value in esp0. the value of the stack variable is also ok.
I don't know why ESP0 is recorded incorrectly.

Re: Interrupts are handled incorrectly while the user space

Posted: Wed Sep 09, 2020 10:26 am
by mrjbom
The problem is solved. My task switcher incorrectly set tss.esp0.
Thanks for the hint, I guessed that I had some problems with tss, but I didn't think that the esp0 installed there affects the operation of interrupts.