From e2a8989ff49baf1b422e6b31b74a427af5c34736 Mon Sep 17 00:00:00 2001 From: Junjie Mao Date: Wed, 21 Nov 2018 19:15:06 +0800 Subject: [PATCH] doc: add a document on considerations and current status of hypervisor modularization To kick off the efforts on modularization, this patch introduces a document describing the goals and general principles of modular design as well as a brief introduction on the current status of component/module decomposition. A detailed assignment of source files to components will be added in the future. v2 -> v3: * Expand mailing list address in the doc v1 -> v2: * Add more description on complexity measures, cyclic dependency avoidance, and the reverse dependency of boot on hypervisor initialzation. * Fix typos. Tracked-On: #1842 Signed-off-by: Junjie Mao --- .../images/modularity-architecture.png | Bin 0 -> 52052 bytes doc/developer-guides/index.rst | 1 + doc/developer-guides/modularity.rst | 133 ++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100755 doc/developer-guides/images/modularity-architecture.png create mode 100644 doc/developer-guides/modularity.rst diff --git a/doc/developer-guides/images/modularity-architecture.png b/doc/developer-guides/images/modularity-architecture.png new file mode 100755 index 0000000000000000000000000000000000000000..6253f2e352da1b1d4b840fd9796b8ff2facb9699 GIT binary patch literal 52052 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 & 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 literal 0 HcmV?d00001 diff --git a/doc/developer-guides/index.rst b/doc/developer-guides/index.rst index 1e92b273f..20394319d 100644 --- a/doc/developer-guides/index.rst +++ b/doc/developer-guides/index.rst @@ -11,6 +11,7 @@ Developer Guides GVT-g-porting trusty l1tf + modularity ../api/index ../reference/kconfig/index diff --git a/doc/developer-guides/modularity.rst b/doc/developer-guides/modularity.rst new file mode 100644 index 000000000..26c210d3e --- /dev/null +++ b/doc/developer-guides/modularity.rst @@ -0,0 +1,133 @@ +.. _modularity: + +ACRN Hypervisor: Modular Design +############################### + +Overview +******** + +ACRN highly emphasizes modular design, i.e. the separation of functionality info +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. White-box 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 + [IEC_61508-3]_ and ISO 26262 [ISO_26262-6]_. + +Principles +********** + +* Each source file shall belong 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 shall have well-defined interfaces, including the exported + functions and global variables. Functions and variables that are not + interfaces shall be 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 shall be limited. + +Minimizing Cyclic Dependencies +============================== + +Cyclic dependencies can be mostly avoided by carefully defining the boundary of +modules. The following methods can be used when certain cyclic dependency cannot +be resolved by design. + +* **Use callbacks** Callback registration and invocation help reverse dependencies + between two modules and break cyclic dependencies. However callbacks shall be + used with care due to its dynamic behavior. Send proposals or patches to the + `acrn-dev mailing list `_ for + discussing if 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 work around 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 criterias on complexity +will be determined while enhancing the modularity of the hypervisor. The current +recommendation is to limit the cyclomatic complexity of a function 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 abstract hardware + resources and provide services like 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 SOS. +* **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. +* **Passthru Management** This component manages devices that are passed-through + to specific VMs. +* **Extended Device Emulation** This component implements an I/O request + mechanism that allow the hypervisor to forward I/O accesses from UOSes to SOS + 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 up + SOS 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 only invokes 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