acrn-hypervisor/doc/developer-guides/hld/vuart-virt-hld.rst

172 lines
5.3 KiB
ReStructuredText

.. _vuart_virtualization:
vUART Virtualization
####################
Architecture
************
A vUART is a virtual 16550 UART implemented in the hypervisor. It can work as a
console or a communication port. Currently, the vUART is mapped to the
traditional COM port address. A UART driver in the kernel can auto detect the
port base and IRQ.
.. figure:: images/uart-virt-hld-1.png
:align: center
:name: uart-arch-pic
UART virtualization architecture
Each vUART has two FIFOs: 8192 bytes TX FIFO and 256 bytes RX FIFO.
Currently, we only provide 4 ports for use.
- COM1 (port base: 0x3F8, irq: 4)
- COM2 (port base: 0x2F8, irq: 3)
- COM3 (port base: 0x3E8, irq: 6)
- COM4 (port base: 0x2E8, irq: 7)
A VM can enable one console vUART and several communication vUARTs.
Console vUART
*************
A vUART can be used as a console port, and it can be activated by
a ``vm_console <vm_id>`` command in the hypervisor console.
:numref:`console-uart-arch` shows only one physical UART, but four console
vUARTs (green color blocks). A hypervisor console is implemented above the
physical UART, and it works in polling mode. The hypervisor console has a
timer. The timer handler sends input from the physical UART to the
vUART or the hypervisor shell process. The timer handler also gets data from
the vUART's TX FIFO and sends it to the physical UART. The data in the vUART's
FIFOs is overwritten if it is not taken out in time.
.. figure:: images/uart-virt-hld-2.png
:align: center
:name: console-uart-arch
console vUART architecture
Communication vUART
*******************
The communication vUART is used to transfer data between two VMs in low
speed. For the kernel driver, it is a general UART that can be detected and
probed by 8250 serial driver. But in the hypervisor, it has a special process.
From :numref:`communication-uart-arch`, the vUART in two VMs is
connected according to the configuration in the hypervisor. When a user
writes a byte to the communication UART in VM0:
Operations in VM0
- VM0 UART driver puts the data to THR.
- VM traps to hypervisor, and the vUART PIO handler is called.
- Puts the data to its target vUART's RX FIFO.
- Injects a Data Ready interrupt to VM1.
- If the target vUART's FIFO is not full, injects a THRE interrupt to VM0.
- Returns.
Operations in VM1
- Receives an interrupt, dispatches to UART driver.
- Reads LSR register, finds a Data Ready interrupt.
- Reads data from RX FIFO.
- If RX FIFO is not full, injects THRE interrupt to VM0.
.. figure:: images/uart-virt-hld-3.png
:align: center
:name: communication-uart-arch
communication vUART architecture
Usage
*****
- For console vUART
To enable the console port for a VM, change the ``port_base`` and ``irq``
fields in
``configs/scenarios/<scenario name>/vm_configurations.c`` under the
hypervisor build directory using the combinations listed below. If the IRQ
number has been used in your
system ( ``cat /proc/interrupt``), you can choose other IRQ number. Set
the ``.irq =0``, the vUART will work in polling mode.
- COM1_BASE (0x3F8) + COM1_IRQ(4)
- COM2_BASE (0x2F8) + COM2_IRQ(3)
- COM3_BASE (0x3E8) + COM3_IRQ(6)
- COM4_BASE (0x2E8) + COM4_IRQ(7)
Example::
.vuart[0] = {
.type = VUART_LEGACY_PIO,
.addr.port_base = COM1_BASE,
.irq = COM1_IRQ,
}
The kernel bootargs ``console=ttySx`` should be the same with
vuart[0]; otherwise, the kernel console log cannot be captured by the
hypervisor. Then, after bringing up the system, you can switch the console
to the target VM by:
.. code-block:: console
ACRN:\>vm_console 0
----- Entering VM 0 Shell -----
- For communication vUART
To enable the communication port, configure vuart[1] in
the two VMs that need to communicate. The port_base and IRQ should
not repeat with the vuart[0] in the same VM. t_vuart.vm_id is the
target VM's vm_id, start from 0 (0 means VM0). t_vuart.vuart_id is the
target vUART index in the target VM, start from 1 (1 means vuart[1]).
Example::
/* VM0 */
...
/* VM1 */
.vuart[1] = {
.type = VUART_LEGACY_PIO,
.addr.port_base = COM2_BASE,
.irq = COM2_IRQ,
.t_vuart.vm_id = 2U,
.t_vuart.vuart_id = 1U,
},
...
/* VM2 */
.vuart[1] = {
.type = VUART_LEGACY_PIO,
.addr.port_base = COM2_BASE,
.irq = COM2_IRQ,
.t_vuart.vm_id = 1U,
.t_vuart.vuart_id = 1U,
},
.. note:: The Device Model also has a virtual UART and uses 0x3F8
and 0x2F8 as port base. If you add ``-s <slot>, lpc`` in the launch
script, the Device Model will create COM0 and COM1 for the post-launched VM.
It will also add the port information to the ACPI table. This configuration
is useful for Windows and VxWorks as they probe the driver according to the
ACPI table.
If you enable the Device Model UART and the hypervisor vUART at the
same port address, access to the port address will be responded to by the
hypervisor vUART directly, and will not pass to the Device Model.