# Zircon Kernel Invariants

On x86, Zircon needs to maintain the following invariants for code running
in ring 0 (kernel mode).

These invariants are documented here because they are not necessarily easy
to test -- breaking an invariant will not necessarily be caught by
Zircon's test suite.

- Flags register:

  - The direction flag (DF) should be 0. This is required by the x86 calling conventions.

  If this flag is set to 1, uses of x86 string instructions (e.g. `rep
  movs` in `memcpy()` or inlined by the compiler) can go wrong and copy
  in the wrong direction. It is OK for a function to set this flag to 1
  temporarily as long as it changes it back to 0 before returning or
  calling other functions.
  - The alignment check flag (AC) should normally be 0. On CPUs that support SMAP, this prevents the kernel from accidentally reading or writing userland data.
- The `gs_base` register must point to the current CPU's `x86_percpu`
  struct whenever running in kernel mode with interrupts enabled.
  `gs_base` should only be changed to point to something else while
  interrupts are disabled. For example, the `swapgs` instruction should
  only be used when interrupts are disabled.

- The following are partially enforced by the compiler:

  - No use of extended registers (SSE, AVX, x87, etc.) is allowed, because that would clobber userland's register state.

  This is partially achieved by passing `-mno-sse` to the compiler. This
  option is necessary to prevent the compiler from using SSE registers in
  optimizations (e.g. memory copies).

  We would like to prevent accidentally using the `float` or `double`
  types in kernel code, but GCC and Clang won't do that for us in all
  cases. `-mno-sse` does not prevent using `float`/`double` with either
  compiler -- the compilers will use x87 instructions instead.

  We compile with `-msoft-float`, which seems to prevent GCC from
  generating x87 instructions (and hence using x87 registers): GCC 6.3.0
  will give an error on `float`/`double` arithmetic and return values,
  but it does not prevent passing these types around as arguments.
  However, passing `-msoft-float` to Clang seems to have no effect: Clang
  7.0.0 will still generate x87 instructions (and use x87 registers) for
  code using `float` or `double`.
  - No storing data below `%rsp` on the stack. Note that userland code can do this: the SysV x86-64 ABI allows functions to store data in the "red zone", which is the 128 bytes below %rsp. However, kernel code cannot use the red zone because interrupts may clobber this region -- the CPU pushes data onto the stack immediately below %rsp when it invokes an interrupt handler.

  This is generally enforced by passing `-mno-red-zone` to the compiler.

[](https://issues.fuchsia.dev/issues/new?component=1439230&template=1881640&description=Issue+on:+https://fuchsia.dev/docs/concepts/kernel/kernel_invariants.md "Report a bug or suggest improvements on this page") [](https://cs.opensource.google/fuchsia/fuchsia/+/main:docs/concepts/kernel/kernel_invariants.md "View the source code of this page") [](https://ci.android.com/edit?repo=fuchsia/fuchsia/main&file=docs/concepts/kernel/kernel_invariants.md&cloneRepo=fuchsia/fuchsia:refs/heads/main&fullPath=fuchsia/docs/concepts/kernel/kernel_invariants.md "Edit the source code of this page")