arquitectura AVF

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 marco.

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 mayor. 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 sólidas garantías de confidencialidad e integridad.

Hipervisor

La máquina virtual protegida basada en kernel (pKVM) se basa en el hipervisor KVM de Linux , 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 dependiendo de la disponibilidad de ciertas funciones de la CPU, es decir, las Extensiones de host de virtualización (VHE) (ARMv8.1 y posteriores). 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 encargado del cambio entre múltiples EL1 y completamente controlado por el kernel del host. El componente del hipervisor está compilado con Linux, pero reside en una sección de memoria dedicada separada de la imagen vmlinux . pKVM aprovecha este diseño al extender el código del hipervisor con nuevas características que le permiten imponer restricciones al kernel del host de Android y al espacio del usuario, y limitar el acceso del host a la memoria del huésped y al hipervisor.

Módulos de proveedor pKVM

Un módulo de proveedor pKVM es un módulo específico de hardware que contiene funcionalidades específicas del dispositivo, como controladores de unidad de administración de memoria de entrada y salida (IOMMU). Estos módulos le permiten transferir funciones de seguridad que requieren acceso de nivel de excepción 2 (EL2) a pKVM.

Para aprender cómo implementar y cargar un módulo de proveedor pKVM, consulte Implementar un módulo de proveedor pKVM .

Procedimiento de arranque

La siguiente figura muestra el procedimiento de inicio de pKVM:

Procedimiento de arranque pKVM

Figura 1. Procedimiento de arranque de pKVM

  1. El gestor de arranque ingresa al kernel genérico en EL2.
  2. El kernel genérico detecta que se está ejecutando en EL2 y se priva de EL1 mientras pKVM y sus módulos continúan ejecutándose en EL2. Además, los módulos del proveedor pKVM se cargan en este momento.
  3. El kernel genérico procede a arrancar normalmente, cargando todos los controladores de dispositivos necesarios hasta llegar al espacio del usuario. En este punto, pKVM está implementado y maneja las tablas de páginas de la etapa 2.

El procedimiento de arranque confía en que el gestor de arranque mantenga la integridad de la imagen del kernel sólo durante el arranque temprano. Cuando el kernel tiene privilegios, el hipervisor ya no lo considera confiable, y 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 mantenibilidad a largo plazo. El estrecho acoplamiento también permite optimizaciones del 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 implementar automáticamente el hipervisor pKVM 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 pueden usarse 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 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 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 una IPA y luego a una PA.

Protección de acceso a la memoria de la CPU

Figura 2. Protección de acceso a la memoria de la CPU

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 del 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, permitiendo así 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 huésped en lugar del host.

KVM aprovecha al máximo la traducción de direcciones en la etapa 2 para implementar asignaciones IPA/PA complejas 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 únicamente al control de acceso. La etapa 2 del host tiene un mapeo 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 asignaciones grandes en la tabla de páginas y, en consecuencia, reduce la presión sobre el búfer de traducción (TLB). Debido a que PA puede indexar una asignación de identidad, la etapa 2 del host 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, desasignar las páginas invitadas del host Linux en las tablas de páginas de la CPU es un paso necesario pero insuficiente para proteger la memoria invitada. pKVM también necesita protección contra accesos a la memoria realizados por dispositivos compatibles con 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 invitada, pKVM requiere hardware de unidad de administración de memoria de entrada-salida (IOMMU) para cada dispositivo compatible con DMA en el sistema, como se muestra en la figura 3.

Protección de acceso a memoria DMA

Figura 3. Protección de acceso a memoria DMA

Como mínimo, el hardware IOMMU proporciona los medios para otorgar y revocar el acceso de lectura/escritura de un dispositivo a la memoria física con granularidad de página. Sin embargo, este hardware IOMMU limita el uso de dispositivos en pVM ya que asumen una etapa 2 con mapeo de identidad.

Para garantizar el aislamiento entre máquinas virtuales, la IOMMU debe distinguir las transacciones de memoria generadas en nombre de diferentes entidades para que se pueda utilizar el conjunto apropiado 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 eludir por otros medios, por ejemplo, después de un reinicio del dispositivo.

