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
>>>
>>>
>>
>>
>>
>
>
>