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

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


Hi,

what works:
- Jump to user space, execution of RTEMS - at least it looks like it.
But it can't find the registered clock interrupt handler.

what doesn't:
- I don't know where my asm code is writing the interrupt frame, vector
number, eip. It is not in the user's stack according to gdb. But I doubt
gdb is showing the right values. It seems it can't handle segmentation.
When I write some inline asm code in the user's handler and move the
parameters to eax and ebx at least ebx looks familiar. GDB tells me they
are both 0.

Maybe I can recover the environment blindly (without gdb) from the stack
and return to the right address.

Cheers,
Philipp



On 09/12/2013 04:40 PM, Philipp Eppelt wrote:
> 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/