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 = ¤t->thread.regs;
UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
(1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
SC_SIGMASK(UPT_SC(¤t->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, ¤t->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(¤t->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(¤t->thread.regs.regs) = (void *) (&sig + 1);
disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
(1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
SC_SIGMASK(UPT_SC(¤t->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, ¤t->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(¤t->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