[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: IDT/Exception handling understanding - kernel vs userspace control path
On Wed, Jul 2, 2008 at 12:45 AM, Peter Teoh <htmldeveloper@xxxxxxxxx> wrote:
> On Mon, Jun 30, 2008 at 7:55 PM, Mulyadi Santosa
> <mulyadi.santosa@xxxxxxxxx> wrote:
>> Hi!
>>
>> On Sat, Jun 28, 2008 at 4:02 PM, Peter Teoh <htmldeveloper@xxxxxxxxx> wrote:
>>> Looked the last few lines of this:
>>>
>>> http://lkml.org/lkml/2003/7/10/74
>>>
>>>
>>> I am trying to trying to understand the control path of IDT in userspace vs
>>> kernelspace:
>>>
>>> 1. The patch mentioned NMI can returned back to userspace.....is that
>>> correct?
>>
>> yes...think like this, interrupt can come anytime...whether you're in
>> user mode or kernel mode. So logically, after you're being
>> interrupted, you come back to the place you were interrupted, right?
>>
>>> How and where in the kernel is this return to userspace
>>> controlled/directed?
>>
>> IIRC, entry.S...but i forgot in which directory the file resides.
>>
>> Check the file...i am sure you get the idea... the label like
>> "ret_from_fork" (kinda OOT, just to give you idea) will ease you to
>> make conclusion..
>>
>
> Yes, your memory is superb, Mulyadi - in arch/x86/kernel/entry_32.S:
>
> ENTRY(ret_from_fork)
> CFI_STARTPROC
> pushl %eax
> CFI_ADJUST_CFA_OFFSET 4
> call schedule_tail
> GET_THREAD_INFO(%ebp)
> popl %eax
> CFI_ADJUST_CFA_OFFSET -4
> pushl $0x0202 # Reset kernel eflags
> CFI_ADJUST_CFA_OFFSET 4
> popfl
> CFI_ADJUST_CFA_OFFSET -4
> jmp syscall_exit
> CFI_ENDPROC
> END(ret_from_fork)
>
> /*
> * Return to user mode is not as complex as all this looks,
> * but we want the default path for a system call return to
> * go as quickly as possible which is why some of this is
> * less clear than it otherwise should be.
> */
>
> # userspace resumption stub bypassing syscall exit tracing
> ALIGN
> RING0_PTREGS_FRAME
> ret_from_exception:
> preempt_stop(CLBR_ANY)
> ret_from_intr:
> GET_THREAD_INFO(%ebp)
> check_userspace:
> movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
> movb PT_CS(%esp), %al
> andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
> cmpl $USER_RPL, %eax
> jb resume_kernel # not returning to v8086 or userspace
>
> ENTRY(resume_userspace)
> LOCKDEP_SYS_EXIT
> DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
> # setting need_resched or sigpending
> # between sampling and the iret
> TRACE_IRQS_OFF
> movl TI_flags(%ebp), %ecx
> andl $_TIF_WORK_MASK, %ecx # is there any work to be done on
> # int/exception return?
> jne work_pending
>
>
>>
>>> 2. When in userspace, the IDT table - which have the return address of the
>>> functions in the kernel...cannot be used. So how is the control path of
>>> "int 3" looked like when processes execute it? Userspace will have
>>> exception handling etc....but I think all these processing comes after the
>>> kernel handle the exception right? And these userspace exception are
>>> therefore controlled by kernel - where is it?
>>
>> you were talking about ptrace-ing, right? it's the parent (the one
>> that issued ptrace command) that will check the ptraced process's
>> stack frame and target process' PID.
>>
>> Specifically, in the context of ptrace, it's not just the instruction
>> that's replaced by INT 3, but kernel also deliver SIGCHLD (if I
>> remember correctly) to the ptracing process. That way, the tracing
>> process know the ptraced process has hit the INT 3....
>>
>
> Let me check out your statement. But my question was actually this:
>
> Insert the following into your code:
>
> __asm {int 3} and execute it as a userspace program.
>
> What happened? How does the OS handle the exception in the userspace
> program, or generally, any exception that it encountered (eg, div by
> zero)? In kernel these will trigger the hardware IDT into action.
> But how about userspace - it ought to right? But it cannot see the
> IDT's address right (since these are kernel address)....so how it
> flow?
>
Part of answer is here --> which is kill_pgrp() - the following is for
handling ctrl-C receive from user scenario:
http://lkml.org/lkml/2008/7/1/250
> diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
> index 8096389..74018ef 100644
> --- a/drivers/char/n_tty.c
> +++ b/drivers/char/n_tty.c
> @@ -759,20 +759,9 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
> signal = SIGTSTP;
> if (c == SUSP_CHAR(tty)) {
> send_signal:
> - /*
> - * Echo character, and then send the signal.
> - * Note that we do not use isig() here because we want
> - * the order to be:
> - * 1) flush, 2) echo, 3) signal
> - */
> - if (!L_NOFLSH(tty)) {
> - n_tty_flush_buffer(tty);
> - tty_driver_flush_buffer(tty);
> - }
> if (L_ECHO(tty))
> echo_char(c, tty);
> - if (tty->pgrp)
> - kill_pgrp(tty->pgrp, signal, 1);
> + isig(signal, tty, 0);
> return;
> }
> }
so effectively, the propagation of the interrupt processing is via
kill_pgrp(). Correct? Which somehow...should flow back to
userspace program's exception handler --> correct? (as decided and
controlled by glibc)
>
> Thanks again.
>
>> I hope I clear your doubts.
>>
>> regards,
>>
>> Mulyadi.
>>
>
>
>
> --
> Regards,
> Peter Teoh
>
--
Regards,
Peter Teoh
--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