| # 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. |