Este es un seguimiento de mi pregunta anterior: regresar de un controlador de señal a través de setcontext
Traté de escribir el ensamblado para hacer el cambio de contexto de un controlador de señal al contexto interrumpido sin la asistencia del kernel (la llamada al sistema sigreturn) para un controlador de señal donde no es necesario cambiar las señales bloqueadas ( SA_NODEFER
).
Parece factible (principalmente solo recargar registros) hasta un punto final: establecer %rsp
y %rip
back. Por lo que entiendo, si no hubiera una zona roja , podría hacer algo como:
//use %rax to old %rsp, and %rcx as a scratch register mov RSP_OFFSET(%rdi), %rax // push old rip, rax, rcx, rdi using the scratch %rcx register mov RIP_OFFSET(%rdi), %rcx mov %rcx, -8(%rax) mov RAX_OFFSET(%rdi), %rcx mov %rcx, -16(%rax) mov RCX_OFFSET(%rdi), %rcx mov %rcx, -24(%rax) mov RDI_OFFSET(%rdi), %rcx mov %rcx, -32(%rax) //make rax point to old_rsp - 32 lea -32(%rax), %rax mov %rax, %rsp //restore rsp to that //restore the pushed registers through actual popping pop %rdi pop %rcx pop %rax //pop and set %rip ret
pero con la zona roja parece imposible ya que no hay (?) ninguna forma de atómicamente (con respecto a las señales) y sin uso de registro sacar una gran cantidad de la pila y saltar a una dirección almacenada en lo profundo de la parte emergente (o en algún lugar completamente diferente como es el caso con las pilas de señales alternativas). Examiné el cambio de tareas de hardware, pero eso no es compatible con el modo protegido de 64 bits.
¿Cómo funcionará esto con las próximas interrupciones a nivel de usuario? ¿Podrán esos controladores regresar de alguna manera sin pasar por el núcleo?