El contador de marca de tiempo ( TSC ) es un registro de 64 bits presente en todos los procesadores x86 desde el Pentium . Cuenta el número de ciclos de CPU desde su reinicio. La instrucción RDTSC
devuelve el TSC en EDX: EAX. En el modo x86-64 , RDTSC
también borra los 32 bits superiores de RAX y RDX . Su código de operación es 0F 31
. [1] Los competidores Pentium como el Cyrix 6x86 no siempre tenían un TSC y pueden considerar RDTSC
una instrucción ilegal. Cyrix incluyó un contador de marca de tiempo en su MII.
Usar
El contador de marca de tiempo fue una vez una forma excelente de alta resolución y baja sobrecarga para que un programa obtuviera información de tiempo de la CPU. Con la llegada de las CPU de múltiples núcleos / hiperprocesos , los sistemas con varias CPU y los sistemas operativos en hibernación , no se puede confiar en que el TSC proporcione resultados precisos, a menos que se tenga mucho cuidado para corregir los posibles defectos: tasa de tic y si todos los núcleos (procesadores) tienen valores idénticos en sus registros de tiempo. No hay ninguna promesa de que se sincronizarán los contadores de marcas de tiempo de varias CPU en una sola placa base. Por lo tanto, un programa puede obtener resultados confiables solo si se limita a ejecutarse en una CPU específica. Incluso entonces, la velocidad de la CPU puede cambiar debido a las medidas de ahorro de energía tomadas por el sistema operativo o la BIOS , o el sistema puede ser hibernado y luego reanudado, reiniciando el TSC. En estos últimos casos, para seguir siendo relevante, el programa debe recalibrar el contador periódicamente.
Confiar en el TSC también reduce la portabilidad, ya que otros procesadores pueden no tener una característica similar. Los procesadores Intel recientes incluyen un TSC de tasa constante (identificado por el kern.timecounter.invariant_tsc sysctl en FreeBSD o por el constant_tsc
indicador " " en Linux /proc/cpuinfo
). Con estos procesadores, el TSC funciona a la frecuencia nominal del procesador, independientemente de la frecuencia de reloj de la CPU real debido a los estados de ahorro de energía o turbo. Por lo tanto, los ticks de TSC cuentan el paso del tiempo, no el número de ciclos de reloj de la CPU transcurridos.
En las plataformas Windows, Microsoft desaconseja encarecidamente el uso de TSC para tiempos de alta resolución exactamente por estas razones, proporcionando en su lugar las API de Windows QueryPerformanceCounter
y QueryPerformanceFrequency
. [2] En los sistemas POSIX , un programa puede obtener una función similar leyendo el valor del CLOCK_MONOTONIC_RAW
reloj usando la clock_gettime
función. [3]
Comenzando con el Pentium Pro , los procesadores Intel han practicado la ejecución fuera de orden , donde las instrucciones no necesariamente se ejecutan en el orden en que aparecen en el programa. Esto puede hacer que el procesador se ejecute RDTSC
antes de lo que espera un programa simple, produciendo un recuento de ciclos engañoso. [4] El programador puede resolver este problema insertando una instrucción de serialización, como CPUID , para forzar que todas las instrucciones anteriores se completen antes de permitir que el programa continúe. La RDTSCP
instrucción es una variante de la RDTSC
que presenta una serialización parcial del flujo de instrucciones, pero no debe considerarse como serialización.
Implementación en varios procesadores
Las familias de procesadores Intel incrementan el contador de marca de tiempo de manera diferente: [5]
- Para procesadores Pentium M (familia [06H], modelos [09H, 0DH]); para procesadores Pentium 4, procesadores Intel Xeon (familia [0FH], modelos [00H, 01H o 02H]); y para los procesadores de la familia P6: el contador de marca de tiempo aumenta con cada ciclo de reloj del procesador interno. El ciclo de reloj del procesador interno está determinado por la relación actual de reloj de núcleo a reloj de bus. Las transiciones de la tecnología Intel SpeedStep también pueden afectar el reloj del procesador.
- Para procesadores Pentium 4 , procesadores Intel Xeon (familia [0FH], modelos [03H y superiores]); para procesadores Intel Core Solo e Intel Core Duo (familia [06H], modelo [0EH]); para los procesadores Intel Xeon serie 5100 y procesadores Intel Core 2 Duo (familia [06H], modelo [0FH]); para procesadores Intel Core 2 e Intel Xeon (familia [06H], display_model [17H]); para procesadores Intel Atom (familia [06H], display_model [1CH]): el contador de marca de tiempo aumenta a una velocidad constante. Esa velocidad puede establecerse por la relación máxima de reloj de núcleo a reloj de bus del procesador o puede establecerse por la frecuencia máxima resuelta a la que se inicia el procesador. La frecuencia máxima resuelta puede diferir de la frecuencia máxima calificada del procesador.
La configuración específica del procesador determina el comportamiento. El comportamiento constante del TSC asegura que la duración de cada tic del reloj sea uniforme y hace posible el uso del TSC como un temporizador de reloj de pared incluso si el núcleo del procesador cambia de frecuencia. Este es el comportamiento arquitectónico de todos los procesadores Intel posteriores.
Los procesadores AMD hasta el núcleo K8 siempre incrementaron el contador de marca de tiempo en cada ciclo de reloj. [6] Por lo tanto, las funciones de administración de energía pudieron cambiar el número de incrementos por segundo, y los valores podrían desincronizarse entre diferentes núcleos o procesadores en el mismo sistema. Para Windows, AMD proporciona una utilidad [7] para sincronizar periódicamente los contadores en CPU de múltiples núcleos. Desde la familia 10h (Barcelona / Phenom), los chips AMD cuentan con un TSC constante, que puede ser impulsado por la velocidad HyperTransport o por el estado P más alto. Un bit de CPUID ( Fn8000_0007:EDX_8
) anuncia esto; Las CPU Intel también informan su TSC invariante en ese bit.
Uso del sistema operativo
Un sistema operativo puede proporcionar métodos que usan y no usan las RDTSC
instrucciones para mantener el tiempo, bajo el control del administrador. Por ejemplo, en algunas versiones del kernel de Linux , el modo de espacio aislado de seccomp se desactiva RDTSC
. [8] También se puede desactivar usando el PR_SET_TSC
argumento de la prctl()
llamada al sistema. [9]
Uso para explotar ataques de canal lateral de caché
El contador de marca de tiempo se puede utilizar para cronometrar las instrucciones con precisión, lo que se puede aprovechar en las vulnerabilidades de seguridad de Meltdown y Spectre . [10] [11] Sin embargo, si esto no está disponible, se pueden usar otros contadores o temporizadores, como es el caso de los procesadores ARM vulnerables a este tipo de ataque.
Otras arquitecturas
Otros procesadores también tienen registros que cuentan los ciclos de reloj de la CPU, pero con nombres diferentes. Por ejemplo, en el AVR32 , se denomina registro de contador de reloj de rendimiento (PCCNT). SPARC V9 proporciona el TICK
registro. PowerPC proporciona el TBR
registro de 64 bits .
Las arquitecturas ARMv7 [12] y ARMv8 [13] proporcionan un contador genérico que cuenta a una frecuencia constante. ARMv7 proporciona el registro de contador de ciclos ( instrucción CCNT ) para leer y escribir el contador, pero la instrucción tiene privilegios. [14]
Ver también
- Temporizador de eventos de alta precisión (HPET)
Referencias
- ^ Manual del desarrollador de software de arquitecturas Intel 64 e IA-32 Volumen 2B: Referencia del conjunto de instrucciones, MZ (PDF) . pag. 545.
- ^ Procesadores de tiempo de juego y multinúcleo . págs. 251-252.
- ^ "clock_getres, clock_gettime, clock_settime - funciones de reloj y temporizador" .
- ^ "Uso de la instrucción RDTSC para la supervisión del rendimiento" (PDF) .
- ^ "Volumen 3A, Capítulo 16". Manual del desarrollador de software de arquitecturas Intel 64 e IA-32 .
- ^ "Volumen 3". Manual del programador de la arquitectura AMD64 .
- ^ "Optimizador AMD de doble núcleo" .
- ^ "Blog de cr0: contador de sello de tiempo que desactiva rarezas en el kernel de Linux" . Mayo de 2009.
- ^ - Manual del programador de Linux - Llamadas al sistema
- ^ "meltdown.c" .
- ^ "spectre.c" .
- ^ "Manual de referencia de ARMv7" .
- ^ "Manual de referencia de ARMv8" .
- ^ "Registro de contador de ciclos (CCNT)" . ARM Ltd. Consultado el 5 de marzo de 2021 .
enlaces externos
- cycle.h : código C para leer el temporizador de alta resolución en muchas CPU y compiladores.
- [1] - Código C muy simple para leer el temporizador en una máquina x86. Esto lee el valor de 64 bits en dos enteros de 32 bits y los combina; usar solo un entero de 64 bits es otra opción. [ aclaración necesaria ]
- Ingeniero de AMD sobre la deriva de TSC en procesadores AMD