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) 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 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 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:

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.

d. Update the //sdk/history/*/zx.api_summary.json files. These are for the public zx FIDL library, which shares zx_common.fidl with the syscall library.

e. Extend docsgen as necessary.

2. Implement the syscall in the kernel

Implement the syscall somewhere in zircon/kernel/lib/syscalls/, with a prefix of sys_ instead of zx_. For now, the implementation should simply return ZX_ERR_NOT_SUPPORTED.

3. Add a lib/zx C++ wrapper

Add a new or extend an existing lib/zx 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 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.

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, and update (fidl_codec (used by fidlcat): - ShortObjTypeName in display_handle.cc - PrettyPrinter::DisplayObjType in printer.cc

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.