Hi,all:

I just modified the kernel thread function in UML 2.6.7 tt mode. I want the 
kernel thread go to the user space after finished the kernel function rather 
than exit. It's just like a system call return or a return from fork...

But now the problem is that there will be segmentation fault just before the 
kernel thread go to the user space. After tracing I found when the segmentation 
fault occur, in handle_page_fault function, (!(vma->vm_flags & VM_GROWSDOWN)) 
is true and the err is -14. What's the meaning of such value?

I modified the new_thread_handler function with regarding to 
finish_fork_handler function. (also add pt_regs as a parameter of the kernel 
thread function)
My modified new_thread_handler function is following:
-------------------------------------------------------
static void new_thread_handler(int sig)
{
        unsigned long disable;
        int (*fn)(void *);
        void *arg;
        struct pt_regs *regs;
                                                                                
                                             
        fn = current->thread.request.u.thread.proc;
        arg = current->thread.request.u.thread.arg;
                                                                                
                                             
        regs = &current->thread.regs;
                                                                                
                                             
        UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
        disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
                (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
        SC_SIGMASK(UPT_SC(&current->thread.regs.regs)) &= ~disable;             
                                                                                
                                
                                                                       
        suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
                                                                                
                                             
        force_flush_all();
        if(current->thread.prev_sched != NULL)
                schedule_tail(current->thread.prev_sched);
        current->thread.prev_sched = NULL;
                                                                                
                                             
        init_new_thread_signals(1);
        enable_timer();
                                                                                
                                             
        change_sig(SIGVTALRM, 1);
        local_irq_enable();
        if(current->mm != current->parent->mm)
                protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
                               1, 0, 1);
        task_protections((unsigned long) current_thread);
                                                                                
                                             
                                                                                
                                             
        free_page(current->thread.temp_stack);
        set_cmdline("(bproc kernel thread)");
                                                                                
                                             
        change_sig(SIGUSR1, 1);
        change_sig(SIGPROF, 1);
                                                                                
                                             
        if(!run_kernel_thread(fn, regs, arg, &current->thread.exec_buf)){
                local_irq_disable();
                change_sig(SIGUSR1, 0);
                set_user_mode(current);
        }
                                                                                
                                             
        /* XXX No set_user_mode here because a newly execed process will
         * immediately segfault on its non-existent IP, coming straight back
         * to the signal handler, which will call set_user_mode on its way
         * out.  This should probably change since it's confusing.
         */
}
----------------------------------------------
For convenience,I also attached the original UML functions:

void finish_fork_handler(int sig)
{
        UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
        suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
                                                                                
                                             
        force_flush_all();
        if(current->thread.prev_sched != NULL)
                schedule_tail(current->thread.prev_sched);
        current->thread.prev_sched = NULL;
                                                                                
                                             
        enable_timer();
        change_sig(SIGVTALRM, 1);
        local_irq_enable();
        if(current->mm != current->parent->mm)
                protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
                               1, 0, 1);
        task_protections((unsigned long) current_thread);
                                                                                
                                             
        free_page(current->thread.temp_stack);
        local_irq_disable();
        change_sig(SIGUSR1, 0);
        set_user_mode(current);
}

static void new_thread_handler(int sig)
{
        unsigned long disable;
        int (*fn)(void *);
        void *arg;
                                                                                
                                             
        fn = current->thread.request.u.thread.proc;
        arg = current->thread.request.u.thread.arg;
                                                                                
                                             
        UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
        disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
                (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
        SC_SIGMASK(UPT_SC(&current->thread.regs.regs)) &= ~disable;
                                                                                
                                             
        suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
                                                                                
                                             
        force_flush_all();
        if(current->thread.prev_sched != NULL)
                schedule_tail(current->thread.prev_sched);
        current->thread.prev_sched = NULL;
                                                                                
                                             
        init_new_thread_signals(1);
        enable_timer();
        free_page(current->thread.temp_stack);
        set_cmdline("(kernel thread)");
                                                                                
                                             
        change_sig(SIGUSR1, 1);
        change_sig(SIGVTALRM, 1);
        change_sig(SIGPROF, 1);
        local_irq_enable();
        if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
                do_exit(0);
                                                                                
                                             
        /* XXX No set_user_mode here because a newly execed process will
         * immediately segfault on its non-existent IP, coming straight back
         * to the signal handler, which will call set_user_mode on its way
         * out.  This should probably change since it's confusing.
         */
}
------------------------------------------------
I also modified the copy_thread_tt function and create the sigcontext for the 
kernel thread just like fork:
------------------------------------------------
         sc_to_sc(UPT_SC(&p->thread.regs.regs),
                UPT_SC(&current->thread.regs.regs));
         SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
         if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
------------------------------------------------

Any ideas? 
Thanks a lot!

Alex



-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_idt77&alloc_id492&op=click
_______________________________________________
User-mode-linux-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

Reply via email to