Android proporciona una implementación de referencia de todos los componentes necesarios para implementar el marco de virtualización de Android. Actualmente esta implementación está limitada a ARM64. Esta página explica la arquitectura del framework.
Fondo
La arquitectura Arm permite hasta cuatro niveles de excepción, siendo el nivel de excepción 0 (EL0) el menos privilegiado y el nivel de excepción 3 (EL3) el más privilegiado. La mayor parte del código base de Android (todos los componentes del espacio de usuario) se ejecuta en EL0. El resto de lo que comúnmente se llama "Android" es el kernel de Linux, que se ejecuta en EL1.
La capa EL2 permite la introducción de un hipervisor que permite aislar la memoria y los dispositivos en pVM individuales en EL1/EL0, con fuertes garantías de confidencialidad e integridad.
hipervisor
La máquina virtual protegida basada en kernel (pKVM) se basa en el hipervisor Linux KVM , que se ha ampliado con la capacidad de restringir el acceso a las cargas útiles que se ejecutan en máquinas virtuales invitadas marcadas como "protegidas" en el momento de la creación.
KVM/arm64 admite diferentes modos de ejecución según la disponibilidad de ciertas características de la CPU, a saber, Virtualization Host Extensions (VHE) (ARMv8.1 y posterior). En uno de esos modos, comúnmente conocido como modo no VHE, el código del hipervisor se separa de la imagen del kernel durante el arranque y se instala en EL2, mientras que el kernel mismo se ejecuta en EL1. Aunque forma parte del código base de Linux, el componente EL2 de KVM es un pequeño componente a cargo del cambio entre múltiples EL1 y está completamente controlado por el kernel del host. El componente de hipervisor se compila con Linux, pero reside en una sección de memoria dedicada separada de la imagen de vmlinux
. pKVM aprovecha este diseño al extender el código del hipervisor con nuevas funciones que le permiten imponer restricciones en el kernel del host de Android y el espacio del usuario, y limita el acceso del host a la memoria del invitado y al hipervisor.
Procedimiento de arranque
El procedimiento de arranque de pKVM se muestra en la figura 1. El primer paso es que el cargador de arranque ingrese un kernel de Linux habilitado para pKVM en EL2. Durante el inicio temprano, el kernel detecta que se está ejecutando en EL2, se priva de privilegios a EL1 y deja atrás a pKVM. A partir de este momento, el kernel de Linux procede a arrancar normalmente, cargando todos los controladores de dispositivos necesarios, hasta llegar al espacio de usuario. Estos pasos suceden bajo el control de pKVM.
El procedimiento de arranque confía en que el gestor de arranque mantendrá la integridad de la imagen del kernel solo durante el arranque inicial. Cuando el kernel está privado de privilegios, el hipervisor ya no considera que confíe en él, que luego es responsable de protegerse incluso si el kernel está comprometido.
Tener el kernel de Android y el hipervisor en la misma imagen binaria permite una interfaz de comunicación muy estrechamente acoplada entre ellos. Este estrecho acoplamiento garantiza actualizaciones atómicas de los dos componentes, lo que evita la necesidad de mantener estable la interfaz entre ellos y ofrece una gran flexibilidad sin comprometer la capacidad de mantenimiento a largo plazo. El estrecho acoplamiento también permite optimizaciones de rendimiento cuando ambos componentes pueden cooperar sin afectar las garantías de seguridad proporcionadas por el hipervisor.
Además, la adopción de GKI en el ecosistema de Android permite automáticamente que el hipervisor pKVM se implemente en dispositivos Android en el mismo binario que el kernel.
Protección de acceso a la memoria de la CPU
La arquitectura Arm especifica una unidad de administración de memoria (MMU) dividida en dos etapas independientes, las cuales se pueden usar para implementar la traducción de direcciones y el control de acceso a diferentes partes de la memoria. La MMU de etapa 1 está controlada por EL1 y permite un primer nivel de traducción de direcciones. Linux utiliza la MMU de etapa 1 para administrar el espacio de direcciones virtuales proporcionado a cada proceso de espacio de usuario y a su propio espacio de direcciones virtuales.
La MMU de la etapa 2 está controlada por EL2 y permite la aplicación de una segunda traducción de dirección en la dirección de salida de la MMU de la etapa 1, lo que da como resultado una dirección física (PA). Los hipervisores pueden utilizar la traducción de la etapa 2 para controlar y traducir los accesos a la memoria desde todas las máquinas virtuales invitadas. Como se muestra en la figura 2, cuando ambas etapas de traducción están habilitadas, la dirección de salida de la etapa 1 se denomina dirección física intermedia (IPA). Nota: la dirección virtual (VA) se traduce a IPA y luego a PA.
Históricamente, KVM se ejecuta con la traducción de la etapa 2 habilitada mientras se ejecutan invitados y con la etapa 2 deshabilitada mientras se ejecuta el kernel de Linux host. Esta arquitectura permite que los accesos a la memoria desde la MMU de la etapa 1 del host pasen a través de la MMU de la etapa 2, lo que permite el acceso sin restricciones desde el host a las páginas de memoria del invitado. Por otro lado, pKVM permite la protección de etapa 2 incluso en el contexto del host y pone al hipervisor a cargo de proteger las páginas de memoria del invitado en lugar del host.
KVM hace un uso completo de la traducción de direcciones en la etapa 2 para implementar asignaciones complejas de IPA/PA para los invitados, lo que crea la ilusión de una memoria contigua para los invitados a pesar de la fragmentación física. Sin embargo, el uso de la MMU de etapa 2 para el host está restringido solo al control de acceso. La etapa 2 del host tiene un mapa de identidad, lo que garantiza que la memoria contigua en el espacio IPA del host sea contigua en el espacio PA. Esta arquitectura permite el uso de grandes asignaciones en la tabla de páginas y, en consecuencia, reduce la presión sobre el búfer de búsqueda de traducción (TLB). Debido a que PA puede indexar un mapeo de identidad, la etapa de host 2 también se usa para rastrear la propiedad de la página directamente en la tabla de páginas.
Protección de acceso directo a memoria (DMA)
Como se describió anteriormente, quitar la asignación de páginas de invitados del host Linux en las tablas de páginas de la CPU es un paso necesario pero insuficiente para proteger la memoria de invitados. pKVM también debe protegerse contra los accesos a la memoria realizados por dispositivos con capacidad DMA bajo el control del kernel del host y la posibilidad de un ataque DMA iniciado por un host malicioso. Para evitar que dicho dispositivo acceda a la memoria de invitado, pKVM requiere hardware de unidad de administración de memoria de entrada y salida (IOMMU) para cada dispositivo compatible con DMA en el sistema, como se muestra en la figura 3.
Como mínimo, el hardware de IOMMU proporciona los medios para otorgar y revocar el acceso de lectura/escritura de un dispositivo a la memoria física en la granularidad de la página. Sin embargo, este hardware IOMMU limita el uso de dispositivos en pVM, ya que asumen una etapa 2 con asignación de identidad.
Para garantizar el aislamiento entre máquinas virtuales, las transacciones de memoria generadas en nombre de diferentes entidades deben ser distinguibles por IOMMU para que se pueda utilizar el conjunto adecuado de tablas de páginas para la traducción.
Además, reducir la cantidad de código específico de SoC en EL2 es una estrategia clave para reducir la base informática confiable (TCB) general de pKVM y va en contra de la inclusión de controladores IOMMU en el hipervisor. Para mitigar este problema, el host en EL1 es responsable de las tareas auxiliares de administración de IOMMU, como la administración de energía, la inicialización y, cuando corresponda, el manejo de interrupciones.
Sin embargo, poner al host en control del estado del dispositivo impone requisitos adicionales en la interfaz de programación del hardware IOMMU para garantizar que las comprobaciones de permisos no se puedan omitir por otros medios, por ejemplo, después de reiniciar el dispositivo.
Una IOMMU estándar y bien compatible para dispositivos Arm que hace posible tanto el aislamiento como la asignación directa es la arquitectura de la Unidad de administración de memoria del sistema Arm (SMMU). Esta arquitectura es la solución de referencia recomendada.
Propiedad de la memoria
En el momento del arranque, se supone que toda la memoria que no es del hipervisor es propiedad del host y el hipervisor la rastrea como tal. Cuando se genera una pVM, el host dona páginas de memoria para permitir que se inicie y el hipervisor transfiere la propiedad de esas páginas del host a la pVM. Por lo tanto, el hipervisor establece restricciones de control de acceso en la tabla de páginas de la etapa 2 del host para evitar que acceda a las páginas nuevamente, brindando confidencialidad al invitado.
La comunicación entre el anfitrión y los invitados es posible gracias al intercambio controlado de memoria entre ellos. Los invitados pueden compartir algunas de sus páginas con el host mediante una hiperllamada, que indica al hipervisor que reasigne esas páginas en la tabla de páginas de la etapa 2 del host. Del mismo modo, la comunicación del host con TrustZone es posible gracias a las operaciones de préstamo y/o uso compartido de la memoria, todas las cuales son monitoreadas y controladas de cerca por pKVM utilizando la especificación Firmware Framework for Arm (FF-A) .
El hipervisor es responsable de rastrear la propiedad de todas las páginas de memoria en el sistema y si se comparten o se prestan a otras entidades. La mayor parte de este seguimiento de estado se realiza utilizando metadatos adjuntos a las tablas de páginas de la etapa 2 del host y los invitados, utilizando bits reservados en las entradas de la tabla de páginas (PTE) que, como su nombre sugiere, están reservados para uso de software.
El host debe asegurarse de que no intenta acceder a páginas que el hipervisor ha hecho inaccesibles. Un acceso ilegal al host hace que el hipervisor inyecte una excepción síncrona en el host, lo que puede provocar que la tarea del espacio de usuario responsable reciba una señal SEGV o que el kernel del host se bloquee. Para evitar accesos accidentales, las páginas donadas a los invitados no son elegibles para el intercambio o la fusión por parte del kernel del host.
Manejo de interrupciones y temporizadores
Las interrupciones son una parte esencial de la forma en que un invitado interactúa con los dispositivos y para la comunicación entre las CPU, donde las interrupciones entre procesadores (IPI) son el principal mecanismo de comunicación. El modelo KVM consiste en delegar toda la gestión de interrupciones virtuales al host en EL1, que para ese propósito se comporta como una parte no confiable del hipervisor.
pKVM ofrece una emulación completa de Generic Interrupt Controller versión 3 (GICv3) basada en el código KVM existente. El temporizador y los IPI se manejan como parte de este código de emulación que no es de confianza.
Compatibilidad con GICv3
La interfaz entre EL1 y EL2 debe garantizar que el host EL1 pueda ver el estado de interrupción completo, incluidas las copias de los registros del hipervisor relacionados con las interrupciones. Esta visibilidad generalmente se logra mediante regiones de memoria compartida, una por CPU virtual (vCPU).
El código de soporte de tiempo de ejecución del registro del sistema se puede simplificar para admitir solo el registro de interrupción generado por software (SGIR) y la captura de registros de registro de interrupción desactivado (DIR). La arquitectura exige que estos registros siempre atrapen a EL2, mientras que las otras trampas hasta ahora solo han sido útiles para mitigar las erratas. Todo lo demás se maneja en hardware.
Del lado de MMIO, todo se emula en EL1, reutilizando toda la infraestructura actual en KVM. Finalmente, Wait for Interrupt (WFI) siempre se transmite a EL1, porque esta es una de las primitivas de programación básicas que utiliza KVM.
Soporte de temporizador
El valor del comparador para el temporizador virtual debe exponerse a EL1 en cada WFI de captura para que EL1 pueda inyectar interrupciones del temporizador mientras la vCPU está bloqueada. El temporizador físico se emula por completo y todas las trampas se transmiten a EL1.
manejo de MMIO
Para comunicarse con el monitor de máquina virtual (VMM) y realizar la emulación de GIC, las trampas MMIO deben retransmitirse al host en EL1 para una evaluación adicional. pKVM requiere lo siguiente:
- IPA y tamaño del acceso
- Datos en caso de escritura
- Endianness de la CPU en el punto de captura
Además, las trampas con un registro de propósito general (GPR) como fuente/destino se retransmiten utilizando un pseudo-registro de transferencia abstracta.
Interfaces de invitado
Un invitado puede comunicarse con un invitado protegido mediante una combinación de hiperllamadas y acceso a la memoria en regiones atrapadas. Las hiperllamadas se exponen de acuerdo con el estándar SMCCC , con un rango reservado para la asignación de un proveedor por KVM. Las siguientes hiperllamadas son de particular importancia para los invitados pKVM.
Hiperllamadas genéricas
- PSCI proporciona un mecanismo estándar para que el huésped controle el ciclo de vida de sus vCPU, lo que incluye la conexión, la desconexión y el apagado del sistema.
- TRNG proporciona un mecanismo estándar para que el huésped solicite entropía del pKVM que transmite la llamada a EL3. Este mecanismo es particularmente útil cuando no se puede confiar en el host para virtualizar un generador de números aleatorios (RNG) de hardware.
hiperllamadas pKVM
- Compartir memoria con el anfitrión. Toda la memoria de invitado es inicialmente inaccesible para el host, pero el acceso del host es necesario para la comunicación de memoria compartida y para dispositivos paravirtualizados que dependen de búferes compartidos. Las hiperllamadas para compartir y dejar de compartir páginas con el anfitrión le permiten al invitado decidir exactamente qué partes de la memoria se hacen accesibles para el resto de Android sin necesidad de un apretón de manos.
- Trampa de acceso a la memoria en el host. Tradicionalmente, si un invitado de KVM accede a una dirección que no corresponde a una región de memoria válida, el subproceso de vCPU sale al host y el acceso generalmente se usa para MMIO y el VMM lo emula en el espacio del usuario. Para facilitar este manejo, se requiere que pKVM anuncie detalles sobre la instrucción que falla, como su dirección, parámetros de registro y potencialmente su contenido, de vuelta al host, lo que podría exponer involuntariamente datos confidenciales de un huésped protegido si no se anticipó la trampa. pKVM resuelve este problema al tratar estas fallas como fatales a menos que el invitado haya emitido previamente una hiperllamada para identificar el rango de IPA que falla como uno para el cual se permite que los accesos vuelvan al host. Esta solución se conoce como la protección MMIO .
Dispositivo de E/S virtual (virtio)
Virtio es un estándar popular, portátil y maduro para implementar e interactuar con dispositivos paravirtualizados. La mayoría de los dispositivos expuestos a invitados protegidos se implementan con virtio. Virtio también respalda la implementación de vsock utilizada para la comunicación entre un invitado protegido y el resto de Android.
Los dispositivos Virtio generalmente se implementan en el espacio de usuario del host mediante el VMM, que intercepta los accesos de memoria atrapados del invitado a la interfaz MMIO del dispositivo virtio y emula el comportamiento esperado. El acceso a MMIO es relativamente costoso porque cada acceso al dispositivo requiere un viaje de ida y vuelta al VMM y viceversa, por lo que la mayor parte de la transferencia de datos real entre el dispositivo y el invitado se produce mediante un conjunto de colas virtuales en la memoria. Una suposición clave de virtio es que el host puede acceder a la memoria del invitado de manera arbitraria. Esta suposición es evidente en el diseño de la virtqueue, que puede contener punteros a búferes en el invitado al que la emulación del dispositivo debe acceder directamente.
Aunque las hiperllamadas de intercambio de memoria descritas anteriormente podrían usarse para compartir búferes de datos virtio del invitado al host, este intercambio se realiza necesariamente en la granularidad de la página y podría terminar exponiendo más datos de los necesarios si el tamaño del búfer es menor que el de una página. . En su lugar, el invitado está configurado para asignar tanto las colas virtuales como sus búferes de datos correspondientes desde una ventana fija de memoria compartida, y los datos se copian (rebotan) hacia y desde la ventana según sea necesario.
Interacción con TrustZone
Aunque los invitados no pueden interactuar directamente con TrustZone, el anfitrión aún debe poder emitir llamadas SMC al mundo seguro. Estas llamadas pueden especificar búferes de memoria direccionados físicamente que son inaccesibles para el host. Debido a que el software seguro generalmente desconoce la accesibilidad del búfer, un host malicioso podría usar este búfer para realizar un ataque adjunto confuso (análogo a un ataque DMA). Para evitar este tipo de ataques, pKVM atrapa todas las llamadas SMC del host a EL2 y actúa como un proxy entre el host y el monitor seguro en EL3.
Las llamadas PSCI del host se reenvían al firmware EL3 con modificaciones mínimas. Específicamente, el punto de entrada para una CPU que se conecta o se reanuda desde la suspensión se reescribe para que la tabla de páginas de la etapa 2 se instale en EL2 antes de regresar al host en EL1. Durante el arranque, pKVM aplica estas protecciones.
Esta arquitectura se basa en el SoC compatible con PSCI, preferiblemente mediante el uso de una versión actualizada de TF-A como su firmware EL3.
Firmware Framework for Arm (FF-A) estandariza las interacciones entre los mundos normal y seguro, particularmente en presencia de un hipervisor seguro. Una parte importante de la especificación define un mecanismo para compartir memoria con el mundo seguro, utilizando un formato de mensaje común y un modelo de permisos bien definido para las páginas subyacentes. pKVM transmite mensajes FF-A para garantizar que el host no intente compartir memoria con el lado seguro para el cual no tiene suficientes permisos.
Esta arquitectura se basa en el software del mundo seguro que aplica el modelo de acceso a la memoria, para garantizar que las aplicaciones confiables y cualquier otro software que se ejecute en el mundo seguro pueda acceder a la memoria solo si es propiedad exclusiva del mundo seguro o se ha compartido explícitamente con él mediante FF. -A. En un sistema con S-EL2, la aplicación del modelo de acceso a la memoria debe realizarse mediante un Secure Partition Manager Core (SPMC), como Hafnium , que mantiene las tablas de páginas de la etapa 2 para el mundo seguro. En un sistema sin S-EL2, el TEE puede imponer un modelo de acceso a la memoria a través de sus tablas de página de etapa 1.
Si la llamada SMC a EL2 no es una llamada PSCI o un mensaje definido por FF-A, los SMC no manejados se reenvían a EL3. La suposición es que el firmware seguro (necesariamente confiable) puede manejar los SMC no manejados de manera segura porque el firmware comprende las precauciones necesarias para mantener el aislamiento de pVM.
monitor de máquina virtual
crosvm es un monitor de máquina virtual (VMM) que ejecuta máquinas virtuales a través de la interfaz KVM de Linux. Lo que hace que crosvm sea único es su enfoque en la seguridad con el uso del lenguaje de programación Rust y un espacio aislado alrededor de los dispositivos virtuales para proteger el kernel del host.
Descriptores de archivos e ioctls
KVM expone el dispositivo de caracteres /dev/kvm
al espacio de usuario con ioctls que conforman la API de KVM. Los ioctls pertenecen a las siguientes categorías:
- Los ioctls del sistema consultan y establecen atributos globales que afectan a todo el subsistema KVM y crean pVM.
- VM ioctls consulta y establece atributos que crean CPU virtuales (vCPU) y dispositivos, y afectan a una pVM completa, como incluir el diseño de la memoria y la cantidad de CPU virtuales (vCPU) y dispositivos.
- vCPU ioctls consulta y establece atributos que controlan el funcionamiento de una sola CPU virtual.
- Device ioctls consulta y establece atributos que controlan el funcionamiento de un único dispositivo virtual.
Cada proceso crosvm ejecuta exactamente una instancia de una máquina virtual. Este proceso usa el ioctl del sistema KVM_CREATE_VM
para crear un descriptor de archivo de VM que se puede usar para emitir ioctls de pVM. Un ioctl KVM_CREATE_VCPU
o KVM_CREATE_DEVICE
en una VM FD crea una vCPU/dispositivo y devuelve un descriptor de archivo que apunta al nuevo recurso. ioctls en una vCPU o dispositivo FD se puede usar para controlar el dispositivo que se creó usando ioctl en una VM FD. Para vCPU, esto incluye la importante tarea de ejecutar el código invitado.
Internamente, crosvm registra los descriptores de archivo de la VM con el kernel mediante la interfaz epoll
activada por borde. Luego, el kernel notifica a crosvm cada vez que hay un nuevo evento pendiente en cualquiera de los descriptores de archivo.
pKVM agrega una nueva capacidad, KVM_CAP_ARM_PROTECTED_VM
, que se puede usar para obtener información sobre el entorno de pVM y configurar el modo protegido para una VM. crosvm usa esto durante la creación de pVM si se pasa el --protected-vm
, para consultar y reservar la cantidad adecuada de memoria para el firmware de pVM, y luego para habilitar el modo protegido.
Asignación de memoria
Una de las principales responsabilidades de un VMM es asignar la memoria de la VM y administrar su diseño de memoria. crosvm genera un diseño de memoria fijo que se describe libremente en la siguiente tabla.
FDT en modo normal | PHYS_MEMORY_END - 0x200000 |
Espacio libre | ... |
ramdisk | ALIGN_UP(KERNEL_END, 0x1000000) |
Núcleo | 0x80080000 |
cargador de arranque | 0x80200000 |
FDT en modo BIOS | 0x80000000 |
Base de memoria física | 0x80000000 |
firmware pvm | 0x7FE00000 |
Dispositivo de memoria | 0x10000 - 0x40000000 |
La memoria física se asigna con mmap
y la memoria se dona a la VM para llenar sus regiones de memoria, llamadas memslots , con KVM_SET_USER_MEMORY_REGION
ioctl. Por lo tanto, toda la memoria de pVM invitada se atribuye a la instancia de crosvm que la administra y puede resultar en la finalización del proceso (finalización de la VM) si el host comienza a quedarse sin memoria libre. Cuando se detiene una máquina virtual, el hipervisor borra automáticamente la memoria y la devuelve al kernel del host.
Bajo KVM regular, el VMM retiene el acceso a toda la memoria de invitado. Con pKVM, la memoria del invitado se desasigna del espacio de direcciones físicas del host cuando se dona al invitado. La única excepción es la memoria compartida explícitamente por el huésped, como en el caso de los dispositivos virtio.
Las regiones MMIO en el espacio de direcciones del invitado se dejan sin asignar. El acceso a estas regiones por parte del invitado queda atrapado y da como resultado un evento de E/S en la VM FD. Este mecanismo se utiliza para implementar dispositivos virtuales. En el modo protegido, el invitado debe reconocer que una región de su espacio de direcciones se utilizará para MMIO mediante una hiperllamada, para reducir el riesgo de fuga de información accidental.
Planificación
Cada CPU virtual está representada por un subproceso POSIX y está programada por el programador de Linux del host. El subproceso llama a KVM_RUN
ioctl en el FD de vCPU, lo que hace que el hipervisor cambie al contexto de vCPU invitado. El programador de host contabiliza el tiempo pasado en un contexto de invitado como tiempo utilizado por el subproceso de vCPU correspondiente. KVM_RUN
regresa cuando hay un evento que debe ser manejado por el VMM, como E/S, final de interrupción o la detención de vCPU. El VMM maneja el evento y vuelve a llamar a KVM_RUN
.
Durante KVM_RUN
, el subproceso sigue siendo prioritario para el programador del host, excepto para la ejecución del código del hipervisor EL2, que no es prioritario. El pVM invitado en sí mismo no tiene ningún mecanismo para controlar este comportamiento.
Debido a que todos los subprocesos de vCPU se programan como cualquier otra tarea del espacio de usuario, están sujetos a todos los mecanismos estándar de QoS. Específicamente, cada subproceso de vCPU se puede asociar a CPU físicas, colocarse en conjuntos de cpu, potenciarse o limitarse mediante la restricción de utilización, cambiar su política de prioridad/programación, y más.
Dispositivos virtuales
crosvm es compatible con varios dispositivos, incluidos los siguientes:
- virtio-blk para imágenes de disco compuestas, solo lectura o lectura-escritura
- vhost-vsock para la comunicación con el host
- virtio-pci como transporte virtio
- pl030 reloj en tiempo real (RTC)
- 16550a UART para comunicación serie
firmware pvm
El firmware de pVM (pvmfw) es el primer código ejecutado por un pVM, similar a la ROM de arranque de un dispositivo físico. El objetivo principal de pvmfw es iniciar un arranque seguro y derivar el secreto único de pVM. pvmfw no se limita al uso con ningún sistema operativo específico, como Microdroid , siempre que el sistema operativo sea compatible con crosvm y se haya firmado correctamente.
El binario pvmfw se almacena en una partición flash del mismo nombre y se actualiza mediante OTA .
Arranque del dispositivo
La siguiente secuencia de pasos se agrega al procedimiento de inicio de un dispositivo habilitado para pKVM:
- El cargador de arranque de Android (ABL) carga pvmfw desde su partición en la memoria y verifica la imagen.
- El ABL obtiene sus secretos del motor de composición de identificadores de dispositivos (DICE) (identificadores de dispositivos compuestos (CDI) y cadena de certificados de arranque (BCC)) de una raíz de confianza.
- El ABL realiza la medición y la derivación DICE de los secretos de pvmfw (CDI) y los agrega al binario de pvmfw.
- El ABL agrega un nodo de región
linux,pkvm-guest-firmware-memory
al DT, que describe la ubicación y el tamaño del binario pvmfw y los secretos que derivó en el paso anterior. - El ABL entrega el control a Linux y Linux inicializa pKVM.
- pKVM desasigna la región de memoria pvmfw de las tablas de páginas de la etapa 2 del host y la protege del host (y los invitados) durante el tiempo de actividad del dispositivo.
Después del inicio del dispositivo, Microdroid se inicia según los pasos de la sección Secuencia de inicio del documento de Microdroid .
arranque pvm
Al crear un pVM, crosvm (u otro VMM) debe crear un memslot suficientemente grande para que el hipervisor lo ocupe con la imagen pvmfw. El VMM también está restringido en la lista de registros cuyo valor inicial puede establecer (x0-x14 para la CPU virtual principal, ninguno para las CPU virtuales secundarias). Los registros restantes están reservados y forman parte de la ABI de hipervisor-pvmfw.
Cuando se ejecuta pVM, el hipervisor primero entrega el control de la vCPU principal a pvmfw. El firmware espera que crosvm haya cargado un kernel firmado por AVB, que puede ser un gestor de arranque o cualquier otra imagen, y una FDT sin firmar en la memoria con compensaciones conocidas. pvmfw valida la firma AVB y, si tiene éxito, genera un árbol de dispositivos confiables a partir de la FDT recibida, borra sus secretos de la memoria y se ramifica al punto de entrada de la carga útil. Si uno de los pasos de verificación falla, el firmware emite una hiperllamada SYSTEM_RESET
.
Entre arranques, la información sobre la instancia de pVM se almacena en una partición (dispositivo virtio-blk) y se cifra con el secreto de pvmfw para garantizar que, después de un reinicio, el secreto se proporcione a la instancia correcta.