Una IOMMU estándar y con buen soporte para dispositivos Arm que hace posible tanto el aislamiento como la asignación directa es la arquitectura de la Unidad de gestión de memoria del sistema (SMMU) de Arm. 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, como tal, el hipervisor la rastrea. Cuando se genera un pVM, el host dona páginas de memoria para permitirle arrancar y el hipervisor transfiere la propiedad de esas páginas del host al pVM. Por lo tanto, el hipervisor establece restricciones de control de acceso en la tabla de páginas de la etapa 2 del anfitrión para evitar que vuelva a acceder a las páginas, 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 anfitrión mediante una hiperllamada, que indica al hipervisor que reasigne esas páginas en la tabla de páginas de la etapa 2 del anfitrión. De manera similar, la comunicación del host con TrustZone es posible mediante operaciones de préstamo y/o uso compartido de memoria, todas las cuales son monitoreadas y controladas de cerca por pKVM utilizando la especificación Firmware Framework for Arm (FF-A) .

Dado que los requisitos de memoria de un pVM pueden cambiar con el tiempo, se proporciona una hiperllamada que permite devolver al host la propiedad de páginas específicas que pertenecen a la persona que llama. En la práctica, esta hiperllamada se utiliza con el protocolo de globo virtio para permitir que el VMM solicite memoria del pVM y que el pVM notifique al VMM sobre las páginas abandonadas, de manera controlada.

El hipervisor es responsable de rastrear la propiedad de todas las páginas de memoria del 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 anfitrión y de los invitados, utilizando bits reservados en las entradas de la tabla de páginas (PTE) que, como su nombre indica, están reservados para uso de software.

El host debe asegurarse de no intentar acceder a páginas que el hipervisor ha hecho inaccesibles. Un acceso ilegal al host hace que el hipervisor inyecte una excepción sincrónica en el host, lo que puede provocar que la tarea responsable del espacio de usuario reciba una señal SEGV o que el kernel del host falle. Para evitar accesos accidentales, las páginas donadas a invitados no son elegibles para ser intercambiadas o fusionadas por el kernel del host.

Manejo de interrupciones y temporizadores

Las interrupciones son una parte esencial de la forma en que un huésped interactúa con los dispositivos y para la comunicación entre 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 controlador de interrupción genérico 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.

Soporte GICv3

La interfaz entre EL1 y EL2 debe garantizar que el estado completo de la interrupción sea visible para el host EL1, incluidas las copias de los registros del hipervisor relacionados con las interrupciones. Esta visibilidad normalmente se logra mediante regiones de memoria compartida, una por CPU virtual (vCPU).

El código de soporte del tiempo de ejecución del registro del sistema se puede simplificar para admitir solo el registro de interrupción generado por software (SGIR) y el registro de desactivación de interrupción (DIR). La arquitectura exige que estos registros siempre se capturen en EL2, mientras que las otras trampas hasta ahora solo han sido útiles para mitigar 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, la espera de interrupción (WFI) siempre se retransmite 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 GIC, las capturas MMIO deben retransmitirse al host en EL1 para su posterior clasificación. pKVM requiere lo siguiente:

  • IPA y tamaño del acceso
  • Datos en caso de escritura
  • Endianidad de la CPU en el punto de captura

Además, las trampas con un registro de propósito general (GPR) como origen/destino se retransmiten mediante un pseudorregistro de transferencia abstracta.

Interfaces de invitados

Un invitado puede comunicarse con un invitado protegido mediante una combinación de hiperllamadas y acceso a la memoria a regiones atrapadas. Las hiperllamadas se exponen según el estándar SMCCC , con un rango reservado para la asignación de un proveedor por parte de 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, incluida la conexión, la desconexión y el apagado del sistema.
  • TRNG proporciona un mecanismo estándar para que el invitado solicite entropía del pKVM que retransmite la llamada a EL3. Este mecanismo es particularmente útil cuando no se puede confiar en que el host virtualice un generador de números aleatorios (RNG) de hardware.

