| # Style guide |
| |
| Hafnium's coding style has been based on the |
| [Linux style](https://www.kernel.org/doc/html/v4.17/process/coding-style.html) |
| with explicit modifications: |
| |
| * Always use braces for conditionals and loops. (No SSL `goto fail;`, thanks.) |
| |
| Following this, we generally fall back to the subset of the |
| [Google C++ style guide](https://google.github.io/styleguide/cppguide.html) that |
| is applicable to C. |
| |
| We try to automate this where possible with clang-format and clang-tidy but that |
| doesn't capture everything we'd like today. Where the style enforced by this |
| tooling conflicts with what is in this document we accept what the tooling |
| requires, and try to improve it if possible. |
| |
| [TOC] |
| |
| ## Clarifications |
| |
| * Yes, it does mean all variables are declared, C90-style, at the top of |
| scope, even those loop induction variables. |
| * Linux encourages no braces around single-statement branches. We follow |
| Google and require braces around all scope blocks. |
| |
| ## Naming symbols |
| |
| * Arch-specific functions should start with `arch_`. |
| * Platform-specific functions should start with `plat_`. |
| * Non-static functions should generally start with the name of the file they |
| are declared in (after the `arch_` or `plat_` prefix if appropriate), though |
| there are quite a few exceptions to this rule. |
| * Prefer `x_count` over `num_x`. |
| |
| ## Prose |
| |
| These rules apply to comments and other natural language text. |
| |
| * Capitalize acronyms. |
| * CPU, vCPU, VM, EL2, SPCI, QEMU |
| * Spell out Hafnium in full, not Hf. |
| * Use single spaces. |
| * Sentences end with full stops. |
| * If the comment fits on one line use `/* */`, otherwise space it out: |
| |
| ``` |
| /* |
| * Informative long comment |
| * with extra information. |
| */ |
| ``` |
| |
| * Doc-ish comments start with `/**`. |
| |
| * Use for: |
| * Function definitions (not declarations) |
| * Struct declarations |
| * Enum values |
| * Do not use for: |
| * Macros |
| * Definitions of globals |
| |
| * References to code symbols use backticks, e.g. `` `my_symbol` ``. |
| |
| ## Coding practices |
| |
| * Function macros should be functions instead, that way you get types. |
| * Lock ordering is described at the top of [`api.c`](../src/api.c). |
| * Use opaque types to avoid implicit casts when it will help avoid mistakes. |
| e.g. [`addr.h`](../inc/hf/addr.h) |
| * Avoid inline casting. C doesn't give much protection so be formal about the |
| transformations. e.g. [`addr.h`](../inc/hf/addr.h) |
| * If a function acquires a resource, there must be a single exit path to free |
| the resource. Tracking down multiple exit points is hard and requires |
| duplicated code which is harder. This may require splitting functions into |
| subfunctions. Early exit is okay if there aren't any clean up tasks. |
| * Don't use function pointers. It makes analysis hard and is often a target of |
| attacks. |
| * Be liberal with `CHECK`. Use it to assert pre-/post- conditions. |
| * No self-modifying code. |
| * Build targets should include all the direct dependencies for their sources, |
| where possible, rather than relying on transitive dependencies. |
| |
| ## Logging |
| |
| Hafnium uses the same log levels as Arm Trusted Firmware. There are 5 log |
| levels, in order of severity: |
| |
| 1. `ERROR` |
| |
| Use this only for cases that there is an error in the hypervisor itself, |
| perhaps caused by a coding error, bad configuration, unexpected hardware |
| behaviour or a malformed manifest. Errors should not be logged during normal |
| operation, even in case of a buggy or malicious VM. |
| |
| 2. `NOTICE` |
| |
| Use this sparingly for important messages which should be logged even in |
| production builds because they will be useful for debugging. This is a |
| suitable level to use for events which may indicate a bug in a VM. |
| |
| 3. `WARNING` |
| |
| Use this for warnings which are important to developers but can generally be |
| ignored in production. |
| |
| 4. `INFO` |
| |
| Use this to provide extra information that is helpful for developers. |
| |
| 5. `VERBOSE` |
| |
| Use this to provide even more information which may be helpful when tracing |
| through execution in detail, such as when debugging test failures. This is |
| the only level which should include any sensitive data. |
| |
| Logging is done with the `dlog_*` macros, e.g. `dlog_info`. These accept |
| printf-style format strings and arguments. |
| |
| The log level of a build is controlled by the `log_level` argument defined in |
| [`BUILDCONFIG.gn`](../build/BUILDCONFIG.gn). This defaults to `INFO` for debug |
| builds and tests, meaning that all levels except `VERBOSE` will be logged. It is |
| recommended to set the log level to `NOTICE` for production builds, to reduce |
| binary size and log spam. |