Re: [pok-devel] Re: switch to user space and back during ISR

[ Thread Index | Date Index | More lists.tuxfamily.org/pok-devel Archives ]


Hi,

I implemented the asm code that changes the kernel and user stack,
prepares the segment registers and removes everything not pop'ed by iret
from the stack.
The iret jumps to the right function, but gdb loses the knowledge of the
instruction bounds. GDB recognizes the function name, but si leads to a
constant increase of 0x2 on the PC.

Unfortunately, I am not sure, if I write to the right memory address. I
tested the asm code by writing to the - what I think - right address and
read it back into a register and that leads to the right value. But when
the iret happened and I test the stack, I can't find my written values.

The code can be found here after line 96.
https://github.com/phipse/pok/blob/master/kernel/arch/x86/x86-qemu/bsp.c

The problematic stuff is this:
%1 is the interrupt frame, offset 36 is eax in the frame.
%gs is frame->ds, and %ebx points to frame->esp.

"movl 36(%1), %%eax \t\n"
"movl %%eax, %%gs:-4(%%ebx) \t\n" //move eax to user esp

Any ideas why this is going wrong?

Cheers,
Philipp

On 09/10/2013 04:58 PM, Philipp Eppelt wrote:
> Hi,
> 
> I think have a solution that might work, but it is a dirty hack.
> 
> I jump in after the kernel  handler.
> - Copy interrupt_frame from kernel stack to user stack
> - prepare user stack to look like a normal function call occurred
> (ARG2,ARG1,EIP)
> - Set ds+es to user space values
> - delete everything up to the error code
> - modify the EIP in that was pushed by the interrupt to point to the
> user space handler
> - modify eflags to enable interrupts on iret
> - iret
> - user-space handler works as if it was called normally
> - right before return from the handler, a piece of inline asm code
> recovers the interrupt frame from the stack and restores all missing
> values (not restored by iret) and after cleaning up the stack it places
> the right EIP and EBP on the stack.
> - The following leave,ret of the normal function execution will return
> to the point of interrupt.
> 
> Question:
> What happens if the interrupt occurred while in kernel space and the
> EIP, CS,DS,etc. point into the kernel? --> *kramboom*
> 
> If the irq occurred in the kernel, I could check for that and do a
> syscall passing the interrupt frame along to get to the right point, but
> I think this will lead to dead memory on the user stack. The interrupt
> frame on the user stack isn't cleaned up after the syscall.
> Maybe I can do this from the kernel.
> 
> It feels like I opened the gates of hell just a little bit more.
> 
> Thoughts?
> 
> Cheers
> Philipp
> 
> 
> On 09/09/2013 09:50 PM, Julien Delange wrote:
>> Hi Philipp,
>>
>> The design you suggest seems to make sense, I do not foresee any
>> potential issue. Sounds very specific to one arch but on the other hand,
>> this is more a proof-of-concept rather than a clean implementation ... I
>> would suggest to proceed and try and see what is going on when you start
>> to implement it ...
>>
>>
>> On Mon, Sep 9, 2013 at 9:46 AM, Philipp Eppelt
>> <philipp.eppelt@xxxxxxxxxxxxxxxxxxxxx
>> <mailto:philipp.eppelt@xxxxxxxxxxxxxxxxxxxxx>> wrote:
>>
>>     Hi,
>>
>>     I have two handlers for an ISR which should be invoked during an ISR.
>>     The first handler is the kernel handler which is called fine. Then I
>>     have a handler, which is registered from user space.
>>     To call this handler I first need to switch to the user space
>>     environment. I am doing this by loading the CS,DS,SS and ESP - saved in
>>     the interrupt frame by the interrupt entry. The EIP should point to the
>>     instruction after the following 'iret'.
>>
>>     "pushl %2         \t\n"
>>     "pushl %3         \t\n"
>>     "pushf            \t\n"
>>     "pushl %1         \t\n"
>>     "push $1f         \t\n"
>>     "iret             \t\n"
>>     "1:               \t\n"
>>     (with: 2->ss, 3->esp, 1->cs)
>>
>>     This is a snippet from the inline asm block. The code should now be
>>     executed in user space environment. So the handler should be able to use
>>     and modify variables in the user space environment.
>>
>>     Now I need to switch back to the kernel mode to finish the interrupt
>>     service routine and get back to the point of interruption.
>>
>>     Can someone help me out here?
>>
>>     The control flow is as follows:
>>     - irq 0
>>     - irq prolog 0
>>     - isr handler
>>     -- c isr handler
>>     --- kernel handler for irq 0
>>     -- inline asm code to switch to user space
>>     --- user space handler for irq 0
>>     -- inline asm code to switch to kernel space
>>     - isr handler cont'd.
>>     -- update tss
>>     - isr handler cont'd.
>>     - final iret
>>
>>     By now I doubt that design will work, but I haven't come up with a way
>>     to invoke a user space handler and return to the point of
>>     interruption, yet.
>>
>>     Any thoughts on this?
>>
>>     Cheers,
>>     Philipp
>>
>>
> 
> 
> 




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/