blob: 3868a22115552ef02b0670dea241ae5ab00fd0ba [file] [log] [blame] [view]
# Adding a New Zircon Syscall (...or a New Zircon Object Type)
This doc is a short guide to adding a new Zircon syscall. The intended audience
is kernel developers or anyone who is adding a new syscall.
Keep in mind that this guide only covers the *mechanics* of adding
syscall/objects. It's not a style guide, rubric, and does not provide any
advice on how to know when an API is stable enough or mature enough to become
part of the system interface.
Because our system continues to change, you should expect that this guide is out
of date. Sorry. If you are following this guide and you notice errors or
omissions, please make an attempt to update it. Thank you!
## Overview
There are a number of ways you can structure the changes to add a new Zircon
syscall (or object). This guide will describe an approach consisting of four
CLs: stub, implementation, extras, and annotations.
We're going to follow the "rewrite history" method. Zircon syscalls do not
([currently][345252431]) follow Platform Versioning so instead we're going to
make it look as if the new syscall had been there all along. To do this, we'll
need to update some SDK history files for frozen API levels.
### Stub CL: Start with a stub at HEAD
In this CL, you'll define the syscall and provide a stub implementation that
simply returns `ZX_ERR_NOT_SUPPORTED`. Be sure to include a core-test in this
stub CL that verifies the caller doesn't crash and that the new call returns the
error as expected.
The build system and FIDL compiler will automatically generate some of the
boilerplate for you. To take advantage, you'll want to get in the habit of
performing a default build, `fx build`, and running `fx check-goldens` after you
make changes to FIDL files.
To illustrate, let's look at a [stub CL][stub-cl] that adds both a new Zircon
object (`counter`) and a new syscall (`zx_counter_create`).
The stub CL has four parts.
#### 1. Define the syscall using FIDL
Next, [define the new syscall][counter-fidl] in an existing `.fidl` file or add
a new file if appropriate. Be sure to add a commented out
`@available(added=HEAD)` annotation that indicates the new syscall (or object if
adding a new Zircon object) is added at HEAD.
In the rarer event of adding a new Zircon object, you'll need to take a few
extra steps.
a. Teach the FIDL compiler about the new object type. The FIDL toolchain bakes
in knowledge of object types. This isn't elegant, but it avoids some circular
dependencies. You'll have to update parts of the FIDL toolchain to understand
your new object type. In particular, update:
- `HandleSubtype` in [`//tools/fidl/fidlc/src/properties.h`][fidlc-properties]
- `NameHandleSubtype` in [`//tools/fidl/fidlc/src/names.cc`][fidlc-names]
- `HandleType` in
[`//tools/fidl/abi-compat/src/compare/handle.rs`][fidl-compare]
- `handle-subtype` in [`//tools/fidl/fidlc/schema.json`][fidlc-schema]
- `GoodHandleSubtype` in
[`//tools/fidl/fidlc/tests/types_tests.cc`][fidlc-types-tests]
- `HandleSubtype` and `ObjectType` consts in
[`//tools/fidl/lib/fidlgen/types.go`][fidlgen-types]
- `handleSubtypes`, `handleSubtypesFdomain` and `objectTypeConsts` in
[`//tools/fidl/fidlgen_rust/codegen/ir.go`][fidlgen-ir]
b. Update the `fidlc` goldens by following the instructions provided in the build
error you get when you build without updating them.
c. Add the new object type to [zircon/types.h][zircon-types-header].
d. Update the `//sdk/history/*/zx.api_summary.json` [files][api-summary]. These
are for the public `zx` FIDL library, which shares `zx_common.fidl` with the
syscall library.
e. [Extend docsgen][gen-syscalls-toc] as necessary.
#### 2. Implement the syscall in the kernel
Implement the syscall [somewhere in
zircon/kernel/lib/syscalls/][counter-syscall-impl], with a prefix of `sys_`
instead of `zx_`. For now, the implementation should simply return
`ZX_ERR_NOT_SUPPORTED`.
Note: The `sys_` function's signature isn't necessarily the same as the `zx_`
function's signature. If you're unsure of the right `sys_` signature you run a
build and check the resulting
`$root_build_dir/fidling/gen/zircon/vdso/zx/zither/kernel/lib/syscalls/kernel.inc`
file. Or check the build output for a linker error that tells you the missing
`sys_` function's expected signature.
#### 3. Add a lib/zx C++ wrapper
[Add a new or extend an existing lib/zx wrapper][counter-wrapper] in order to
provide a C++ API for the new syscall. Be sure to apply a
`ZX_AVAILABLE_SINCE(HEAD)` annotation to your new C++ method (or class if it's a
new Zircon object). While the syscall itself will appear to have been present
from the very beginning, the C++ wrapper is added at HEAD.
#### 4. Add a core-test
[Add a core-test][counter-core-test] that verifies the stub returns the right
error value (and does not crash the system). By using the new `lib/zx` wrapper
in this test, you can be sure it also works as expected.
Once you've gotten the stub to build and pass CQ, land it. Next, move on to the
implementation CL.
#### 5. Add FIDL language bindings for new Zircon objects
To enable the use of a new Zircon object (i.e. `zx.Handle:COUNTER`) in the C++
and Rust language bindings, there are a few additional areas that must be
updated. These updates allow the language binding code generators to know how to
handle a new Zircon object.
For FIDL C++ language bindings, update:
- `ShortObjTypeName` in [`//src/lib/fidl_codec/display_handle.cc`][fidlcodec-display-handle]
- `DisplayObjType` in [`//src/lib/fidl_codec/printer.cc`][fidlcodec-printer]
- Add object header to [`//sdk/lib/fidl/hlcpp/include/lib/fidl/cpp/internal/header.h`][fidlcpp-header]
- `handleSubtypeConsts` in [`//tools/fidl/lib/fidlgen_cpp/handles.go`][fidlgencpp-handles]
- `zxNames` in [`//tools/fidl/lib/fidlgen_cpp/name_transforms.go`][fidlgencpp-name-transforms]
For FIDL Rust language bindings, update:
- `ObjectType` in [`//sdk/rust/zx/src/handle.rs`][rust-handle]
- `invoke_for_handle_types` in [`//src/lib/fuchsia-async/src/handle/mod.rs`][fasync-handle]
### Implementation CL: Filling in the stub
Now it's time to replace the stub implementation with a real one, add real tests
and real documentation. Built it, pass CQ, land it, and move on.
### Extras CL: Add the rest
Once you've got a working implementation with C/C++ bindings, you're now ready
to add [Rust bindings][rust], and update `(fidl_codec` (used by `fidlcat`):
- `ShortObjTypeName` in [`display_handle.cc`][codec-handle]
- `PrettyPrinter::DisplayObjType` in [`printer.cc`][codec-printer]
The above list of "extras" may be incomplete so this is a good time look around
ad other syscalls to see if there are more things you need to update (tools?
bindings for other languages?). Land the extras CLs and move on to the final
step.
### Annotations CL: Change HEAD to NEXT
Now that the implementation and extras have landed, go back and change the value
you added in the `@available` and `ZX_AVAILABLE_SINCE` annotation(s) from `HEAD`
to `NEXT` to make the syscall available in the next stable API level.
<!-- TODO(https://fxbug.dev/383761360): Update the links below to use code
search rather than CL in gerrit. -->
[345252431]: https://fxbug.dev/345252431
[stub-cl]: https://fxrev.dev/1181176
[fidlc-properties]: /tools/fidl/fidlc/src/properties.h
[fidlc-names]: /tools/fidl/fidlc/src/names.cc
[fidl-compare]: /tools/fidl/abi-compat/src/compare/handle.rs
[fidlc-schema]: /tools/fidl/fidlc/schema.json
[fidlc-types-tests]: /tools/fidl/fidlc/tests/types_tests.cc
[fidlgen-types]: /tools/fidl/lib/fidlgen/types.go
[fidlgen-ir]:/tools/fidl/fidlgen_rust/codegen/ir.go
[zircon-types-header]: https://fuchsia-review.googlesource.com/c/fuchsia/+/1181176/9/zircon/system/public/zircon/types.h
[api-summary]: https://fuchsia-review.googlesource.com/c/fuchsia/+/1181176/9/sdk/history/16/zx.api_summary.json
[gen-syscalls-toc]: https://fuchsia-review.googlesource.com/c/fuchsia/+/1181176/9/tools/docsgen/gen_syscalls_toc.py
[counter-fidl]: https://fuchsia-review.googlesource.com/c/fuchsia/+/1181176/9/zircon/vdso/counter.fidl
[counter-syscall-impl]: https://fuchsia-review.googlesource.com/c/fuchsia/+/1181176/9/zircon/kernel/lib/syscalls/counter.cc#13
[counter-wrapper]: https://fuchsia-review.googlesource.com/c/fuchsia/+/1181176/9/zircon/system/ulib/zx/include/lib/zx/counter.h
[counter-core-test]: https://fuchsia-review.googlesource.com/c/fuchsia/+/1181176/9/zircon/system/utest/core/counter/counter.cc
[rust]: /sdk/rust/zx
[codec-handle]: /src/lib/fidl_codec/display_handle.cc
[codec-printer]: /src/lib/fidl_codec/printer.cc
[fidlcodec-display-handle]: /src/lib/fidl_codec/display_handle.cc
[fidlcodec-printer]: /src/lib/fidl_codec/printer.cc
[fidlcpp-header]: /sdk/lib/fidl/hlcpp/include/lib/fidl/cpp/internal/header.h
[fidlgencpp-handles]: /tools/fidl/lib/fidlgen_cpp/handles.go
[fidlgencpp-name-transforms]: /tools/fidl/lib/fidlgen_cpp/name_transforms.go
[rust-handle]: /sdk/rust/zx/src/handle.rs
[fasync-handle]: /src/lib/fuchsia-async/src/handle/mod.rs