Skip to content

Commit

Permalink
SP reset watchdog (#1707)
Browse files Browse the repository at this point in the history
An SP update has one fundamental requirement: it has to allow for future
updates.

This is not guaranteed: a sufficiently broken SP image could fail to
bring up `net` or `control-plane-agent`, which would require physical
intervention to reflash (not ideal in a rack!).

In #1695, we discuss a
strategy for automatically rolling back updates, using the RoT as a
watchdog. This PR adds the tools to implement that strategy:

- New SP-RoT messages to enable and disable a "reset into alternate
  slot" watchdog timer
- RoT implementation of that watchdog
- MGS plumbing (along with management-gateway-service#216) to
  accept these commands over the network
  • Loading branch information
mkeeter authored Apr 16, 2024
1 parent 5dabf67 commit 410fe72
Show file tree
Hide file tree
Showing 20 changed files with 501 additions and 108 deletions.
27 changes: 14 additions & 13 deletions 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 @@ -34,7 +34,7 @@ anyhow = { version = "1.0.31", default-features = false, features = ["std"] }
arrayvec = { version = "0.7.4", default-features = false }
atty = { version = "0.2", default-features = false }
bitfield = { version = "0.13", default-features = false }
bitflags = { version = "2.4.1", default-features = false }
bitflags = { version = "2.5.0", default-features = false }
bstringify = { version = "0.1.2", default-features = false }
byteorder = { version = "1.3.4", default-features = false }
cargo_metadata = { version = "0.12.0", default-features = false }
Expand Down
9 changes: 5 additions & 4 deletions app/oxide-rot-1/app-dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,14 @@ task-slots = ["syscon_driver"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 48608, ram = 32768}
max-sizes = {flash = 51168, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
features = ["spi0", "sp-ctrl"]
start = true
notifications = ["spi-irq"]
interrupts = {"flexcomm8.hs_spi" = "spi-irq"}
stacksize = 16384
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest"]
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest", "swd"]

[tasks.sprot.config]
pins = [
Expand All @@ -110,7 +110,7 @@ uses = ["flexcomm5", "iocon"]
start = true
stacksize = 1000
task-slots = ["gpio_driver", "syscon_driver"]
notifications = ["spi-irq"]
notifications = ["spi-irq", "timer"]
interrupts = {"flexcomm5.irq" = "spi-irq"}

[tasks.swd.config]
Expand All @@ -132,6 +132,7 @@ pins = [
# SCK
{ pin = { port = 0, pin = 7 }, alt = 3 },
{ name = "SP_TO_ROT_JTAG_DETECT_L", pin = { port = 0, pin = 20 }, alt = 0, direction = "input" },
{ name = "ROT_TO_SP_RESET_L", pin = { port = 0, pin = 13 }, alt = 0, value = true, direction = "output", opendrain = "opendrain" },
]
spi_num = 5

Expand Down
7 changes: 4 additions & 3 deletions app/oxide-rot-1/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ task-slots = ["syscon_driver"]
name = "drv-lpc55-sprot-server"
priority = 6
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
features = ["spi0", "sp-ctrl"]
start = true
notifications = ["spi-irq"]
interrupts = {"flexcomm8.hs_spi" = "spi-irq"}
stacksize = 16384
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest"]
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest", "swd"]

[tasks.sprot.config]
pins = [
Expand All @@ -100,7 +100,7 @@ uses = ["flexcomm5", "iocon"]
start = true
stacksize = 1000
task-slots = ["gpio_driver", "syscon_driver"]
notifications = ["spi-irq"]
notifications = ["spi-irq", "timer"]
interrupts = {"flexcomm5.irq" = "spi-irq"}

[tasks.swd.config]
Expand All @@ -122,6 +122,7 @@ pins = [
# SCK
{ pin = { port = 0, pin = 7 }, alt = 3 },
{ name = "SP_TO_ROT_JTAG_DETECT_L", pin = { port = 0, pin = 20 }, alt = 0, direction = "input" },
{ name = "ROT_TO_SP_RESET_L", pin = { port = 0, pin = 13 }, alt = 0, value = true, direction = "output", opendrain = "opendrain" },
]
spi_num = 5

Expand Down
59 changes: 4 additions & 55 deletions app/rot-carrier/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,14 @@ task-slots = ["syscon_driver"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 48608, ram = 32768}
max-sizes = {flash = 49728, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
start = true
notifications = ["spi-irq"]
interrupts = {"flexcomm8.hs_spi" = "spi-irq"}
stacksize = 16384
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest"]
task-slots = ["gpio_driver", "syscon_driver", "update_server", "attest"]

[tasks.sprot.config]
pins = [
Expand All @@ -133,47 +133,6 @@ pins = [
{ name = "SP_RESET", pin = { port = 0, pin = 9}, alt = 0, direction = "input"},
]

[tasks.swd]
name = "drv-lpc55-swd"
priority = 4
max-sizes = {flash = 16384, ram = 4096}
uses = ["flexcomm3", "iocon"]
start = true
stacksize = 1000
notifications = ["spi-irq"]
task-slots = ["gpio_driver", "syscon_driver"]
interrupts = {"flexcomm3.irq" = "spi-irq"}

[tasks.swd.config]
# MOSI = PIO0_3
# MISO = PIO0_2

# Out = MOSI on, MISO off
out_cfg = [
{ pin = { port = 0, pin = 3 }, alt = 1 },
{ pin = { port = 0, pin = 2 }, alt = 0, mode = "pulldown" },
]
# In = MISO on, MOSI off
in_cfg = [
{ pin = { port = 0, pin = 2 }, alt = 1 },
{ pin = { port = 0, pin = 3 }, alt = 0, mode = "pulldown" },
]
pins = [
# SCK
{ pin = { port = 0, pin = 6 }, alt = 1 },
# CS, not strictly necessary but handy for debugging
# { pin = {port = 0, pin = 20}, alt = 1},
]
spi_num = 3

[tasks.dumper]
name = "task-dumper"
priority = 5
max-sizes = {flash = 16384, ram = 4096}
start = true
stacksize = 2600
task-slots = ["swd"]

[tasks.pong]
name = "task-pong"
priority = 7
Expand All @@ -185,21 +144,11 @@ notifications = ["timer"]
[tasks.hiffy]
name = "task-hiffy"
priority = 6
features = ["lpc55", "gpio", "spctrl", "spi"]
features = ["lpc55", "gpio", "spi"]
max-sizes = {flash = 32768, ram = 16384 }
stacksize = 2048
start = true
task-slots = ["gpio_driver", "swd", "update_server"]

[tasks.sp_measure]
name = "task-sp-measure"
priority = 6
max-sizes = {flash = 131072, ram = 8192}
task-slots = ["swd"]
stacksize = 2048

[tasks.sp_measure.config]
binary_path = "../../target/gemini-bu/dist/final.bin"
task-slots = ["gpio_driver", "update_server"]

[tasks.attest]
name = "task-attest"
Expand Down
17 changes: 17 additions & 0 deletions build/lpc55pins/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ pub struct PinConfig {
digimode: Digimode,
#[serde(default)]
opendrain: Opendrain,

direction: Option<Direction>,
value: Option<bool>,
name: Option<String>,
}

Expand Down Expand Up @@ -155,6 +157,21 @@ pub fn codegen(pins: Vec<PinConfig>) -> Result<()> {
writeln!(&mut file, "{}", p.to_token_stream())?;
writeln!(&mut file, ");")?;

// Output pins can specify their value, which is set before configuring
// their output mode (to avoid glitching).
if let Some(v) = p.value {
assert!(
matches!(p.direction, Some(Direction::Output)),
"can only set value for output pins"
);
writeln!(&mut file, "iocon.set_val(")?;
writeln!(&mut file, "{}", p.pin.to_token_stream())?;
writeln!(
&mut file,
"{});",
if v { "Value::One" } else { "Value::Zero" }
)?;
}
match p.direction {
None => (),
Some(d) => {
Expand Down
5 changes: 4 additions & 1 deletion drv/lpc55-sprot-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@ drv-lpc55-syscon-api = { path = "../lpc55-syscon-api" }
drv-lpc55-update-api = { path = "../lpc55-update-api" }
drv-sprot-api = { path = "../sprot-api" }
drv-update-api = { path = "../update-api" }
dumper-api = { path = "../../task/dumper-api" }
lpc55_romapi = { path = "../../lib/lpc55-romapi" }
ringbuf = { path = "../../lib/ringbuf" }
static-cell = { path = "../../lib/static-cell" }
task-jefe-api = { path = "../../task/jefe-api" }
userlib = { path = "../../sys/userlib" }
lpc55-rom-data = { path = "../../lib/lpc55-rom-data" }

drv-sp-ctrl-api = { path = "../sp-ctrl-api", optional = true }
dumper-api = { path = "../../task/dumper-api", optional = true }

[build-dependencies]
build-lpc55pins = { path = "../../build/lpc55pins" }
build-util = { path = "../../build/util" }
Expand All @@ -40,6 +42,7 @@ idol = { workspace = true }
[features]
spi0 = []
no-ipc-counters = ["idol/no-counters"]
sp-ctrl = ["drv-sp-ctrl-api", "dumper-api"]

# This section is here to discourage RLS/rust-analyzer from doing test builds,
# since test builds don't work for cross compilation.
Expand Down
Loading

0 comments on commit 410fe72

Please sign in to comment.