oxidecomputer / idolatry

An experimental IPC interface definition language for Hubris.
Mozilla Public License 2.0
17 stars 11 forks source link

generate counters for client and server IPC operations #41

Closed hawkw closed 8 months ago

hawkw commented 8 months ago

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 of Ok and Err responses, with the Err path including child counters of each variant of the IPC's error type, provided it derives the Count 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 all ClientError variants globally rather than per-IPC, if this is necessary to limit the size of the generated counter table. I've moved several functions into methods on the Generator type and changed the free functions to call those methods with Generator::default() for API compatibility. Unfortunately, this makes the diff kind of unpleasant to review, since it required moving and re-indenting a bunch of code. It probably makes sense to review the diff prior to that change first --- sorry about that.

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