Closed hawkw closed 8 months ago
Unfortunately, merging this is a little bit tricky, as there's kind of a circular dependency between the hubris
and idolatry
repos. This branch currently has a Git dep on oxidecomputer/hubris#1642, the branch that integrates these changes with Hubris, because it needs changes to the counters
crate in the Hubris repo. But, oxidecomputer/hubris#1642 depends on idolatry
from this branch, because it uses the new APIs added in this change.
I'm going to separate out the counters
crate changes in the Hubris repo, so that we can merge them first. That way, we can merge this PR without having a broken master
branch in either repo, and without merging branch deps to master
.
Update: the Hubris PRs that need to merge before this branch are oxidecomputer/hubris#1640 and oxidecomputer/hubris#1647. Once those branches have merged, this PR can depend on oxidecomputer/hubris@master, and we can merge it, and then move on to actually using the new counter generation stuff in Hubris.
Okay, this branch now depends on oxidecomputer/hubris@master again, now that the requisite PRs have merged.
Depends on #41.
This branch adds the capability to automatically generate counters of IPC operations using the Hubris
counters
crate to Idol code generation. Counters can be generated for both client and server stubs, and will generate a separate counter for each IPC operation in an interface. Fallible IPC operations will generate separate counters ofOk
andErr
responses, with theErr
path including child counters of each variant of the IPC's error type, provided it derives theCount
trait.In order to configure how and where counters are generated, I've added a new
Generator
struct that represents a code-generation configuration. This type has flags for whether counters are enabled, and a flag that changes the server-side counter generation to track allClientError
variants globally rather than per-IPC, if this is necessary to limit the size of the generated counter table. This is configured using theGenerator
struct added in #41.This also requires additions to the
counters
crate in the corresponding Hubris PR #1642.As an example, the counters generated by this branch for the Gimlet sequencer IPC API look like this in Humility. Note that a separate set of counters is generated for each task which is a client of the sequencer:
Humility output:
```console $ humility -d hubris.c12.autocounts.core.3 counters --full __SEQUENCER_CLIENT` humility: attached to dump control_plane_agent | +---> drv_gimlet_seq_api::__SEQUENCER_CLIENT_COUNTERS: 0 get_state(_) 0 | get_state(Ok) 0 | get_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 set_state(_) 0 | set_state(Ok) 0 | set_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_on(_) 0 | fans_on(Ok) 0 | fans_on(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_off(_) 0 | fans_off(Ok) 0 | fans_off(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 send_hardware_nmi(_) 0 | send_hardware_nmi(Ok) 0 | send_hardware_nmi(Err) 0 read_fpga_regs(_) 0 | read_fpga_regs(Ok) 0 | read_fpga_regs(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) gimlet_inspector | +---> drv_gimlet_seq_api::__SEQUENCER_CLIENT_COUNTERS: 0 get_state(_) 0 | get_state(Ok) 0 | get_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 set_state(_) 0 | set_state(Ok) 0 | set_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_on(_) 0 | fans_on(Ok) 0 | fans_on(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_off(_) 0 | fans_off(Ok) 0 | fans_off(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 send_hardware_nmi(_) 0 | send_hardware_nmi(Ok) 0 | send_hardware_nmi(Err) 0 read_fpga_regs(_) 0 | read_fpga_regs(Ok) 0 | read_fpga_regs(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) host_sp_comms | +---> drv_gimlet_seq_api::__SEQUENCER_CLIENT_COUNTERS: 4 get_state(_) 4 +---> get_state(Ok) 0 | get_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 set_state(_) 0 | set_state(Ok) 0 | set_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_on(_) 0 | fans_on(Ok) 0 | fans_on(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_off(_) 0 | fans_off(Ok) 0 | fans_off(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 send_hardware_nmi(_) 0 | send_hardware_nmi(Ok) 0 | send_hardware_nmi(Err) 0 read_fpga_regs(_) 0 | read_fpga_regs(Ok) 0 | read_fpga_regs(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) power | +---> drv_gimlet_seq_api::__SEQUENCER_CLIENT_COUNTERS: 67 get_state(_) 67 +---> get_state(Ok) 0 | get_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 set_state(_) 0 | set_state(Ok) 0 | set_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_on(_) 0 | fans_on(Ok) 0 | fans_on(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_off(_) 0 | fans_off(Ok) 0 | fans_off(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 send_hardware_nmi(_) 0 | send_hardware_nmi(Ok) 0 | send_hardware_nmi(Err) 0 read_fpga_regs(_) 0 | read_fpga_regs(Ok) 0 | read_fpga_regs(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) thermal | +---> drv_gimlet_seq_api::__SEQUENCER_CLIENT_COUNTERS: 146 get_state(_) 146 +---> get_state(Ok) 0 | get_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 set_state(_) 0 | set_state(Ok) 0 | set_state(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_on(_) 0 | fans_on(Ok) 0 | fans_on(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 fans_off(_) 0 | fans_off(Ok) 0 | fans_off(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) 0 send_hardware_nmi(_) 0 | send_hardware_nmi(Ok) 0 | send_hardware_nmi(Err) 0 read_fpga_regs(_) 0 | read_fpga_regs(Ok) 0 | read_fpga_regs(Err(_)) 0 | Err(IllegalTransition) 0 | Err(MuxToHostCPUFailed) 0 | Err(MuxToSPFailed) 0 | Err(ReadRegsFailed) 0 | Err(CPUNotPresent) 0 | Err(UnrecognizedCPU) 0 | Err(A1Timeout) 0 | Err(A0TimeoutGroupC) 0 | Err(A0Timeout) 0 | Err(I2cFault) 0 | Err(ServerRestarted) ```