1.. _uart_virtualization:
2
3UART Virtualization
4###################
5
6In ACRN, UART virtualization is implemented as a fully-emulated device.
7In the Service VM, UART virtualization is implemented in the
8hypervisor itself.  In the User VM, UART virtualization is
9implemented in the Device Model (DM), and is the primary topic of this
10document.  We'll summarize differences between the hypervisor and DM
11implementations at the end of this document.
12
13
14UART emulation is a typical full-emulation implementation and is a
15good example to learn about I/O emulation in a virtualized environment.
16There is a detailed explanation about the I/O emulation flow in
17ACRN in :ref:`ACRN-io-mediator`.
18
19Architecture
20************
21
22The ACRN DM architecture for UART virtualization is shown here:
23
24.. figure:: images/uart-image1.png
25   :align: center
26   :name: uart-arch
27   :width: 800px
28
29   Device Model's UART Virtualization Architecture
30
31There are three objects used to emulate one UART device in DM:
32UART registers, rxFIFO, and backend tty devices.
33
34**UART registers** are emulated by member variables in struct
35``uart_vdev``, one variable for each register. These variables are used
36to track the register status programed by the frontend driver. The
37handler of each register depends on the register's functionality.
38
39A **FIFO** is implemented to emulate RX. Normally characters are read
40from the backend tty device when available, then put into the rxFIFO.
41When the Guest application tries to read from the UART, the access to
42register ``com_data`` causes a ``vmexit``. Device Model catches the
43``vmexit`` and emulates the UART by returning one character from rxFIFO.
44
45.. note:: When ``com_fcr`` is available, the Guest application can write
46   ``0`` to this register to disable rxFIFO. In this case the rxFIFO in
47   the Device Model degenerates to a buffer containing only one character.
48
49When the Guest application tries to send a character to the UART, it
50writes to the ``com_data`` register, which will cause a ``vmexit`` as
51well.  Device Model catches the ``vmexit`` and emulates the UART by
52redirecting the character to the **backend tty device**.
53
54The UART device emulated by the ACRN Device Model is connected to the system by
55the LPC bus. In the current implementation, two channel LPC UARTs are I/O mapped to
56the traditional COM port addresses of 0x3F8 and 0x2F8. These are defined in
57global variable ``uart_lres``.
58
59There are two options needed for configuring the UART in the ``acrn-dm``
60command line. First, the LPC is defined as a PCI device::
61
62   -s 1:0,lpc
63
64The other option defines a UART port::
65
66   -l com1,stdio
67
68The first parameter here is the name of the UART (must be "com1" or
69"com2"). The second parameter is species the backend
70tty device: ``stdio`` or a path to the dedicated tty device
71node, for example ``/dev/pts/0``.
72
73If you are using a specified tty device, find the name of the terminal
74connected to standard input using the ``tty`` command (e.g.,
75``/dev/pts/1``).  Use this name to define the UART port on the acrn-dm
76command line, for example::
77
78   -l com1,/dev/pts/1
79
80
81When acrn-dm starts, ``pci_lpc_init`` is called as the callback of the
82``vdev_init`` of the PCI device given on the acrn-dm command line.
83Later, ``lpc_init`` is called in ``pci_lpc_init``. ``lpc_init`` iterates
84on the available UART instances defined on the command line and
85initializes them one by one.  ``register_inout`` is called on the port
86region of each UART instance, enabling access to the UART ports to be
87routed to the registered handler.
88
89In the case of UART emulation, the registered handlers are ``uart_read``
90and ``uart_write``.
91
92A similar virtual UART device is implemented in the hypervisor.
93UART16550 is owned by the hypervisor itself and is used for
94debugging purposes.  (The UART properties are configured by parameters
95to the hypervisor command line.) The hypervisor emulates a UART device
96with 0x3F8 address to the Service VM and acts as the Service VM console. The
97general emulation is the same as used in the Device Model, with the following
98differences:
99
100-  PIO region is directly registered to the vmexit handler dispatcher via
101   ``vuart_register_io_handler``
102
103-  Two FIFOs are implemented, one for RX, the other of TX
104
105-  RX flow:
106
107   -  Characters are read from the UART HW into a 2048-byte sbuf,
108      triggered by ``console_read``
109
110   -  Characters are read from the sbuf and put to rxFIFO,
111      triggered by ``vuart_console_rx_chars``
112
113   -  A virtual interrupt is sent to the Service VM that triggered the read,
114      and characters from rxFIFO are sent to the Service VM by emulating a read
115      of register ``UART16550_RBR``
116
117-  TX flow:
118
119   -  Characters are put into txFIFO by emulating a write of register
120      ``UART16550_THR``
121
122   -  Characters in txFIFO are read out one by one, and sent to the console
123      by printf, triggered by ``vuart_console_tx_chars``
124
125   -  Implementation of printf is based on the console, which finally sends
126      characters to the UART HW by writing to register ``UART16550_RBR``
127