A Linux driver quality standard requirements document
Many people who create drivers as part of their job are familiar with the driver/hardware qualification requirements that Microsoft uses. While Linux has no formal driver certification process, there are a set of guidelines, processes and rules that are comparable to the other qualification process and that have a similar impact on the market acceptance of a Linux device driver.
The Linux kernel is a moving target without ABI or API compatibility towards device drivers. The fundamental model is that device drivers are part of the kernel tree, and get automatically adjusted for API changes by the person who proposes an API change.
(Requirement 1.1) Develop drivers against the latest kernel codebase at all times
OS vendors generally require or desire that drivers are part of the official kernel.org kernel tree before they will consider your device driver for their products; in order to become part of OS distributions it’s therefore critical to aim and develop for kernel.org inclusion. (And once that inclusion is achieved, inclusion of your driver in all future OS releases is pretty much automatic)
(Requirement 2.1) Follow the Documentation/CodingStyle document
The Linux kernel has a very specific style and preferred way to structure the code of drivers. This style is rather different compared to most other projects and operating systems. The open source nature of Linux also means that the source code of the driver is a key deliverable. The Linux kernel has a document called “CodingStyle” that describes the requirements that Linux has in terms of looks, naming and structure of the code.
BKM The CodingStyle document is about structure as well as style. The structure requirements impact both the design and implementation, so the CodingStyle document is something that should be considered from the start of development; it’s not something you can just put in at the end when development is done.
(Requirement 2.2) Run the scripts/checkpatch.pl script on any code/patch and fix all issues it reports
The Linux kernel also has a perl script (checkpatch.pl) that checks a patch or a driver for common mistakes made in the style area; in effect this is an objective check for the often subjective advice in the CodingStyle document
(Requirement 2.3) Use kerneldoc for in-code documentation
Comments and documentation that are put in the source code, must use the so called “kerneldoc” documentation format. There are many examples of “kerneldoc” in the kernel, the distinctive marking of kerneldoc is the /** sequence as the start of a comment.
(Requirement 2.4) All source code files must have an approved copyright/license header
Due to the open source, many contributors nature of the Linux kernel, it’s important to put a copyright header on each and every file of your project, stating the Intel ownership of the copyright and the copyright license used (GPL version 2).
BKM An example header is shown below:
* (C) Copyright 2008 Intel Corporation * Author: Your Name <Your.Name@intel.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; version 2 * of the License. */
(Requirement 2.5) Source files must not use deprecated APIs
Due to the evolving nature of the Linux kernel, there are always some legacy APIs that are being phased out. Often, the functions that implement the API are marked with the __deprecated keyword that causes the compiler to give a warning. For some cases, the depreciation is more complex and is put on the global depreciation list in the Documentation/feature-removal-schedule.txt file. Using deprecated functions or APIs will form a maintenance problem in the near future, so avoid using these APIs at all cost; use the new API instead.
(Requirement 2.6) Kernel code must use the in-kernel debug macros The Linux kernel has debug print helpers (pr_debug/dev_debug family of APIs). These APIs hook into a diagnostics backend and are required to be used by device drivers for their debugging infrastructure.
(Requirement 2.7) Drivers must contain sufficient locking The Linux kernel is a highly multithreaded environment. As a result, all drivers need to contain sufficient locking using the Linux locking primitives to be safe against concurrent use of the driver in the various scenarios. Locking tends to have an impact on driver architecture, and is generally not something that can be added at the end.
(Requirement 2.8) Drivers must validate user provided input To meet the kernels security objectives, device drivers must validate for validity any and all input provided from userspace. Example mechanisms where such userspace input is provided into drivers are ioctls and sysfs.
(Requirement 3.1) Patches must be small self-contained, represent one logical change and contain sufficient documentation
The Linux development process makes a distinction between the first submission of a driver and later improvements/maintenance that is done on the driver. While it is OK for a first submission of a driver to be relatively large, future improvements to the driver should be done as incremental, well described changes
(Requirement 3.2) Each patch must contain a Signed-Off-By: line
Linux has its own COO-like process. By adding a Signed-Off-By: line to the patch, the author/submitter of the patch submits the patch under the conditions of the Developers Certificate of Origin as documented in the Documentation/SubmittingPatches file.
Linux has various tools to help increase driver quality. It’s important to leverage these tools to the maximum extend possible in order to ensure a low-defect, maintainable driver.
(Requirement 4.1) Driver code must not generate any compiler warnings
Your first tool to detect issues is the compiler itself: The compiler (helped by Linux) flags many code defects on a very basic level via the warnings mechanism.
(Requirement 4.2) Test drivers both on 32 bit and 64 bit kernels
Even when you’re developing primarily for a 32 bit Operating System, it’s important to test the driver on both 32 bit and 64 bit kernels. At minimum compile the driver and run the ABAT. 64 bit kernels tend to expose bugs in normal use that happen only rarely on 32 bit kernels
(Requirement 4.3) The driver must pass tests and generate no errors, warnings or kernel messages when using the kernel debug options from table 4.1
The Linux kernel has various kernel options that help finding issues in drivers; while many of these options are not suitable for production deployment, it’s critical to enable these options during development and validation to find bugs early during the development process. Below is a list of configuration options that must be enabled during development and validation:
Table 4.1 CONFIG_PREEMPT CONFIG_PROVE_LOCKING CONFIG_ENABLE_MUST_CHECK CONFIG_LOCKDEP CONFIG_HEADERS_CHECK CONFIG_DEBUG_SPINLOCK_SLEEP CONFIG_DEBUG_KERNEL CONFIG_STACKTRACE CONFIG_DEBUG_SHIRQ CONFIG_DEBUG_KOBJECT CONFIG_DETECT_SOFTLOCKUP CONFIG_DEBUG_VM CONFIG_TIMER_STATS CONFIG_DEBUG_LIST CONFIG_DEBUG_SLAB CONFIG_FRAME_POINTER CONFIG_DEBUG_SLAB_LEAK CONFIG_FAULT_INJECTION CONFIG_DEBUG_RT_MUTEXES CONFIG_FAILSLAB CONFIG_DEBUG_PI_LIST CONFIG_FAIL_PAGE_ALLOC CONFIG_DEBUG_SPINLOCK CONFIG_FAIL_MAKE_REQUEST CONFIG_DEBUG_MUTEXES CONFIG_DEBUG_RODATA CONFIG_DEBUG_LOCK_ALLOC
(Requirement 4.4) The driver design must be power friendly and not wake the CPU out of idle more than 1x per second when idle
(Requirement 4.5) Put the hardware device in a low power state when not in use
Power consumption is one of the key value drivers for Intel platforms, and our silicon is getting increasingly more advanced features over time. Unfortunately, software, including device drivers, can be written in a way that prevents our silicon from using its power saving features. In addition, device drivers in Linux are required to put the device in a low power state when there are no active users of the device when the hardware design allows this.
BKM The PowerTOP program is a tool to detect bad software/driver behaviour.
(Requirement 4.6) Use “make namespacecheck” to mark code static whenever possible
The Linux kernel has strict requirements about the identifier namespaces; since it’s not uncommon for people to have a kernel with all drivers linked into it, no driver can have clashes in (exposed) function names with any other driver. A key technique to make this workable is to mark as many identifiers as possible as “static”.
(Requirement 4.7) Use “make checkstack” to verify a stack footprint of less than 128 bytes
Unlike some other operating systems, the Linux kernel has a small stack for itself, as little as 4 Kilobytes. It is therefore critical to design the code to have a low stack footprint. The kernel provides a tool to verify that the stack consumption of a driver is reasonable: make checkstack
(Requirement 4.8) Create and use an ABAT with at least the minimal operations
There is a minimal set of tests that each driver should go through and that test some of the very common code paths. The validation team should have an ABAT that covers at least the following operations: • Repeated load / use / unload cycles of the driver module • Repeated bind / unbind cycles via the bind sysfs API • A “cat” on every sysfs file • A file permission check on every sysfs file; only root should be able to modify settings • Repeated Suspend/Resume cycles (both Standby and Hibernate)
• (Requirement 1.1) Develop drivers against the latest kernel codebase at all times • (Requirement 2.1) Follow the Documentation/CodingStyle document
• (Requirement 2.2) Run the scripts/checkpatch.pl script on any code/patch and fix all issues it reports • (Requirement 2.3) Use kerneldoc for in-code documentation
• (Requirement 2.4) All source code files need to have a copyright/license header • (Requirement 2.5) Do not use deprecated functions or APIs, check the feature-removal-schedule.txt file. • (Requirement 2.6) Device drivers must use Linux debug APIs
• (Requirement 2.7) Device drivers must contain sufficient locking
• (Requirement 2.8) Drivers must validate user provided input
• (Requirement 3.1) Patches should be small self-contained, representing one logical change and documented sufficient for a reviewer to understand the rational as well as the change • (Requirement 4.1) Driver code should not generate any compiler warnings
• (Requirement 4.2) Test drivers both on 32 bit and 64 bit kernels
• (Requirement 4.3) Enable the debug kernel options during development and validation • (Requirement 4.4) Use PowerTOP to make sure the driver doesn’t wake the CPU out of idle • (Requirement 4.5) Put the hardware device in a low power state when not in use • (Requirement 4.6) Use “make namespacecheck” to mark code static whenever possible • (Requirement 4.7) Use “make checkstack” to verify a minimal stack footprint • (Requirement 4.8) Create and use an ABAT with at least the minimal operations