Skip to content

Commit a2bc333

Browse files
committed
Launch Katana asynchronously via VM control channel
1 parent ec7b3cb commit a2bc333

File tree

3 files changed

+341
-68
lines changed

3 files changed

+341
-68
lines changed

misc/AMDSEV/README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ If `--katana` is not provided, `build.sh` prompts for confirmation (`y/N`) befor
4040
| `build-kernel.sh` | Downloads and extracts Ubuntu kernel (`vmlinuz`) |
4141
| `build-initrd.sh` | Creates minimal initrd with busybox, SEV-SNP modules, and katana |
4242
| `build-config` | Pinned versions and checksums for reproducible builds |
43-
| `start-vm.sh` | Starts a TEE VM with SEV-SNP enabled using QEMU |
43+
| `start-vm.sh` | Starts a TEE VM with SEV-SNP and launches Katana asynchronously |
4444

4545
## SNP Tools
4646

@@ -93,8 +93,11 @@ qemu-system-x86_64 \
9393
# Initial ramdisk containing katana (measured when kernel-hashes=on)
9494
-initrd output/qemu/initrd.img \
9595
# Kernel command line (measured when kernel-hashes=on)
96-
# katana.args passes arguments to katana via init script
97-
-append "console=ttyS0 katana.args=--http.addr,0.0.0.0,--http.port,5050,--tee.provider,sev-snp" \
96+
-append "console=ttyS0" \
97+
# Katana control channel (used to start Katana asynchronously after boot)
98+
-device virtio-serial-pci,id=virtio-serial0 \
99+
-chardev socket,id=katanactl,path=/tmp/katana-control.sock,server=on,wait=off \
100+
-device virtserialport,chardev=katanactl,name=org.katana.control.0 \
98101
..
99102
```
100103

@@ -108,11 +111,16 @@ sudo ./misc/AMDSEV/start-vm.sh
108111

109112
# Or specify a custom boot components directory
110113
sudo ./misc/AMDSEV/start-vm.sh /path/to/boot-components
114+
115+
# Or customize Katana runtime flags (comma-separated)
116+
sudo ./misc/AMDSEV/start-vm.sh --katana-args "--http.addr,0.0.0.0,--http.port,5050,--tee.provider,sev-snp,--dev"
111117
```
112118

113119
The script:
114120
- Starts QEMU with SEV-SNP confidential computing enabled
115121
- Uses direct kernel boot with kernel-hashes=on for attestation
122+
- Keeps kernel cmdline stable (`console=ttyS0`) for deterministic measurement
123+
- Starts Katana asynchronously via virtio-serial control channel
116124
- Forwards RPC port 5050 to host port 15051
117125
- Outputs serial log to a temp file and follows it
118126

@@ -129,7 +137,7 @@ cargo build -p snp-tools
129137
--ovmf output/qemu/OVMF.fd \
130138
--kernel output/qemu/vmlinuz \
131139
--initrd output/qemu/initrd.img \
132-
--append "console=ttyS0 katana.args=--http.addr,0.0.0.0,--http.port,5050,--tee.provider,sev-snp" \
140+
--append "console=ttyS0" \
133141
--vcpus 1 \
134142
--cpu epyc-v4 \
135143
--vmm qemu \

misc/AMDSEV/build-initrd.sh

