use super::super::super::*;
use super::*;
#[test]
fn set_status_clear_acknowledge_rejected() {
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
assert_eq!(dev.device_status, S_ACK);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, VIRTIO_CONFIG_S_DRIVER);
assert_eq!(
dev.device_status, S_ACK,
"writing a value that clears ACKNOWLEDGE must be rejected — \
monotone gate (virtio-v1.2 §3.1.1)",
);
}
#[test]
fn set_status_clear_driver_keeps_ack_rejected() {
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_DRV);
assert_eq!(dev.device_status, S_DRV);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
assert_eq!(
dev.device_status, S_DRV,
"writing ACK alone after advancing to DRIVER must be \
rejected — clears DRIVER bit",
);
}
#[test]
fn set_status_clear_driver_ok_rejected() {
let mut dev = VirtioConsole::new();
init_device(&mut dev);
assert_eq!(dev.device_status, S_OK);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_FEAT);
assert_eq!(
dev.device_status, S_OK,
"writing S_FEAT after S_OK must be rejected — \
clears DRIVER_OK",
);
}
#[test]
fn set_status_idempotent_same_value_no_change() {
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
assert_eq!(dev.device_status, S_ACK);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
assert_eq!(
dev.device_status, S_ACK,
"re-writing the same status must leave device_status \
unchanged — no advance, no regression",
);
}
#[test]
fn set_status_two_bits_at_once_rejected() {
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_DRV);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_OK);
assert_eq!(
dev.device_status, S_DRV,
"advancing two FSM bits at once (FEATURES_OK + DRIVER_OK) \
must be rejected — the FSM advances one bit at a time",
);
}
#[test]
fn set_status_unknown_bit_rejected() {
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
assert_eq!(dev.device_status, S_ACK);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK | 0x10);
assert_eq!(
dev.device_status, S_ACK,
"writing a status with an unrecognised bit (0x10) must \
be rejected — only the defined ACK/DRIVER/FEATURES_OK/\
DRIVER_OK/FAILED transitions are accepted",
);
}
#[test]
fn set_status_failed_accepted_at_every_fsm_state() {
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, VIRTIO_CONFIG_S_FAILED);
assert_eq!(
dev.device_status, VIRTIO_CONFIG_S_FAILED,
"FAILED from status=0 must be accepted",
);
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK | VIRTIO_CONFIG_S_FAILED);
assert_eq!(
dev.device_status,
S_ACK | VIRTIO_CONFIG_S_FAILED,
"FAILED from status=ACK must be accepted (ACK preserved)",
);
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_DRV);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_DRV | VIRTIO_CONFIG_S_FAILED);
assert_eq!(
dev.device_status,
S_DRV | VIRTIO_CONFIG_S_FAILED,
"FAILED from status=DRV must be accepted (DRV preserved)",
);
let mut dev = VirtioConsole::new();
init_device(&mut dev);
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_OK | VIRTIO_CONFIG_S_FAILED);
assert_eq!(
dev.device_status,
S_OK | VIRTIO_CONFIG_S_FAILED,
"FAILED from status=S_OK must be accepted (S_OK preserved)",
);
}
#[test]
fn set_status_failed_plus_unknown_bit_rejected() {
let mut dev = VirtioConsole::new();
write_reg(&mut dev, VIRTIO_MMIO_STATUS, S_ACK);
write_reg(
&mut dev,
VIRTIO_MMIO_STATUS,
S_ACK | VIRTIO_CONFIG_S_FAILED | 0x10,
);
assert_eq!(
dev.device_status, S_ACK,
"FAILED combined with a non-FAILED unknown bit must be \
rejected — the early-accept is gated on FAILED alone",
);
}