Interfaz hypercall
El hipervisor proporciona un mecanismo de llamada para invitados. Estas llamadas se conocen como hiperllamadas. Cada hiperllamada define un conjunto de parámetros de entrada o salida. Estos parámetros se especifican en términos de una estructura de datos basada en memoria. Todos los elementos de las estructuras de datos de entrada y salida se rellenan en límites naturales de hasta 8 bytes (es decir, los elementos de dos bytes deben estar en límites de dos bytes, etc.).
Opcionalmente, se puede usar una segunda convención de llamada de hiperllamada para un subconjunto de hiperllamadas, en particular, aquellas que tienen dos o menos parámetros de entrada y sin parámetros de salida. Al usar esta convención de llamada, los parámetros de entrada se pasan en registros de uso general.
Opcionalmente, se puede usar una tercera convención de llamada de hiperllamada para un subconjunto de hiperllamadas donde el bloque de parámetros de entrada es de hasta 112 bytes. Al usar esta convención de llamada, los parámetros de entrada se pasan en registros, incluidos los registros XMM volátiles.
Las estructuras de datos de entrada y salida deben colocarse en memoria en un límite de 8 bytes y rellenarse en un múltiplo de 8 bytes de tamaño. El hipervisor omite los valores de las regiones de relleno.
En el caso de la salida, el hipervisor puede sobrescribir (pero no se garantiza que) sobrescriba las regiones de relleno. Si sobrescribe regiones de relleno, escribirá ceros.
Clases de Hypercall
Hay dos clases de hiperllamadas: simple y rep (abreviar para "repetir"). Una hiperllamada simple realiza una sola operación y tiene un conjunto de tamaño fijo de parámetros de entrada y salida. Una hiperllamada de repetición actúa como una serie de hiperllamadas simples. Además de un conjunto de parámetros de entrada y salida de tamaño fijo, las hiperllamadas de repetición implican una lista de elementos de entrada o salida de tamaño fijo.
Cuando un llamador invoca inicialmente una hiperllamada de repetición, especifica un recuento de repeticiones que indica el número de elementos de la lista de parámetros de entrada o salida. Los autores de llamadas también especifican un índice de inicio de rep que indica el siguiente elemento de entrada o salida que se debe consumir. El hipervisor procesa parámetros rep en orden de lista, es decir, aumentando el índice de elementos.
En el caso de las invocaciones posteriores de la hiperllamada rep, el índice de inicio de la repetición indica cuántos elementos se han completado y, junto con el valor de recuento de repeticiones, cuántos elementos quedan. Por ejemplo, si un autor de la llamada especifica un recuento de repeticiones de 25 y solo se completan 20 iteraciones dentro de las restricciones de tiempo, la hiperllamada devuelve el control al procesador virtual que realiza la llamada después de actualizar el índice de inicio del rep a 20. Cuando se vuelve a ejecutar la hiperllamada, el hipervisor se reanudará en el elemento 20 y completará los cinco elementos restantes.
Si se produce un error al procesar un elemento, se proporciona un código de estado adecuado junto con un recuento completado de reps, que indica el número de elementos que se procesaron correctamente antes de que se encontrara el error. Suponiendo que la palabra de control de hiperllamada especificada es válida (vea lo siguiente) y se puede acceder a las listas de parámetros de entrada y salida, se garantiza que el hipervisor intente al menos un rep, pero no es necesario procesar toda la lista antes de devolver el control al autor de la llamada.
Continuación de Hypercall
Una hiperllamada se puede considerar como una instrucción compleja que toma muchos ciclos. El hipervisor intenta limitar la ejecución de hiperllamadas a 50μs o menos antes de devolver el control al procesador virtual que invocó la hiperllamada. Algunas operaciones de hiperllamada son suficientemente complejas que una garantía de 50μs es difícil de hacer. Por lo tanto, el hipervisor se basa en un mecanismo de continuación de hiperllamada para algunas hiperllamadas, incluidos todos los formularios de hiperllamadas de repetición.
El mecanismo de continuación de hiperllamada es principalmente transparente para el autor de la llamada. Si una hiperllamada no puede completarse dentro del límite de tiempo prescrito, el control se devuelve al autor de la llamada, pero el puntero de instrucción no está avanzado más allá de la instrucción que invocó la hiperllamada. Esto permite controlar las interrupciones pendientes y se programan otros procesadores virtuales. Cuando el subproceso de llamada original reanude la ejecución, volverá a ejecutar la instrucción de hiperllamada y avanzará hacia la finalización de la operación.
Se garantiza que la mayoría de las hiperllamadas simples se completen dentro del límite de tiempo prescrito. Sin embargo, un pequeño número de hiperllamadas simples podría requerir más tiempo. Estas hiperllamadas usan la continuación de hiperllamadas de forma similar a las hiperllamadas. En tales casos, la operación implica dos o más estados internos. La primera invocación coloca el objeto (por ejemplo, la partición o el procesador virtual) en un estado y, después de las invocaciones repetidas, el estado finalmente pasa a un estado terminal. Para cada hiperllamada que sigue este patrón, se describen los efectos secundarios visibles de los estados internos intermedios.
Atomicidad y ordenación de hiperllamada
Excepto cuando se indique, la acción realizada por una hiperllamada es atómica con respecto a todas las demás operaciones invitadas (por ejemplo, instrucciones ejecutadas dentro de un invitado) y todas las demás hiperllamadas que se ejecutan en el sistema. Una hiperllamada simple realiza una única acción atómica; Una hiperllamada de repetición realiza varias acciones atómicas independientes.
Las hiperllamadas simples que usan la continuación de hiperllamadas pueden implicar varios estados internos que son visibles externamente. Estas llamadas comprenden varias operaciones atómicas.
Cada acción de hiperllamada puede leer parámetros de entrada o resultados de escritura. Las entradas de cada acción se pueden leer en cualquier granularidad y en cualquier momento después de que se realice la hiperllamada y antes de que se ejecute la acción. Los resultados (es decir, los parámetros de salida) asociados a cada acción se pueden escribir en cualquier granularidad y en cualquier momento después de ejecutar la acción y antes de que se devuelva la hiperllamada.
El invitado debe evitar el examen o manipulación de los parámetros de entrada o salida relacionados con una hiperllamada en ejecución. Aunque un procesador virtual que ejecuta una hiperllamada no podrá hacerlo (ya que su ejecución de invitado se suspende hasta que se devuelve la hiperllamada), no hay nada para evitar que otros procesadores virtuales lo hagan. Los invitados se comportan de esta manera pueden bloquearse o causar daños dentro de su partición.
Entornos de Hypercall legales
Las hiperllamadas solo se pueden invocar desde el modo de procesador invitado con más privilegios. En x64 platfoms, esto significa modo protegido con un nivel de privilegio actual (CPL) de cero. Aunque el código en modo real se ejecuta con una CPL eficaz de cero, no se permiten hiperllamadas en modo real. Un intento de invocar una hiperllamada dentro de un modo de procesador no válido generará una excepción de #UD (operación no definida).
Todas las hiperllamadas deben invocarse a través de la interfaz de hiperllamada definida por la arquitectura (consulte a continuación). Un intento de invocar una hiperllamada por cualquier otro medio (por ejemplo, copiar el código de la página de códigos de hiperllamada a una ubicación alternativa y ejecutarla desde allí) podría dar lugar a una excepción de operación no definida (#UD). No se garantiza que el hipervisor entregue esta excepción.
Requisitos de alineación
Los autores de llamadas deben especificar la dirección física de invitado (GPA) de 64 bits de los parámetros de entrada o salida. Los punteros de GPA deben estar alineados con 8 bytes. Si la hiperllamada no implica parámetros de entrada o salida, el hipervisor omite el puntero GPA correspondiente.
Las listas de parámetros de entrada y salida no se pueden superponer ni cruzar los límites de la página. Se espera que las páginas de entrada y salida de hiperllamadas sean páginas GPA y no páginas de "superposición". Si el procesador virtual escribe los parámetros de entrada en una página de superposición y especifica un GPA dentro de esta página, el acceso del hipervisor a la lista de parámetros de entrada no está definido.
El hipervisor validará que la partición que llama puede leer desde la página de entrada antes de ejecutar la hiperllamada solicitada. Esta validación consta de dos comprobaciones: el GPA especificado se asigna y el GPA se marca como legible. Si se produce un error en cualquiera de estas pruebas, el hipervisor genera un mensaje de interceptación de memoria. En el caso de las hiperllamadas que tienen parámetros de salida, el hipervisor validará que la partición se puede escribir en la página de salida. Esta validación consta de dos comprobaciones: el GPA especificado se asigna y el GPA se marca como grabable.
Entradas de hiperllamada
Los autores de llamadas especifican una hiperllamada por un valor de 64 bits denominado valor de entrada de hiperllamada. Tiene el formato siguiente:
Campo | Bits | Información proporcionada |
---|---|---|
Código de llamada | 15-0 | Especifica qué hiperllamada se solicita. |
Fast | 16 | Especifica si la hiperllamada usa la convención de llamada basada en registros: 0 = basada en memoria, 1 = basada en registros. |
Tamaño del encabezado variable | 26-17 | Tamaño de un encabezado de variable, en QWORDS. |
RsvdZ | 30-27 | Debe ser cero |
Está anidado | 31 | Especifica que el hiperllamada debe controlarse mediante el hipervisor L0 en un entorno anidado. |
Recuento de repeticiones | 43-32 | Número total de representantes (en el caso de la llamada de repetición, debe ser cero en caso contrario) |
RsvdZ | 47-44 | Debe ser cero |
Índice de inicio de rep | 59-48 | Índice inicial (para la llamada de rep, debe ser cero de lo contrario) |
RsvdZ | 63-60 | Debe ser cero |
En el caso de las hiperllamadas de repetición, el campo recuento de representantes indica el número total de representantes. El índice de inicio del representante indica la repetición determinada en relación con el inicio de la lista (cero indica que se va a procesar el primer elemento de la lista). Por lo tanto, el valor de recuento de representantes siempre debe ser mayor que el índice de inicio de la rep.
Registre la asignación de entradas de hiperllamadas cuando la marca Fast sea cero:
x64 | x86 | Información proporcionada |
---|---|---|
RCX | EDX:EAX | Valor de entrada de Hypercall |
RDX | EBX:ECX | GPA de parámetros de entrada |
R8 | EDI:ESI | GPA de parámetros de salida |
El valor de entrada de hypercall se pasa en los registros junto con un GPA que apunta a los parámetros de entrada y salida.
En x64, las asignaciones de registro dependen de si el autor de la llamada se ejecuta en modo de 32 bits (x86) o de 64 bits (x64). El hipervisor determina el modo del autor de la llamada en función del valor de EFER. LMA y CS.L. Si se establecen ambas marcas, se supone que el autor de la llamada es un llamador de 64 bits.
Registre la asignación de entradas de hiperllamada cuando la marca Fast sea una:
x64 | x86 | Información proporcionada |
---|---|---|
RCX | EDX:EAX | Valor de entrada de Hypercall |
RDX | EBX:ECX | Parámetro de entrada |
R8 | EDI:ESI | Parámetro de salida |
El valor de entrada de hiperllamada se pasa en los registros junto con los parámetros de entrada.
Encabezados de entrada de hiperllamada de tamaño variable
La mayoría de los encabezados de entrada de hiperllamada tienen un tamaño fijo. Por lo tanto, la cantidad de datos de encabezado que se pasan del invitado al hipervisor se especifica implícitamente mediante el código de hiperllamada y no se debe especificar por separado. Sin embargo, algunas hiperllamadas requieren una cantidad variable de datos de encabezado. Normalmente, estas hiperllamadas tienen un encabezado de entrada de tamaño fijo y una entrada de encabezado adicional que es de tamaño variable.
Un encabezado de tamaño variable es similar a una entrada de hiperllamada fija (alineada a 8 bytes y tamaño a un múltiplo de 8 bytes). El autor de la llamada debe especificar la cantidad de datos que proporciona como encabezados de entrada. Este tamaño se proporciona como parte del valor de entrada de hypercall (consulte "Tamaño de encabezado variable" en la tabla anterior).
Dado que el tamaño fijo del encabezado es implícito, en lugar de proporcionar el tamaño total del encabezado, solo se proporciona la parte variable en los controles de entrada:
Variable Header Bytes = {Total Header Bytes - sizeof(Fixed Header)} rounded up to nearest multiple of 8
Variable HeaderSize = Variable Header Bytes / 8
No es válido especificar un tamaño de encabezado de variable distinto de cero para una hiperllamada que no se documenta explícitamente como encabezados de entrada de tamaño variable aceptados. En tal caso, la hiperllamada dará como resultado un código de retorno de HV_STATUS_INVALID_HYPERCALL_INPUT
.
Es posible que para una invocación determinada de una hiperllamada que acepte encabezados de entrada de tamaño variable que todas las entradas de encabezado se ajusten completamente dentro del encabezado de tamaño fijo. En tales casos, el encabezado de entrada de tamaño variable tiene un tamaño cero y los bits correspondientes de la entrada de hiperllamada deben establecerse en cero.
En todos los demás aspectos, las hiperllamadas que aceptan encabezados de entrada de tamaño variable son similares a las hiperllamadas de encabezado de entrada de tamaño fijo con respecto a las convenciones de llamada. También es posible que una hiperllamada de encabezado de tamaño variable admita además la semántica de repetición. En tal caso, los elementos rep se encuentran después del encabezado de la manera habitual, excepto que el tamaño total del encabezado incluye las partes fijas y variables. Todas las demás reglas siguen siendo las mismas, por ejemplo, el primer elemento rep debe estar alineado con 8 bytes.
Entrada de hiperllamada rápida de XMM
En las plataformas x64, el hipervisor admite el uso de hiperllamadas rápidas de XMM, lo que permite que algunas hiperllamadas aprovechen el rendimiento mejorado de la interfaz de hiperllamada rápida aunque requieran más de dos parámetros de entrada. La interfaz de hiperllamada rápida XMM usa seis registros XMM para permitir que el autor de la llamada pase un bloque de parámetros de entrada de hasta 112 bytes de tamaño.
La disponibilidad de la interfaz de hiperllamada rápida XMM se indica a través de la hoja CPUID (0x40000003) "Identificación de la característica de hipervisor":
- Bit 4: la compatibilidad para pasar la entrada de hiperllamada a través de registros XMM está disponible.
Tenga en cuenta que hay una marca independiente para indicar la compatibilidad con la salida rápida XMM. Cualquier intento de usar esta interfaz cuando el hipervisor no indica la disponibilidad producirá un error de #UD.
Asignación de registros (solo entrada)
x64 | x86 | Información proporcionada |
---|---|---|
RCX | EDX:EAX | Valor de entrada de Hypercall |
RDX | EBX:ECX | Bloque de parámetros de entrada |
R8 | EDI:ESI | Bloque de parámetros de entrada |
XMM0 | XMM0 | Bloque de parámetros de entrada |
XMM1 | XMM1 | Bloque de parámetros de entrada |
XMM2 | XMM2 | Bloque de parámetros de entrada |
XMM3 | XMM3 | Bloque de parámetros de entrada |
XMM4 | XMM4 | Bloque de parámetros de entrada |
XMM5 | XMM5 | Bloque de parámetros de entrada |
El valor de entrada de hiperllamada se pasa en los registros junto con los parámetros de entrada. Las asignaciones de registro dependen de si el autor de la llamada se ejecuta en modo de 32 bits (x86) o de 64 bits (x64). El hipervisor determina el modo del autor de la llamada en función del valor de EFER. LMA y CS.L. Si se establecen ambas marcas, se supone que el autor de la llamada es un llamador de 64 bits. Si el bloque de parámetros de entrada es inferior a 112 bytes, se omiten los bytes adicionales de los registros.
Salidas de hypercall
Todas las hiperllamadas devuelven un valor de 64 bits denominado valor de resultado de hypercall. Tiene el formato siguiente:
Campo | Bits | Comentario |
---|---|---|
Resultado | 15-0 | HV_STATUS código que indica éxito o error |
Rsvd | 31-16 | Los autores de llamadas deben omitir el valor de estos bits. |
Representantes completados | 43-32 | Número de representantes completados correctamente |
RsvdZ | 63-40 | Los autores de llamadas deben omitir el valor de estos bits. |
En el caso de las hiperllamadas de repetición, el campo reps complete es el número total de representantes completados y no en relación con el índice de inicio de la rep. Por ejemplo, si el autor de la llamada especificó un índice de inicio de rep de 5 y un recuento de representantes de 10, el campo reps complete indicaría 10 al finalizar correctamente.
El valor de resultado de hypercall se devuelve en los registros. La asignación de registros depende de si el autor de la llamada se ejecuta en modo de 32 bits (x86) o de 64 bits (x64) (consulte más arriba). La asignación de registros para las salidas de hiperllamadas es la siguiente:
x64 | x86 | Información proporcionada |
---|---|---|
RAX | EDX:EAX | Valor de resultado de Hypercall |
Salida rápida de Hypercall de XMM
De forma similar a cómo el hipervisor admite entradas de hiperllamada rápidas de XMM, se pueden compartir los mismos registros para devolver la salida. Esto solo se admite en plataformas x64.
La capacidad de devolver la salida a través de registros XMM se indica a través de la hoja cpuID (0x40000003):
- Bit 15: la compatibilidad con la devolución de la salida de hiperllamada a través de registros XMM está disponible.
Tenga en cuenta que hay una marca independiente para indicar la compatibilidad con la entrada rápida XMM. Cualquier intento de usar esta interfaz cuando el hipervisor no indica la disponibilidad producirá un error de #UD.
Asignación de registros (entrada y salida)
Los registros que no se usan para pasar parámetros de entrada se pueden usar para devolver la salida. En otras palabras, si el bloque de parámetros de entrada es inferior a 112 bytes (redondeado al fragmento alineado de 16 bytes más cercano), los registros restantes devolverán la salida de hiperllamada.
x64 | Información proporcionada |
---|---|
RDX | Bloque de entrada o salida |
R8 | Bloque de entrada o salida |
XMM0 | Bloque de entrada o salida |
XMM1 | Bloque de entrada o salida |
XMM2 | Bloque de entrada o salida |
XMM3 | Bloque de entrada o salida |
XMM4 | Bloque de entrada o salida |
XMM5 | Bloque de entrada o salida |
Por ejemplo, si el bloque de parámetros de entrada tiene un tamaño de 20 bytes, el hipervisor omitiría los 12 bytes siguientes. Los 80 bytes restantes contendrán la salida de hiperllamada (si procede).
Registros volátiles
Las hiperllamadas solo modificarán los valores de registro especificados en las condiciones siguientes:
- RAX (x64) y EDX:EAX (x86) siempre se sobrescriben con el valor de resultado de hiperllamada y los parámetros de salida, si los hay.
- Las hiperllamadas de rep modificarán RCX (x64) y EDX:EAX (x86) con el nuevo índice de inicio de rep.
- HvCallSetVpRegisters puede modificar los registros compatibles con esa hiperllamada.
- RDX, R8 y XMM0 a XMM5, cuando se usa para la entrada rápida de hiperllamada, permanecen sin modificar. Sin embargo, los registros usados para la salida rápida de hiperllamada se pueden modificar, incluidos RDX, R8 y XMM0 a XMM5. Hyper-V solo modificará estos registros para una salida rápida de hypercall, que está limitada a x64.
Restricciones de hiperllamadas
Las hiperllamadas pueden tener restricciones asociadas a ellas para que realicen su función prevista. Si no se cumplen todas las restricciones, la hiperllamada finalizará con un error adecuado. Se mostrarán las siguientes restricciones, si se aplica alguna:
- La partición que llama debe poseer un privilegio determinado.
- La partición en la que se actúa debe estar en un estado determinado (por ejemplo, "Activo")
Códigos de estado de hypercall
Cada hiperllamada se documenta como devolver un valor de salida que contiene varios campos. Se usa un campo de valor de estado (de tipo HV_STATUS
) para indicar si la llamada se realizó correctamente o no.
Validez del parámetro de salida en hiperllamadas con error
A menos que se indique explícitamente lo contrario, cuando se produce un error en una hiperllamada (es decir, el campo de resultado de la hiperllamada contiene un valor HV_STATUS_SUCCESS
distinto de ), el contenido de todos los parámetros de salida es indeterminado y el autor de la llamada no debe examinarlo. Solo cuando la hiperllamada se realice correctamente, todos los parámetros de salida adecuados contendrán resultados válidos y esperados.
Ordenación de condiciones de error
El orden en el que el hipervisor detecta y notifica las condiciones de error no está definido. En otras palabras, si existen varios errores, el hipervisor debe elegir qué condición de error se va a notificar. Se debe dar prioridad a esos códigos de error que ofrecen mayor seguridad, la intención es evitar que el hipervisor revele información a los autores de llamadas que carecen de privilegios suficientes. Por ejemplo, el código HV_STATUS_ACCESS_DENIED
de estado es el código de estado preferido sobre uno que revelaría cierta información de contexto o estado basada exclusivamente en privilegios.
Códigos comunes de estado de hypercall
Varios códigos de resultado son comunes a todas las hiperllamadas y, por lo tanto, no se documentan para cada hiperllamada individualmente. Entre ellas, figuran:
status code | Condición de error |
---|---|
HV_STATUS_SUCCESS |
La llamada se realizó correctamente. |
HV_STATUS_INVALID_HYPERCALL_CODE |
No se reconoce el código de hiperllamada. |
HV_STATUS_INVALID_HYPERCALL_INPUT |
El recuento de representantes es incorrecto (por ejemplo, se pasa un recuento de rep distinto de cero a una llamada que no es de repetición o se pasa un recuento de representantes cero a una llamada de rep). |
El índice de inicio de la rep no es menor que el recuento de representantes. | |
Un bit reservado en el valor de entrada de hiperllamada especificado es distinto de cero. | |
HV_STATUS_INVALID_ALIGNMENT |
El puntero GPA de entrada o salida especificado no está alineado a 8 bytes. |
Las listas de parámetros de entrada o salida especificadas abarcan páginas. | |
El puntero GPA de entrada o salida no está dentro de los límites del espacio GPA. |
El código HV_STATUS_SUCCESS
de retorno indica que no se detectó ninguna condición de error.
Notificación de la identidad del sistema operativo invitado
El sistema operativo invitado que se ejecuta dentro de la partición debe identificarse en el hipervisor escribiendo su firma y versión en un MSR (HV_X64_MSR_GUEST_OS_ID
) antes de poder invocar hiperllamadas. Este MSR es de toda la partición y se comparte entre todos los procesadores virtuales.
El valor de este registro es inicialmente cero. Se debe escribir un valor distinto de cero en el MSR de id. de so invitado antes de que se pueda habilitar la página de códigos de hiperllamada (consulte Establecimiento de la interfaz de Hypercall). Si este registro se convierte posteriormente en ceros, se deshabilitará la página de códigos de hypercall.
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
Identidad del sistema operativo invitado para sistemas operativos propietarios
A continuación se muestra la codificación recomendada para este MSR. Es posible que algunos campos no se apliquen a algunos sistemas operativos invitados.
Bits | Campo | Descripción |
---|---|---|
15:0 | Número de compilación | Indica el número de compilación del sistema operativo. |
23:16 | Versión del servicio | Indica la versión del servicio (por ejemplo, el número "Service Pack") |
31:24 | Minor Version | Indica la versión secundaria del sistema operativo. |
39:32 | Major Version | Indica la versión principal del sistema operativo. |
47:40 | Identificador del sistema operativo | Indica la variante del sistema operativo. La codificación es única para el proveedor. Los sistemas operativos de Microsoft se codifican de la siguiente manera: 0=Undefined, 1=MS-DOS®, 2=Windows ® 3.x, 3=Windows ® 9x, 4=Windows ® NT (y derivados), 5=Windows ® CE |
62:48 | Id. del proveedor | Indica el proveedor del sistema operativo invitado. Se reserva un valor de 0. Consulte la lista de proveedores a continuación. |
63 | Tipo de SO | Indica los tipos de sistema operativo. Un valor de 0 indica un sistema operativo de origen cerrado propietario. Un valor de 1 indica un sistema operativo código abierto. |
Microsoft asigna los valores de proveedor. Para solicitar un nuevo proveedor, envíe un problema en el repositorio de documentación de virtualización de GitHub (https://aka.ms/VirtualizationDocumentationIssuesTLFS).
Vendor | Valor |
---|---|
Microsoft | 0x0001 |
HPE | 0x0002 |
LANCOM | 0x0200 |
Identidad del sistema operativo invitado MSR para sistemas operativos de código abierto
La siguiente codificación se ofrece como guía para código abierto proveedores de sistemas operativos que cumplan esta especificación. Se recomienda que código abierto sistemas operativos adapten la convención siguiente.
Bits | Campo | Descripción |
---|---|---|
15:0 | Número de compilación | Información adicional |
47:16 | Versión | Información de la versión del kernel ascendente. |
55:48 | Identificador del sistema operativo | Información adicional del proveedor |
62:56 | Tipo de SO | Tipo de sistema operativo (por ejemplo, Linux, FreeBSD, etc.). Consulte la lista de tipos de sistema operativo conocidos a continuación. |
63 | Código abierto | Un valor de 1 indica un sistema operativo código abierto. |
Microsoft asigna los valores de tipo de sistema operativo. Para solicitar un nuevo tipo de sistema operativo, envíe un problema en el repositorio de documentación de virtualización de GitHub (https://aka.ms/VirtualizationDocumentationIssuesTLFS).
Tipo de SO | Valor |
---|---|
Linux | 0x1 |
FreeBSD | 0x2 |
Xen | 0x3 |
Illumos | 0x4 |
Establecimiento de la interfaz hypercall
Las hiperllamadas se invocan mediante un código de operación especial. Dado que este código de operación difiere entre las implementaciones de virtualización, es necesario que el hipervisor abstraa esta diferencia. Esto se hace a través de una página de hiperllamada especial. El hipervisor proporciona esta página y aparece dentro del espacio GPA del invitado. El invitado es necesario para especificar la ubicación de la página mediante la programación de MSR de hypercall invitado.
#define HV_X64_MSR_HYPERCALL 0x40000001
Bits | Descripción | Atributos |
---|---|---|
63:12 | GPFN de hypercall: indica el número de página física invitada de la página de hiperllamada. | Lectura/escritura |
11:2 | RsvdP. Los bits deben omitirse en lecturas y conservarse en escrituras. | Reservado |
1 | Bloqueado. Indica si MSR es inmutable. Si se establece, este MSR se bloquea, lo que impide la reubicación de la página de hiperllamada. Una vez establecido, solo un restablecimiento del sistema puede borrar el bit. | Lectura/escritura |
0 | Habilitar la página de hiperllamada | Lectura/escritura |
La página de hiperllamada se puede colocar en cualquier parte del espacio GPA del invitado, pero debe estar alineada con páginas. Si el invitado intenta mover la página de hiperllamada más allá de los límites del espacio GPA, se producirá un error de #GP cuando se escriba msr.
Este MSR es un MSR de toda la partición. En otras palabras, es compartido por todos los procesadores virtuales de la partición. Si un procesador virtual escribe correctamente en MSR, otro procesador virtual leerá el mismo valor.
Antes de habilitar la página de hiperllamada, el sistema operativo invitado debe notificar su identidad escribiendo su firma de versión en un MSR independiente (HV_X64_MSR_GUEST_OS_ID). Si no se ha especificado ninguna identidad del sistema operativo invitado, se producirá un error en los intentos de habilitar la hiperllamada. El bit de habilitación seguirá siendo cero incluso si se escribe uno en él. Además, si la identidad del sistema operativo invitado se borra a cero después de habilitar la página de hiperllamada, se deshabilitará.
La página de hiperllamada aparece como una "superposición" al espacio GPA; es decir, cubre cualquier otra cosa que se asigne al intervalo de GPA. El invitado puede leer y ejecutable su contenido. Los intentos de escritura en la página de hiperllamada producirán una excepción de protección (#GP). Una vez habilitada la página de hiperllamada, invocar una hiperllamada simplemente implica una llamada al inicio de la página.
A continuación se muestra una lista detallada de los pasos necesarios para establecer la página de hiperllamada:
- El invitado lee la hoja 1 de CPUID y determina si un hipervisor está presente comprobando el bit 31 del registro ECX.
- El invitado lee la hoja CPUID 0x40000000 para determinar la hoja de CPUID máxima del hipervisor (devuelta en el registro EAX) y la hoja CPUID 0x40000001 para determinar la firma de interfaz (devuelta en el registro EAX). Comprueba que el valor de hoja máximo es al menos 0x40000005 y que la firma de interfaz es igual a "Hv#1". Esta firma implica que
HV_X64_MSR_GUEST_OS_ID
HV_X64_MSR_HYPERCALL
, yHV_X64_MSR_VP_INDEX
se implementan. - El invitado escribe su identidad del sistema operativo en MSR
HV_X64_MSR_GUEST_OS_ID
si ese registro es cero. - El invitado lee msr de llamada de Hypercall (
HV_X64_MSR_HYPERCALL
). - El invitado comprueba el bit Habilitar página de Hypercall. Si se establece, la interfaz ya está activa y se deben omitir los pasos 6 y 7.
- El invitado encuentra una página dentro de su espacio de GPA, preferiblemente una que no está ocupada por RAM, MMIO, etc. Si la página está ocupada, el invitado debe evitar el uso de la página subyacente para otros fines.
- El invitado escribe un nuevo valor en el MSR de Hypercall (
HV_X64_MSR_HYPERCALL
) que incluye el GPA del paso 6 y establece el bit Habilitar página de Hypercall para habilitar la interfaz. - El invitado crea una asignación de VA ejecutable a la GPA de la página de hiperllamada.
- El invitado consulta el 0x40000003 hoja CPUID para determinar qué instalaciones de hipervisor están disponibles para él. Una vez establecida la interfaz, el invitado puede iniciar una hiperllamada. Para ello, rellena los registros según el protocolo de hiperllamada y emite una LLAMADA al principio de la página de hiperllamada. El invitado debe asumir que la página de hiperllamada realiza el equivalente de una devolución cercana (0xC3) para volver al autor de la llamada. Por lo tanto, la hiperllamada debe invocarse con una pila válida.
Interfaz de Hiperllamada extendida
Las hiperllamadas con códigos de llamada anteriores 0x8000 se conocen como hiperllamadas extendidas. Las hiperllamadas extendidas usan la misma convención de llamada que las hiperllamadas normales y aparecen idénticas desde la perspectiva de una máquina virtual invitada. Las hiperllamadas extendidas se controlan internamente de forma diferente dentro del hipervisor de Hyper-V.
Las funcionalidades de hiperllamada extendidas se pueden consultar con HvExtCallQueryCapabilities.