Lines changed: 109 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ log() { echo "[init] $*"; }
293293
KATANA_PID=""
294294
KATANA_DB_DIR="/mnt/data/katana-db"
295295
SHUTTING_DOWN=0
296+
KATANA_EXIT_CODE="never"
297+
CONTROL_PORT_NAME="org.katana.control.0"
298+
CONTROL_PORT_LINK="/dev/virtio-ports/org.katana.control.0"
296299
297300
fatal_boot() {
298301
log "ERROR: $*"
@@ -303,6 +306,90 @@ fatal_boot() {
303306
done
304307
}
305308
309+
refresh_katana_state() {
310+
if [ -n "$KATANA_PID" ] && ! kill -0 "$KATANA_PID" 2>/dev/null; then
311+
if wait "$KATANA_PID"; then
312+
KATANA_EXIT_CODE=0
313+
else
314+
KATANA_EXIT_CODE=$?
315+
fi
316+
log "Katana exited with code $KATANA_EXIT_CODE"
317+
KATANA_PID=""
318+
fi
319+
}
320+
321+
respond_control() {
322+
printf '%s\n' "$1" >&3 2>/dev/null || true
323+
}
324+
325+
resolve_control_port() {
326+
mkdir -p /dev/virtio-ports
327+
for name_file in /sys/class/virtio-ports/*/name; do
328+
[ -f "$name_file" ] || continue
329+
330+
PORT_NAME_VALUE="$(cat "$name_file" 2>/dev/null || true)"
331+
if [ "$PORT_NAME_VALUE" != "$CONTROL_PORT_NAME" ]; then
332+
continue
333+
fi
334+
335+
PORT_DIR="${name_file%/name}"
336+
PORT_DEV="/dev/${PORT_DIR##*/}"
337+
if [ -e "$PORT_DEV" ]; then
338+
ln -sf "$PORT_DEV" "$CONTROL_PORT_LINK"
339+
echo "$CONTROL_PORT_LINK"
340+
return 0
341+
fi
342+
done
343+
return 1
344+
}
345+
346+
handle_control_command() {
347+
RAW_CMD="$1"
348+
CMD="${RAW_CMD%% *}"
349+
CMD_PAYLOAD=""
350+
if [ "$CMD" != "$RAW_CMD" ]; then
351+
CMD_PAYLOAD="${RAW_CMD#* }"
352+
fi
353+
354+
case "$CMD" in
355+
start)
356+
refresh_katana_state
357+
if [ -n "$KATANA_PID" ] && kill -0 "$KATANA_PID" 2>/dev/null; then
358+
respond_control "err already-running pid=$KATANA_PID"
359+
return 0
360+
fi
361+
362+
KATANA_ARGS=""
363+
if [ -n "$CMD_PAYLOAD" ]; then
364+
KATANA_ARGS="$(echo "$CMD_PAYLOAD" | tr ',' ' ')"
365+
fi
366+
367+
log "Starting katana asynchronously..."
368+
# shellcheck disable=SC2086
369+
/bin/katana --db-dir="$KATANA_DB_DIR" $KATANA_ARGS &
370+
KATANA_PID=$!
371+
KATANA_EXIT_CODE="running"
372+
respond_control "ok started pid=$KATANA_PID"
373+
;;
374+
375+
status)
376+
refresh_katana_state
377+
if [ -n "$KATANA_PID" ] && kill -0 "$KATANA_PID" 2>/dev/null; then
378+
respond_control "running pid=$KATANA_PID"
379+
else
380+
respond_control "stopped exit=$KATANA_EXIT_CODE"
381+
fi
382+
;;
383+
384+
"")
385+
;;
386+
387+
*)
388+
respond_control "err unknown-command"
389+
;;
390+
esac
391+
}
392+
306393
shutdown_handler() {
307394
if [ "$SHUTTING_DOWN" -eq 1 ]; then
308395
return 0
@@ -404,15 +491,6 @@ else
404491
log "WARNING: eth0 interface not found; skipping static network setup"
405492
fi
406493
407-
# Parse katana args from cmdline
408-
CMDLINE="$(cat /proc/cmdline 2>/dev/null || true)"
409-
KATANA_ARGS=""
410-
for tok in $CMDLINE; do
411-
case "$tok" in
412-
katana.args=*) KATANA_ARGS="$(echo "${tok#katana.args=}" | tr ',' ' ')" ;;
413-
esac
414-
done
415-
416494
# Require persistent storage at /dev/sda
417495
if [ ! -b /dev/sda ]; then
418496
fatal_boot "required storage device /dev/sda not found"
@@ -426,22 +504,30 @@ fi
426504
mkdir -p "$KATANA_DB_DIR"
427505
log "Storage mounted at /mnt/data"
428506
429-
log "Starting katana..."
430-
# shellcheck disable=SC2086
431-
/bin/katana --db-dir="$KATANA_DB_DIR" $KATANA_ARGS &
432-
KATANA_PID=$!
433-
log "Katana started with PID $KATANA_PID"
434-
435-
if wait "$KATANA_PID"; then
436-
EXIT_CODE=0
437-
else
438-
EXIT_CODE=$?
439-
fi
440-
log "Katana exited with code $EXIT_CODE"
507+
# Start async control loop for Katana startup/status commands.
508+
log "Waiting for control channel ($CONTROL_PORT_NAME)..."
509+
CONTROL_PORT=""
510+
while [ -z "$CONTROL_PORT" ]; do
511+
CONTROL_PORT="$(resolve_control_port || true)"
512+
[ -n "$CONTROL_PORT" ] || sleep 1
513+
done
514+
log "Control channel ready: $CONTROL_PORT"
441515
442-
# PID 1 must stay alive unless explicitly powered off.
443516
while true; do
444-
sleep 60
517+
refresh_katana_state
518+
519+
if ! exec 3<>"$CONTROL_PORT"; then
520+
log "WARNING: failed to open control channel, retrying..."
521+
sleep 1
522+
continue
523+
fi
524+
525+
while IFS= read -r CONTROL_CMD <&3; do
526+
handle_control_command "$CONTROL_CMD"
527+
done
528+
529+
exec 3>&- 3<&-
530+
sleep 1
445531
done
446532
INIT_EOF
447533

0 commit comments

Comments
 (0)