Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ apob = { git = "https://github.com/oxidecomputer/apob", default-features = false
# for the migration.
attest-data = { git = "https://github.com/oxidecomputer/dice-util", default-features = false, version = "0.4.0", rev = "a0811d06c75c757a6e12c91ed6ea81fde137ba43" }
dice-mfg-msgs = { git = "https://github.com/oxidecomputer/dice-util", default-features = false, version = "0.2.1", rev = "a0811d06c75c757a6e12c91ed6ea81fde137ba43" }
gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", default-features = false, features = ["smoltcp"] }
gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", branch = "evan/report-power-state-change-reason", default-features = false, features = ["smoltcp"] }
gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", default-features = false }
gimlet-inspector-protocol = { git = "https://github.com/oxidecomputer/gimlet-inspector-protocol", version = "0.1.0" }
hif = { git = "https://github.com/oxidecomputer/hif", default-features = false }
Expand Down
2 changes: 2 additions & 0 deletions drv/cosmo-seq-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ fixedstr = { path = "../../lib/fixedstr", features = ["microcbor"] }
static-cell = { path = "../../lib/static-cell" }

cfg-if = { workspace = true }
hubpack = { workspace = true }
idol-runtime.workspace = true
num-traits = { workspace = true }
pmbus = { workspace = true }
serde = { workspace = true }
zerocopy = { workspace = true }
zerocopy-derive = { workspace = true }

Expand Down
63 changes: 45 additions & 18 deletions drv/cosmo-seq-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
#![no_main]

use drv_cpu_seq_api::{
PowerState, SeqError as CpuSeqError, StateChangeReason, Transition,
PowerState, PowerStateWithReason, SeqError as CpuSeqError,
StateChangeReason, Transition,
};
use drv_ice40_spi_program as ice40;
use drv_packrat_vpd_loader::{Packrat, read_vpd_and_load_packrat};
Expand Down Expand Up @@ -429,6 +430,8 @@ fn init_front_fpga<S: SpiServer>(
#[allow(unused)]
struct ServerImpl {
state: PowerState,
/// The reason we transitioned to the current state
reason: StateChangeReason,
/// The Hubris tick at which we transitioned to the current state.
since: u64,
jefe: Jefe,
Expand Down Expand Up @@ -466,6 +469,7 @@ impl ServerImpl {

ServerImpl {
state: PowerState::A2,
reason: StateChangeReason::InitialPowerOn,
since: now,
jefe,
sys: Sys::from(SYS.get_task_id()),
Expand All @@ -478,8 +482,11 @@ impl ServerImpl {
}
}

fn get_state_impl(&self) -> PowerState {
self.state
fn get_state_impl(&self) -> PowerStateWithReason {
PowerStateWithReason {
state: self.state,
reason: self.reason,
}
}

/// Logs a set of state registers, returning the state machine states
Expand Down Expand Up @@ -510,18 +517,18 @@ impl ServerImpl {
fn set_state_impl(
&mut self,
state: PowerState,
why: StateChangeReason,
reason: StateChangeReason,
) -> Result<Transition, CpuSeqError> {
let now = sys_get_timer().now;
ringbuf_entry!(Trace::SetState {
prev: Some(self.state),
next: state,
why,
why: reason,
now,
});

use seq_api_status::A0Sm;
match (self.get_state_impl(), state) {
match (self.get_state_impl().state, state) {
(PowerState::A2, PowerState::A0) => {
// Reset edge counters in the sequencer
self.seq.amd_reset_fedges.set_counts(0);
Expand Down Expand Up @@ -698,13 +705,19 @@ impl ServerImpl {
_ => return Err(CpuSeqError::IllegalTransition),
}

self.set_state_internal(state, now);
self.set_state_internal(state, reason, now);
Ok(Transition::Changed)
}

/// Updates our internal `state` and the global state in `jefe`
fn set_state_internal(&mut self, state: PowerState, now: u64) {
fn set_state_internal(
&mut self,
state: PowerState,
reason: StateChangeReason,
now: u64,
) {
self.state = state;
self.reason = reason;
self.since = now;
self.jefe.set_state(state as u32);
self.poke_timer();
Expand Down Expand Up @@ -970,36 +983,42 @@ impl ServerImpl {
// host_sp_comms will be notified of this change and will
// call back into this task to reboot the system (going to
// A2 then back into A0)
let next = PowerState::A0Reset;
let reason = StateChangeReason::CpuReset;
ringbuf_entry!(Trace::SetState {
prev: Some(self.state),
next: PowerState::A0Reset,
why: StateChangeReason::CpuReset,
next,
why: reason,
now,
});
self.set_state_internal(PowerState::A0Reset, now);
self.set_state_internal(next, reason, now);
}
InternalAction::NicMapo => {
// Presumably we are in A0+HP, so send us back to A0 so that the
// thermal loop will stop trying to talk to the NIC, and hope
// the host resequences it.
let next = PowerState::A0;
let reason = StateChangeReason::NicMapo;
ringbuf_entry!(Trace::SetState {
prev: Some(self.state),
next: PowerState::A0,
why: StateChangeReason::NicMapo,
next,
why: reason,
now,
});
self.set_state_internal(PowerState::A0, now);
self.set_state_internal(next, reason, now);
}
InternalAction::ThermTrip => {
// This is a terminal state; we set our state to `A0Thermtrip`
// but do not expect any other task to take action right now
let next = PowerState::A0Thermtrip;
let reason = StateChangeReason::Overheat;
ringbuf_entry!(Trace::SetState {
prev: Some(self.state),
next: PowerState::A0Thermtrip,
why: StateChangeReason::Overheat,
next,
why: reason,
now,
});
self.set_state_internal(PowerState::A0Thermtrip, now);
self.set_state_internal(next, reason, now);
}
InternalAction::Mapo => {
// This is a terminal state (for now)
Expand Down Expand Up @@ -1036,6 +1055,14 @@ impl idl::InOrderSequencerImpl for ServerImpl {
&mut self,
_: &RecvMessage,
) -> Result<PowerState, RequestError<core::convert::Infallible>> {
Ok(self.get_state_impl().state)
}

fn get_state_with_reason(
&mut self,
_: &RecvMessage,
) -> Result<PowerStateWithReason, RequestError<core::convert::Infallible>>
{
Ok(self.get_state_impl())
}

Expand Down Expand Up @@ -1291,7 +1318,7 @@ static HOST_CPU_REFDES: ereports::cpu::HostCpuRefdes =
////////////////////////////////////////////////////////////////////////////////

mod idl {
use drv_cpu_seq_api::StateChangeReason;
use drv_cpu_seq_api::{PowerStateWithReason, StateChangeReason};
include!(concat!(env!("OUT_DIR"), "/server_stub.rs"));
}

Expand Down
2 changes: 2 additions & 0 deletions drv/cpu-power-state/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ zerocopy-derive = { workspace = true }
num-traits = { workspace = true }
counters = { path = "../../lib/counters", features = ["derive"] }
microcbor = { path = "../../lib/microcbor", optional = true }
hubpack = { workspace = true }
serde = { workspace = true }

[lib]
test = false
Expand Down
5 changes: 5 additions & 0 deletions drv/cpu-power-state/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#![no_std]

use hubpack::SerializedSize;
use serde::{Deserialize, Serialize};
use userlib::FromPrimitive;
use zerocopy::{Immutable, IntoBytes, KnownLayout};

Expand All @@ -21,6 +23,9 @@ use zerocopy::{Immutable, IntoBytes, KnownLayout};
Immutable,
KnownLayout,
counters::Count,
Deserialize,
Serialize,
SerializedSize,
)]
#[cfg_attr(feature = "microcbor", derive(microcbor::Encode))]
#[repr(u8)]
Expand Down
2 changes: 2 additions & 0 deletions drv/cpu-seq-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ version = "0.1.0"
edition = "2024"

[dependencies]
hubpack.workspace = true
idol-runtime = { workspace = true }
num-traits.workspace = true
serde.workspace = true
zerocopy.workspace = true
zerocopy-derive.workspace = true

Expand Down
23 changes: 23 additions & 0 deletions drv/cpu-seq-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

use counters::Count;
use derive_idol_err::IdolError;
use hubpack::SerializedSize;
use serde::{Deserialize, Serialize};
use userlib::{FromPrimitive, sys_send};
use zerocopy::{Immutable, IntoBytes, KnownLayout};

Expand Down Expand Up @@ -43,6 +45,9 @@ pub enum SeqError {
Immutable,
KnownLayout,
Count,
SerializedSize,
Serialize,
Deserialize,
)]
#[repr(u8)]
pub enum StateChangeReason {
Expand Down Expand Up @@ -81,6 +86,24 @@ pub enum StateChangeReason {
Unknown,
}

#[derive(
Copy,
Clone,
Debug,
Eq,
PartialEq,
IntoBytes,
Immutable,
KnownLayout,
Deserialize,
Serialize,
SerializedSize,
)]
pub struct PowerStateWithReason {
pub state: PowerState,
pub reason: StateChangeReason,
}
Comment on lines +102 to +105
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we are adding a new message for this anyway, i wonder if it's worth also including the since timestamp (the hubris uptime, in milliseconds, at which we transitioned to this state), and maybe also the delta between that and the current uptime? it's not strictly necessary just to solve the problem of "want to know why power state changed" but feels like a handy thing to throw in, and it's just 8 bytes in what's going to be a pretty tiny UDP datagram...


/// Indicates the result of a power state transition.
#[derive(
Copy,
Expand Down
Loading
Loading