ptrace.c
Configura y gestiona los registros SSE i FXSR de las arquitecturas Intel x86, a partir del P III-. SSE es el acrónimo de
Streaming SIMD Extensions y mejora el rendimiento de la arquitectura Intel en 4 vesantes:
- 8 nuevos registros de punto flotante de tamaño 128bit con direccionamiento directo
- 50 nuevas instrucciones para trabajar con paquetes de datos de punto flotante
- 8 nuevas instrucciones para el control de la cache para los datos MMX
- 12 nuevas instrucciones de extensión de MMX.
signal.c
En este fichero se maneja todo lo referente a las señales qe el sistema puede enviar a los procesos. El parche openMosix debe hacer considerables modificaciones, puesto que en los procesos migrados -procesos divididos en
remote y
deputy- la comunicación también debe ser posible, además de transparente. Igualmente tiene que ser posible hacer llegar a
remote el señal para informarle de su vuelta,
etc.
int copy_siginfo_to_user()
Para que el área de usuario esté informado del estado de los señales, controlado por el área de kernel, se le debe pasar la información sobre el mapa de interrupciones.
En procesos migrados esto es importante, puesto que supone una comunicación entre
remote y
deputy.
int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
{
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
return -EFAULT;
if (from->si_code < 0)
return
copy_to_user(to, from, sizeof(siginfo_t));
else {
#ifdef CONFIG_MOSIX
int sz = offsetof(struct siginfo, _sifields);
switch(from->si_code >> 16)
{
case SI_FAULT >> 16:
sz += sizeof(to->_sifields._sigfault);
break;
case
SI_CHLD >> 16:
sz += sizeof(to->_sifields._sigchld);
break;
case SI_MIGRATION >> 16:
sz += sizeof(to->_sifields._sigmig);
break;
default:
sz += sizeof(to->_sifields._kill);
break;
}
return(
copy_to_user(to, from, sz));
#else
int err;
err = put_user(from->si_signo, &to->si_signo);
err |=
put_user(from->si_errno, &to->si_errno);
err |= put_user((short)from->si_code, &to->si_code);
/* First 32bits of unions are always present. */
err |=
put_user(from->si_pid, &to->si_pid);
switch (from->si_code >> 16) {
case SI_FAULT >> 16:
break;
case
SI_CHLD >> 16:
err |= put_user(from->si_utime, &to->si_utime);
err |=
put_user(from->si_stime, &to->si_stime);
err |= put_user(from->si_status, &to->si_status);
default:
err |=
put_user(from->si_uid, &to->si_uid);
break;
}
return err;
#endif /* CONFIG_MOSIX */
}
}
asmlinkage int sys_sigreturn()
Envía el señal para mandar de regreso el remote.
asmlinkage int sys_sigreturn(unsigned long unused)
{
struct pt_regs *regs = (struct pt_regs *) &
unused;
#ifdef CONFIG_MOSIX
struct sigframe *frame;
#else
struct sigframe *frame = (struct sigframe *)(regs->esp - 8);
#endif /* CONFIG_MOSIX */
sigset_t set;
int eax;
#ifdef CONFIG_MOSIX
mosix_obtain_registers(BIT_OF_REGISTER(esp));
frame = (struct sigframe *)(regs->esp - 8);
#endif /* CONFIG_MOSIX */
La estructura sigframe contiene:
char *pretcode;
int sig;
struct sigcontext sc;
struct _fpstate fpstate;
unsigned long extramask[_NSIG_WORDS-1];
char retcode[8];
if (verify_area(VERIFY_READ, frame, sizeof(*frame))) /* verifica la correcta lectura al remoto */
goto badframe;
if (get_user(set.sig[0], &frame->sc.oldmask)
|| (_NSIG_WORDS > 1
&&
copy_from_user(&set.sig[1], &frame->extramask,
sizeof(frame->extramask))))
/* con una correcta comunicacion, copia desde el remoto al UHN */
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(¤t->sigmask_lock); /* bloquea la seccion critica con semaforos */
current->blocked = set; /* aplica la mascara de los registros al proceso en curso */
/* los registros bloquean el proceso, para recibir el senal */
recalc_sigpending(current); /* desbloquea la proteccion */
spin_unlock_irq(¤t->sigmask_lock);
#ifdef CONFIG_MOSIX
if(current->mosix.dflags & DDEPUTY)
{
if (mosix_deputy_restore_sigcontext(&frame->sc, &eax))
/* restaura el contexto de los registros en el deputy */
goto badframe;
} /* si no se recupera bien el registro eax */
else
#endif /* CONFIG_MOSIX */
if (restore_sigcontext(regs, &frame->sc, &eax))
goto badframe;
return eax;
badframe:
force_sig(SIGSEGV, current);
/* en caso de que no se proceda satisfactoriamente, se envia SIGSEGV para abortar*/
return 0;
}
asmlinkage int handle_signal()
Esta rutina atiende a las señales que recibe un proceso.
static void
handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
#ifdef CONFIG_MOSIX
mosix_obtain_registers(
BIT_OF_REGISTER(orig_eax)|BIT_OF_REGISTER(eax)|BIT_OF_REGISTER(eip));
#endif /* CONFIG_MOSIX */
/* si se esta ejecutando una llamada a sistema, como es una se~nal */
if (regs->orig_eax >= 0) {
/* en este caso se informa al proceso, a traves del registro eax */
switch (regs->eax) {
case -ERESTARTNOHAND:
regs->eax = -EINTR;
break;
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->eax = -EINTR;
break;
}
/* fallthrough */
case -ERESTARTNOINTR:
regs->eax = regs->orig_eax;
regs->eip -= 2;
}
}
/* Set up the stack frame */
#ifdef CONFIG_MOSIX
/* si el proceso no es un proceso Linux completo, sino un deputy, se lo
trata como debe hacerse, mediante una llamada a mosix_deputy_setup_frame().
La mayor diferencia es que el deputy carece de segmento de datos para
almacenar esta informacion*/
if(current->mosix.dflags & DDEPUTY)
mosix_deputy_setup_frame(sig, ka, *info, oldset);
else
#endif /* CONFIG_MOSIX */
if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(sig, ka, info, oldset, regs);
else
setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(¤t->sigmask_lock); /* se bloquea la recepcion de interrupciones para el proceso */
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
sigaddset(¤t->blocked,sig); /* se actualiza el estado de las interrupciones del proceso */
recalc_sigpending(current); /* se atiende a las interrupciones pendientes */
spin_unlock_irq(¤t->sigmask_lock); /* se desbloquea */
}
}
vm86.c
Se gestiona la ejecución de los procesos en emulación vm86. La mayor aportación de código openMosix en esta sección se debe a que aún no se permite la ejecución de tales procesos estando migrados, es un aspecto que debe controlarse.
asmlinkage int save_v86_state()
Guarda el estado del proceso en emulación. Se le indica la opción de bloqueo para que PPM no intente migrarlo.
struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
{
struct tss_struct *tss;
struct pt_regs *ret;
unsigned long tmp;
#ifdef CONFIG_MOSIX
if(current->mosix.dflags & DREMOTE)
panic("remote save_v86");
#endif /* CONFIG_MOSIX */
if (!current->thread.vm86_info) {
printk("no vm86_info: this is BAD\n");
do_exit(SIGSEGV);
}
set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask);
tmp = copy_to_user(¤t->thread.vm86_info->regs,regs, VM86_REGS_SIZE1);
tmp += copy_to_user(¤t->thread.vm86_info->regs.VM86_REGS_PART2,
®s->VM86_REGS_PART2, VM86_REGS_SIZE2);
tmp += put_user(current->thread.screen_bitmap,¤t->thread.vm86_info->screen_bitmap);
if (tmp) {
printk("vm86: could not access userspace vm86_info\n");
do_exit(SIGSEGV);
}
tss = init_tss + smp_processor_id();
#ifdef CONFIG_MOSIX
lock_mosix(); /* ptrace checks saved_esp0 under the mosix-lock */
#endif /* CONFIG_MOSIX */
tss->esp0 = current->thread.esp0 = current->thread.saved_esp0;
current->thread.saved_esp0 = 0;
ret = KVM86->regs32;
#ifdef CONFIG_MOSIX
unlock_mosix();
task_lock(current);
current->mosix.stay &= ~DSTAY_FOR_86; /* se marca la opcion de bloqueo del proceso */
task_unlock(current);
#endif /* CONFIG_MOSIX */
return ret;
}
asmlinkage int sys_vm86old()
En caso de tratarse de un proceso en emulación y de haberse iniciado la migración antes de percatarse de tal condición, se manda el señal para volver el proceso al UHN indicando la razón DSTAY_FOR_86.
asmlinkage int sys_vm86old(struct vm86_struct * v86)
{
struct kernel_vm86_struct info;
struct task_struct *tsk;
int tmp, ret = -EPERM;
#ifdef CONFIG_MOSIX
if(!mosix_go_home_for_reason(1, DSTAY_FOR_86))
{
ret = -ENOMEM;
goto out;
}
#endif /* CONFIG_MOSIX */
tsk = current;
if (tsk->thread.saved_esp0)
goto out;
tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
(long)&info.vm86plus - (long)&info.regs.VM86_REGS_PART2);
ret = -EFAULT;
if (tmp)
goto out;
memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus);
info.regs32 = (struct pt_regs *) &v86;
tsk->thread.vm86_info = v86;
do_sys_vm86(&info, tsk);
ret = 0; /* we never return here */
out:
return ret;
}
asmlinkage int sys_ioperm()