Hiperllamadas de pKVM

  • Compartir memoria con el anfitrión. Inicialmente, el host no puede acceder a toda la memoria del huésped, pero el acceso al host es necesario para la comunicación de memoria compartida y para dispositivos paravirtualizados que dependen de buffers compartidos. Las hiperllamadas para compartir y dejar de compartir páginas con el anfitrión permiten al invitado decidir exactamente qué partes de la memoria son accesibles al resto de Android sin necesidad de un apretón de manos.
  • Cesión de memoria al anfitrión. Todos los recuerdos del huésped suelen pertenecer al huésped hasta que se destruyen. Este estado puede resultar inadecuado para máquinas virtuales de larga duración con requisitos de memoria que varían con el tiempo. La hiperllamada relinquish permite a un invitado transferir explícitamente la propiedad de las páginas al anfitrión sin necesidad de cancelar el servicio.
  • Captura de acceso a la memoria del host. Tradicionalmente, si un invitado KVM accede a una dirección que no corresponde a una región de memoria válida, entonces el subproceso de vCPU sale al host y el acceso generalmente se usa para MMIO y el VMM lo emula en el espacio de usuario. Para facilitar este manejo, se requiere que pKVM anuncie detalles sobre la instrucción defectuosa, como su dirección, parámetros de registro y potencialmente su contenido, al host, lo que podría exponer involuntariamente datos confidenciales de un invitado protegido si no se anticipó la trampa. pKVM resuelve este problema al tratar estas fallas como fatales a menos que el huésped haya emitido previamente una hiperllamada para identificar el rango IPA defectuoso como uno para el cual se permite el acceso al host. Esta solución se conoce como guardia 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 mediante 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 a la memoria atrapada desde el 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 anfitrión puede acceder a la memoria del invitado de forma arbitraria. Esta suposición es evidente en el diseño de la virtqueue, que podría contener punteros a buffers en el invitado a los que la emulación del dispositivo debe acceder directamente.

Aunque las hiperllamadas de uso compartido de memoria descritas anteriormente podrían usarse para compartir buffers de datos virtio desde el invitado al host, este intercambio se realiza necesariamente con granularidad de página y podría terminar exponiendo más datos de los necesarios si el tamaño del buffer es menor que el de una página. . En cambio, el invitado está configurado para asignar tanto las virtqueues como sus correspondientes buffers de datos desde una ventana fija de memoria compartida, y los datos se copian (rebotan) hacia y desde la ventana según sea necesario.

Dispositivo virtual

Figura 4. Dispositivo Virtio

Interacción con TrustZone

Aunque los invitados no pueden interactuar directamente con TrustZone, el anfitrión aún debe poder realizar llamadas SMC al mundo seguro. Estas llamadas pueden especificar buffers de memoria con dirección física 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 del SMC del host a EL2 y actúa como proxy entre el host y el monitor seguro en EL3.

Las llamadas PSCI desde el 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 una 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 que el SoC admita PSCI, preferiblemente mediante el uso de una versión actualizada de TF-A como 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 tanto un formato de mensaje común como un modelo de permisos bien definido para las páginas subyacentes. pKVM envía mensajes FF-A para garantizar que el host no intente compartir memoria con el lado seguro para el cual no tiene permisos suficientes.

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 puedan acceder a la memoria solo si es propiedad exclusiva del mundo seguro o si 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 tablas de páginas de etapa 2 para el mundo seguro. En un sistema sin S-EL2, el TEE puede aplicar un modelo de acceso a la memoria a través de sus tablas de páginas de la etapa 1.

Si la llamada SMC a EL2 no es una llamada PSCI o un mensaje definido por FF-A, los SMC no controlados se reenvían a EL3. Se supone que el firmware seguro (necesariamente confiable) puede manejar SMC no controlados 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 una zona de pruebas alrededor de dispositivos virtuales para proteger el kernel host. Para obtener más información sobre crosvm, consulte su documentación oficial aquí .

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.
  • Los ioctls de VM consultan y establecen atributos que crean CPU y dispositivos virtuales (vCPU), y afectan a una pVM completa, como incluir el diseño de la memoria y la cantidad de CPU y dispositivos virtuales (vCPU).
  • vCPU ioctls consulta y establece atributos que controlan el funcionamiento de una única CPU virtual.
  • Los ioctls del dispositivo consultan y establecen atributos que controlan el funcionamiento de un único dispositivo virtual.

