136 lines
6.3 KiB
ReStructuredText
136 lines
6.3 KiB
ReStructuredText
.. _modularity:
|
|
|
|
ACRN Hypervisor: Modular Design
|
|
###############################
|
|
|
|
Overview
|
|
********
|
|
|
|
ACRN highly emphasizes modular design, which is the separation of
|
|
functionality into modules that define a concise set of interfaces. The goals
|
|
of modular design include:
|
|
|
|
* **Understandability** A modular design is easier to understand due to
|
|
encapsulation.
|
|
* **Testability** Modules can be integrated and tested in the reverse order of
|
|
dependencies among them. Modular integration tests help improve the coverage
|
|
of tests and identify corner cases that are hard to trigger when testing the
|
|
hypervisor as a whole.
|
|
* **Configurability** Modular design makes it easy to configure certain
|
|
functionalities in or out. This is crucial in safety-critical scenarios,
|
|
because absence of irrelevant code is required in both MISRA-C and
|
|
functional safety standards.
|
|
* **Meet functional safety requirements** Functional safety standards
|
|
explicitly require a hierarchical structure of modules in software
|
|
architectural design. This applies to any safety integrity level defined in
|
|
[IEC_61508-3]_ and [ISO_26262-6]_.
|
|
|
|
Principles
|
|
**********
|
|
|
|
* Each source file belongs to one module only. One module may consist of one
|
|
or multiple source files, though. A source file can be a C source, a C
|
|
header, or an assembly file.
|
|
* Each module has well-defined interfaces, including the exported functions
|
|
and global variables. Functions and variables that are not interfaces are
|
|
static and used inside the module only.
|
|
* Dependencies among the modules should be acyclic. Any cyclic dependency must
|
|
be deviated explicitly.
|
|
* The complexity of a module should be limited.
|
|
|
|
Minimizing Cyclic Dependencies
|
|
==============================
|
|
|
|
Cyclic dependencies are mostly avoided through careful definition of module
|
|
boundaries. The following methods can be used when a cyclic dependency cannot
|
|
be resolved by design:
|
|
|
|
* **Use callbacks** Callback registration and invocation help to reverse
|
|
dependencies between modules and break cyclic dependencies. However,
|
|
callbacks must be used with care due to their dynamic behavior. Send
|
|
proposals or patches to the
|
|
`acrn-dev mailing list <https://lists.projectacrn.org/g/acrn-dev>`_ for
|
|
discussing whether specific callbacks are appropriate.
|
|
* **Making the cyclic dependency an exception** A specific cyclic dependency
|
|
can be regarded as an exception if it is well justified and a workaround is
|
|
available to break the cyclic dependency for integration testing.
|
|
|
|
Measuring Complexity
|
|
====================
|
|
|
|
ACRN uses the number of functions and the cyclomatic complexity [CC]_ of each
|
|
function to measure the complexity of a module. Concrete criteria on
|
|
complexity will be determined during the process of enhancing the modularity
|
|
of the hypervisor. The current recommendation is to limit the cyclomatic
|
|
complexity of a function to under 20.
|
|
|
|
Architecture
|
|
************
|
|
|
|
The following figure shows the high-level components of ACRN hypervisor:
|
|
|
|
.. figure:: images/modularity-architecture.png
|
|
:align: center
|
|
:name: modularity-architecture
|
|
|
|
Layered Architecture of ACRN Hypervisor
|
|
|
|
The components are listed as follows.
|
|
|
|
* **Boot** This component carries out the most basic hardware initialization
|
|
to enable the execution of C code.
|
|
* **Library** This component consists of subroutines that require no explicit
|
|
initialization. Examples include standard memory and string manipulation
|
|
functions like strncpy, atomic operations, and bitmap operations. This
|
|
component is independent from and widely used in the other components.
|
|
* **Hardware Management and Utilities** This component abstracts hardware
|
|
resources and provide services such as timers and physical interrupt handler
|
|
registration to the upper layers.
|
|
* **Virtual CPU** This component implements CPU, memory, and interrupt
|
|
virtualization. The vCPU loop module in this component handles VM exit
|
|
events by calling the proper handler in the other components. Hypercalls are
|
|
implemented as a special type of VM exit event. This component is also able
|
|
to inject upcall interrupts to the Service VM.
|
|
* **Device Emulation** This component implements devices that are emulated in
|
|
the hypervisor itself, such as the virtual programmable interrupt
|
|
controllers including vPIC, vLAPIC, and vIOAPIC.
|
|
* **Passthrough Management** This component manages devices that are passed
|
|
through to specific VMs.
|
|
* **Extended Device Emulation** This component implements an I/O request
|
|
mechanism that enables the hypervisor to forward I/O accesses from a User
|
|
VM to the Service VM for emulation.
|
|
* **VM Management** This component manages the creation, deletion, and other
|
|
lifecycle operations of VMs.
|
|
* **Hypervisor Initialization** This component invokes the initialization
|
|
subroutines in the other components to bring up the hypervisor and start
|
|
the Service VM in sharing mode or all the VMs in partitioning mode.
|
|
|
|
ACRN hypervisor adopts a layered design where higher layers can invoke the
|
|
interfaces of lower layers but not vice versa. The only exception is the
|
|
invocation of initialization routine in the **Boot** component, illustrated as
|
|
the arrow from bottom to top on the left side of figure
|
|
:numref:`modularity-architecture`. This exception is made due to the following
|
|
reasons.
|
|
|
|
* **Boot** enables the execution of C code and thus has to be the lowest layer
|
|
in the architecture.
|
|
* **Hypervisor Initialization** contains the hypervisor initialization
|
|
function that calls the initialization functions of each layer. Thus this
|
|
component is the highest layer to minimize reverse dependencies.
|
|
* **Boot** shall invoke the hypervisor initialization routine after bringing
|
|
up the hardware. This inevitably causes a reverse dependency from **Boot**
|
|
to **Hypervisor Initialization**.
|
|
|
|
To enable integration testing of a layer in the middle (e.g. **Virtual CPU**),
|
|
**Boot** will invoke a customized function that invokes only the
|
|
initialization functions of that layer as well as the layers below.
|
|
|
|
References
|
|
**********
|
|
|
|
.. [IEC_61508-3] IEC 61508-3:2010, Functional safety of electrical/electronic/programmable electronic safety-related systems - Part 3: Software requirements
|
|
|
|
.. [ISO_26262-6] ISO 26262-6:2011, Road vehicles - Functional safety - Part 6: Product development at the software level
|
|
|
|
.. [CC] Cyclomatic complexity - Wikipedia, https://en.wikipedia.org/wiki/Cyclomatic_complexity
|