1.. _vuart_virtualization:
2
3vUART Virtualization
4####################
5
6Architecture
7************
8
9A vUART is a virtual 16550 UART implemented in the hypervisor. It can work as a
10console or a communication port. The vUART is mapped to the
11traditional COM port address. A UART driver in the kernel can auto detect the
12port base and IRQ.
13
14.. figure:: images/uart-virt-hld-1.png
15   :align: center
16   :name: uart-arch-pic
17
18   UART Virtualization Architecture
19
20Each vUART has two FIFOs: 8192 bytes TX FIFO and 256 bytes RX FIFO.
21We only provide 4 ports for use.
22
23-  COM1 (port base: 0x3F8, irq: 4)
24
25-  COM2 (port base: 0x2F8, irq: 3)
26
27-  COM3 (port base: 0x3E8, irq: 6)
28
29-  COM4 (port base: 0x2E8, irq: 7)
30
31A VM can enable one console vUART and several communication vUARTs.
32
33Console vUART
34*************
35
36A vUART can be used as a console port, and it can be activated by
37a ``vm_console <vm_id>`` command in the hypervisor console.
38:numref:`console-uart-arch` shows only one physical UART, but four console
39vUARTs (green color blocks). A hypervisor console is implemented above the
40physical UART, and it works in polling mode. The hypervisor console has a
41timer. The timer handler sends input from the physical UART to the
42vUART or the hypervisor shell process. The timer handler also gets data from
43the vUART's TX FIFO and sends it to the physical UART. The data in the vUART's
44FIFOs is overwritten if it is not taken out in time.
45
46.. figure:: images/uart-virt-hld-2.png
47   :align: center
48   :name: console-uart-arch
49
50   Console vUART Architecture
51
52Communication vUART
53*******************
54
55The communication vUART is used to transfer data between two VMs in low
56speed. For the kernel driver, it is a general UART that can be detected and
57probed by 8250 serial driver. But in the hypervisor, it has a special process.
58
59From :numref:`communication-uart-arch`, the vUART in two VMs is
60connected according to the configuration in the hypervisor.  When a user
61writes a byte to the communication UART in VM0:
62
63Operations in VM0
64
65-  VM0 UART driver puts the data to THR.
66
67-  VM traps to hypervisor, and the vUART PIO handler is called.
68
69-  Puts the data to its target vUART's RX FIFO.
70
71-  Injects a Data Ready interrupt to VM1.
72
73-  If the target vUART's FIFO is not full, injects a THRE interrupt to VM0.
74
75-  Returns.
76
77Operations in VM1
78
79-  Receives an interrupt, dispatches to UART driver.
80
81-  Reads LSR register, finds a Data Ready interrupt.
82
83-  Reads data from RX FIFO.
84
85-  If RX FIFO is not full, injects THRE interrupt to VM0.
86
87.. figure:: images/uart-virt-hld-3.png
88   :align: center
89   :name: communication-uart-arch
90
91   Communication vUART Architecture
92
93Usage
94*****
95
96-  For console vUART
97
98   To enable the console port for a VM, change the ``port_base`` and ``irq``
99   fields in
100   ``configs/scenarios/<scenario name>/vm_configurations.c`` under the
101   hypervisor build directory using the combinations listed below. If the IRQ
102   number has been used in your
103   system ( ``cat /proc/interrupt``), you can choose other IRQ number. Set
104   the ``.irq =0``, the vUART will work in polling mode.
105
106   -  COM1_BASE (0x3F8) + COM1_IRQ(4)
107
108   -  COM2_BASE (0x2F8) + COM2_IRQ(3)
109
110   -  COM3_BASE (0x3E8) + COM3_IRQ(6)
111
112   -  COM4_BASE (0x2E8) + COM4_IRQ(7)
113
114   Example::
115
116      .vuart[0] = {
117                        .type = VUART_LEGACY_PIO,
118                        .addr.port_base = COM1_BASE,
119                        .irq = COM1_IRQ,
120                  }
121
122   The kernel bootargs ``console=ttySx`` should be the same with
123   vuart[0]; otherwise, the kernel console log cannot be captured by the
124   hypervisor. Then, after bringing up the system, you can switch the console
125   to the target VM by:
126
127   .. code-block:: console
128
129      ACRN:\>vm_console 0
130      ----- Entering VM 0 Shell -----
131
132-  For communication vUART
133
134   To enable the communication port, configure vuart[1] in
135   the two VMs that need to communicate. The port_base and IRQ should
136   not repeat with the vuart[0] in the same VM. t_vuart.vm_id is the
137   target VM's vm_id, start from 0 (0 means VM0). t_vuart.vuart_id is the
138   target vUART index in the target VM, start from 1 (1 means vuart[1]).
139
140   Example::
141
142      /* VM0 */
143      ...
144      /* VM1 */
145      .vuart[1] = {
146                        .type = VUART_LEGACY_PIO,
147                        .addr.port_base = COM2_BASE,
148                        .irq = COM2_IRQ,
149                        .t_vuart.vm_id = 2U,
150                        .t_vuart.vuart_id = 1U,
151                        },
152      ...
153      /* VM2 */
154      .vuart[1] = {
155                        .type = VUART_LEGACY_PIO,
156                        .addr.port_base = COM2_BASE,
157                        .irq = COM2_IRQ,
158                        .t_vuart.vm_id = 1U,
159                        .t_vuart.vuart_id = 1U,
160                  },
161
162.. note:: The Device Model also has a virtual UART and uses 0x3F8
163   and 0x2F8 as port base. If you add ``-s <slot>, lpc`` in the launch
164   script, the Device Model will create COM0 and COM1 for the post-launched VM.
165   It will also add the port information to the ACPI table. This configuration
166   is useful for Windows and VxWorks as they probe the driver according to the
167   ACPI table.
168
169   If you enable the Device Model UART and the hypervisor vUART at the
170   same port address, access to the port address will be responded to by the
171   hypervisor vUART directly, and will not pass to the Device Model.
172