mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-06 12:06:25 +00:00
doc: add UART virtualization documentation
transcode, review, and publish UART virtualization design and documentation Signed-off-by: David B. Kinder <david.b.kinder@intel.com>
This commit is contained in:
parent
6c54cba985
commit
746cbab979
BIN
doc/developer-guides/images/uart-image1.png
Normal file
BIN
doc/developer-guides/images/uart-image1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
@ -23,6 +23,7 @@ specific areas within the ACRN hypervisor system.
|
|||||||
virtio-hld.rst
|
virtio-hld.rst
|
||||||
ACPI-virt-hld.rst
|
ACPI-virt-hld.rst
|
||||||
APL_GVT-g-hld.rst
|
APL_GVT-g-hld.rst
|
||||||
|
uart-virtualization.rst
|
||||||
|
|
||||||
Contributing to the project
|
Contributing to the project
|
||||||
***************************
|
***************************
|
||||||
|
126
doc/developer-guides/uart-virtualization.rst
Normal file
126
doc/developer-guides/uart-virtualization.rst
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
.. _uart_virtualization:
|
||||||
|
|
||||||
|
UART Virtualization
|
||||||
|
###################
|
||||||
|
|
||||||
|
In ACRN, UART virtualization is implemented as a fully-emulated device.
|
||||||
|
In the Service OS (SOS), UART virtualization is implemented in the
|
||||||
|
hypervisor itself. In the User OS (UOS), UART virtualization is
|
||||||
|
implemented in the Device Model (DM), and is the primary topic of this
|
||||||
|
document. We'll summarize differences between the hypervisor and DM
|
||||||
|
implementations at the end of this document.
|
||||||
|
|
||||||
|
|
||||||
|
UART emulation is a typical full-emulation implementation and is a
|
||||||
|
good example to learn about I/O emulation in a virtualized environment.
|
||||||
|
There is a detailed explanation about the I/O emulation flow in
|
||||||
|
ACRN in :ref:`ACRN-io-mediator`.
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
************
|
||||||
|
|
||||||
|
The ACRN DM architecture for UART virtualization is shown here:
|
||||||
|
|
||||||
|
.. figure:: images/uart-image1.png
|
||||||
|
:align: center
|
||||||
|
:name: uart-arch
|
||||||
|
:width: 800px
|
||||||
|
|
||||||
|
Device Model's UART virtualization architecture
|
||||||
|
|
||||||
|
There are three objects used to emulate one UART device in DM:
|
||||||
|
UART registers, rxFIFO, and backend tty devices.
|
||||||
|
|
||||||
|
**UART registers** are emulated by member variables in struct
|
||||||
|
``uart_vdev``, one variable for each register. These variables are used
|
||||||
|
to track the register status programed by the frontend driver. The
|
||||||
|
handler of each register depends on the register's functionality.
|
||||||
|
|
||||||
|
A **FIFO** is implemented to emulate RX. Normally characters are read
|
||||||
|
from the backend tty device when available, then put into the rxFIFO.
|
||||||
|
When the Guest application tries to read from the UART, the access to
|
||||||
|
register ``com_data`` causes a ``vmexit``. Device model catches the
|
||||||
|
``vmexit`` and emulates the UART by returning one character from rxFIFO.
|
||||||
|
|
||||||
|
.. note:: When ``com_fcr`` is available, the Guest application can write
|
||||||
|
``0`` to this register to disable rxFIFO. In this case the rxFIFO in
|
||||||
|
device model degenerates to a buffer containing only one character.
|
||||||
|
|
||||||
|
When the Guest application tries to send a character to the UART, it
|
||||||
|
writes to the ``com_data`` register, which will cause a ``vmexit`` as
|
||||||
|
well. Device model catches the ``vmexit`` and emulates the UART by
|
||||||
|
redirecting the character to the **backend tty device**.
|
||||||
|
|
||||||
|
The UART device emulated by the ACRN device model is connected to the system by
|
||||||
|
the LPC bus. In the current implementation, two channel LPC UARTs are I/O mapped to
|
||||||
|
the traditional COM port addresses of 0x3F8 and 0x2F8. These are defined in
|
||||||
|
global variable ``uart_lres``.
|
||||||
|
|
||||||
|
There are two options needed for configuring the UART in the ``arcn-dm``
|
||||||
|
command line. First, the LPC is defined as a PCI device::
|
||||||
|
|
||||||
|
-s 1:0,lpc
|
||||||
|
|
||||||
|
The other option defines a UART port::
|
||||||
|
|
||||||
|
-l com1,stdio
|
||||||
|
|
||||||
|
The first parameter here is the name of the UART (must be "com1" or
|
||||||
|
"com2"). The second parameter is species the backend
|
||||||
|
tty device: ``stdio`` or a path to the dedicated tty device
|
||||||
|
node, for example ``/dev/pts/0``.
|
||||||
|
|
||||||
|
If you are using a specified tty device, find the name of the terminal
|
||||||
|
connected to standard input using the ``tty`` command (e.g.,
|
||||||
|
``/dev/pts/1``). Use this name to define the UART port on the acrn-dm
|
||||||
|
command line, for example::
|
||||||
|
|
||||||
|
-l com1,/dev/pts/1
|
||||||
|
|
||||||
|
|
||||||
|
When arcn-dm starts, ``pci_lpc_init`` is called as the callback of the
|
||||||
|
``vdev_init`` of the PCI device given on the acrn-dm command line.
|
||||||
|
Later, ``lpc_init`` is called in ``pci_lpc_init``. ``lpc_init`` iterates
|
||||||
|
on the available UART instances defined on the command line and
|
||||||
|
initializes them one by one. ``register_inout`` is called on the port
|
||||||
|
region of each UART instance, enabling access to the UART ports to be
|
||||||
|
routed to the registered handler.
|
||||||
|
|
||||||
|
In the case of UART emulation, the registered handlers are ``uart_read``
|
||||||
|
and ``uart_write``.
|
||||||
|
|
||||||
|
A similar virtual UART device is implemented in the hypervisor.
|
||||||
|
Currently UART16550 is owned by the hypervisor itself and is used for
|
||||||
|
debugging purposes. (The UART properties are configured by parameters
|
||||||
|
to the hypervisor command line.) The hypervisor emulates a UART device
|
||||||
|
with 0x3F8 address to the SOS and acts as the SOS console. The general
|
||||||
|
emulation is the same as used in the device model, with the following
|
||||||
|
differences:
|
||||||
|
|
||||||
|
- PIO region is directly registered to the vmexit handler dispatcher via
|
||||||
|
``vuart_register_io_handler``
|
||||||
|
|
||||||
|
- Two FIFOs are implemented, one for RX, the other of TX
|
||||||
|
|
||||||
|
- RX flow:
|
||||||
|
|
||||||
|
- Characters are read from the UART HW into a 2048-byte sbuf,
|
||||||
|
triggered by ``console_read``
|
||||||
|
|
||||||
|
- Characters are read from the sbuf and put to rxFIFO,
|
||||||
|
triggered by ``vuart_console_rx_chars``
|
||||||
|
|
||||||
|
- A virtual interrupt is sent to the SOS that triggered the read,
|
||||||
|
and characters from rxFIFO are sent to the SOS by emulating a read
|
||||||
|
of register ``UART16550_RBR``
|
||||||
|
|
||||||
|
- TX flow:
|
||||||
|
|
||||||
|
- Characters are put into txFIFO by emulating a write of register
|
||||||
|
``UART16550_THR``
|
||||||
|
|
||||||
|
- Characters in txFIFO are read out one by one, and sent to the console
|
||||||
|
by printf, triggered by ``vuart_console_tx_chars``
|
||||||
|
|
||||||
|
- Implementation of printf is based on the console, which finally sends
|
||||||
|
characters to the UART HW by writing to register ``UART16550_RBR``
|
Loading…
Reference in New Issue
Block a user