Cada proceso crosvm ejecuta exactamente una instancia de una máquina virtual. Este proceso utiliza el ioctl del sistema KVM_CREATE_VM para crear un descriptor de archivo de VM que se puede utilizar para emitir ioctl 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. Los ioctls en una vCPU o dispositivo FD se pueden usar para controlar el dispositivo que se creó usando ioctl en un VM FD. Para las vCPU, esto incluye la importante tarea de ejecutar código invitado.

Internamente, crosvm registra los descriptores de archivos de la VM con el kernel utilizando 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 archivos.

pKVM agrega una nueva capacidad, KVM_CAP_ARM_PROTECTED_VM , que se puede utilizar para obtener información sobre el entorno pVM y configurar el modo protegido para una VM. crosvm usa esto durante la creación de pVM si se pasa el indicador --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 ...
disco RAM 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 el ioctl KVM_SET_USER_MEMORY_REGION . Por lo tanto, toda la memoria pVM invitada se atribuye a la instancia crosvm que la administra y puede provocar que el proceso se detenga (terminando 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.

En KVM normal, VMM conserva el acceso a toda la memoria del 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 invitado, como en el caso de los dispositivos virtio.

Las regiones MMIO en el espacio de direcciones del invitado no se asignan. El acceso del invitado a estas regiones queda atrapado y genera un evento de E/S en la VM FD. Este mecanismo se utiliza para implementar dispositivos virtuales. En modo protegido, el huésped debe reconocer que una región de su espacio de direcciones se utilizará para MMIO mediante una hiperllamada, para reducir el riesgo de fuga accidental de información.

Planificación

Cada CPU virtual está representada por un subproceso POSIX y programada por el programador del host Linux. 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 del 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, fin de interrupción o vCPU detenida. El VMM maneja el evento y vuelve a llamar a KVM_RUN .

Durante KVM_RUN , el programador del host puede interrumpir el subproceso, excepto para la ejecución del código del hipervisor EL2, que no es interrumpible. El pVM invitado en sí no tiene ningún mecanismo para controlar este comportamiento.

Debido a que todos los subprocesos de vCPU están programados como cualquier otra tarea del espacio de usuario, están sujetos a todos los mecanismos de QoS estándar. Específicamente, cada subproceso de vCPU se puede afinar a CPU físicas, colocarse en cpusets, impulsarse o limitarse mediante sujeción de utilización, cambiar su política de prioridad/programación y más.

Dispositivos virtuales

crosvm admite varios dispositivos, incluidos los siguientes:

  • virtio-blk para imágenes de disco compuestas, de solo lectura o lectura-escritura
  • vhost-vsock para 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 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 realizar un arranque seguro y obtener el secreto único del pVM. pvmfw no se limita a su uso con ningún sistema operativo específico, como Microdroid , siempre que el sistema operativo sea compatible con crosvm y esté 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:

  1. El cargador de arranque de Android (ABL) carga pvmfw desde su partición en la memoria y verifica la imagen.
  2. 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.
  3. El ABL realiza mediciones y derivación DICE de los secretos de pvmfw (CDI) y los agrega al binario de pvmfw.
  4. La ABL agrega un nodo de región de memoria reservada 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.
  5. El ABL entrega el control a Linux y Linux inicializa pKVM.
  6. 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 de 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 una ranura de memoria lo suficientemente grande para que el hipervisor la complete con la imagen pvmfw. El VMM también está restringido en la lista de registros cuyo valor inicial puede establecer (x0-x14 para la vCPU principal, ninguno para las vCPU secundarias). Los registros restantes están reservados y forman parte de la ABI 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 en compensaciones conocidas. pvmfw valida la firma AVB y, si tiene éxito, genera un árbol de dispositivos confiables a partir del FDT recibido, borra sus secretos de la memoria y se ramifica hasta el punto de entrada de la carga útil. Si uno de los pasos de verificación falla, el firmware emite una hiperllamada PSCI 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 aprovisione en la instancia correcta.