versiones sistema que para operativo llamadas informacion distribuciones clientes assembly linux-kernel x86-64 system-calls abi

assembly - sistema - Diferencia en ABI entre x86_64 funciones de Linux y syscalls



que es linux wikipedia (2)

El syscall de AMD corta el registro de rcx , por lo que se usa r10 su lugar.

La convención de llamada de función x86_64 SysV ABI define el argumento entero # 4 para pasar en el registro rcx . El kernel syscall de Linux ABI, por otro lado, usa r10 para ese mismo propósito. Todos los demás argumentos se pasan en los mismos registros para ambas funciones y llamadas de sistema.

Esto lleva a algunas cosas extrañas. Vea, por ejemplo, la implementación de mmap en glibc para la plataforma x32 (para la cual existe la misma discrepancia):

00432ce0 <__mmap>: 432ce0: 49 89 ca mov %rcx,%r10 432ce3: b8 09 00 00 40 mov $0x40000009,%eax 432ce8: 0f 05 syscall

Entonces, todos los registros ya están en su lugar, excepto que movemos rcx a r10 .

Me pregunto por qué no se define el syscall ABI para que sea el mismo que el llamado a la función ABI, considerando que ya son muy similares.


La instrucción syscall está destinada a proporcionar un método más rápido para ingresar a Ring-0 para llevar a cabo una llamada al sistema. Esto pretende ser una mejora con respecto al método anterior, que consistía en generar una interrupción de software ( int 0x80 en Linux).

Parte de la razón por la cual la instrucción es más rápida es porque no cambia la memoria, o incluso cambia rsp para apuntar a una pila de kernel. A diferencia de una interrupción de software, donde la CPU está obligada a permitir que el sistema operativo reanude su funcionamiento sin dañar nada, para este comando la CPU puede asumir que el software es consciente de que algo está sucediendo aquí.

En particular, syscall almacena dos partes del estado de espacio de usuario en los registros. El RIP al que volver después de la llamada se almacena en rcx , y los indicadores se almacenan en R11 ( porque RFLAGS está enmascarado con un valor proporcionado por el kernel antes de ingresar al kernel ). Esto significa que ambos registros son destruidos por la instrucción.

Dado que son destruidos, el syscall ABI usa otro registro en lugar de rcx , de ahí el uso de r10 para el cuarto argumento.

r10 es una elección natural, ya que en el System86 AB8686 no se usa para pasar argumentos de función, y las funciones no necesitan preservar el valor de llamador de r10 . Entonces, una función de envoltura de syscall puede mov %rcx, %r10 sin guardar / restaurar. Esto no sería posible con ningún otro registro, para syscalls de 6-arg y la convención de llamadas de función de SysV ABI.

Por cierto, la llamada al sistema ABI de 32 bits también se puede acceder con sysenter , que requiere la cooperación entre el espacio de usuario y el kernel-space para permitir el regreso al espacio de usuario después de un sysenter . (es decir, almacenar algún estado en el espacio de usuario antes de ejecutar sysenter ). Este es un rendimiento mayor que int 0x80 , pero incómodo. Aún así, glibc lo usa (saltando al código de espacio de usuario en las páginas de vdso que el kernel mapea en el espacio de direcciones de cada proceso).

La syscall de AMD es otro acercamiento a la misma idea que el sysenter de Intel: hacer que la entrada / salida del núcleo sea menos costosa al no preservar absolutamente todo.