Skip to content

Commit 3bededd

Browse files
jstarksBen Hillis
authored andcommitted
vpci: send completion after device (#1500)
Follow the Hyper-V protocol order and send the FDO D0 entry completion message only after the device description has been sent.
1 parent eb93e11 commit 3bededd

File tree

1 file changed

+26
-13
lines changed

1 file changed

+26
-13
lines changed

vm/devices/pci/vpci/src/device.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ enum ProtocolState {
525525

526526
struct ReadyState {
527527
send_device: bool,
528+
send_completion: Option<u64>,
528529
vpci_version: protocol::ProtocolVersion,
529530
}
530531

@@ -566,6 +567,7 @@ impl<T: RingMem> VpciChannelState<T> {
566567
self.state = ProtocolState::Ready(ReadyState {
567568
vpci_version: version,
568569
send_device: false,
570+
send_completion: None,
569571
});
570572
}
571573
} else {
@@ -639,6 +641,10 @@ impl ReadyState {
639641
self.send_child_device(conn, dev).await?;
640642
self.send_device = false;
641643
}
644+
if let Some(transaction_id) = self.send_completion {
645+
conn.send_completion(Some(transaction_id), &protocol::Status::SUCCESS, &[])?;
646+
self.send_completion = None;
647+
}
642648

643649
// Don't pull a packets off the ring until there is space for its completion.
644650
conn.wait_for_completion_space().await?;
@@ -688,8 +694,9 @@ impl ReadyState {
688694
}
689695
PacketData::FdoD0Entry { mmio_start } => {
690696
dev.config_space.map(mmio_start);
691-
conn.send_completion(transaction_id, &protocol::Status::SUCCESS, &[])?;
692697
self.send_device = true;
698+
// Send the completion after the device has been sent.
699+
self.send_completion = transaction_id;
693700
}
694701
PacketData::FdoD0Exit => {
695702
dev.config_space.unmap();
@@ -1055,11 +1062,16 @@ impl VpciConfigSpace {
10551062
}
10561063

10571064
fn map(&mut self, addr: u64) {
1065+
tracing::debug!(addr, "mapping config space");
10581066
self.offset.0.store(addr, Ordering::Relaxed);
10591067
self.control_mmio.map(addr);
10601068
}
10611069

10621070
fn unmap(&mut self) {
1071+
tracing::debug!(
1072+
addr = self.offset.0.load(Ordering::Relaxed),
1073+
"unmapping config space"
1074+
);
10631075
// Note that there may be some current accessors that this will not
10641076
// flush out synchronously. The MMIO implementation in bus.rs must be
10651077
// careful to ignore reads/writes that are not to an expected address.
@@ -1073,7 +1085,7 @@ impl VpciConfigSpace {
10731085
/// PCI Config space offset structure
10741086
#[derive(Debug, Clone, Inspect)]
10751087
#[inspect(transparent)]
1076-
pub struct VpciConfigSpaceOffset(Arc<AtomicU64>);
1088+
pub struct VpciConfigSpaceOffset(#[inspect(hex)] Arc<AtomicU64>);
10771089

10781090
impl VpciConfigSpaceOffset {
10791091
const INVALID: u64 = !0;
@@ -1391,7 +1403,7 @@ mod tests {
13911403
}
13921404
}
13931405

1394-
async fn power_on(&mut self, base_address: u64) {
1406+
async fn initiate_power_on(&mut self, base_address: u64) -> u64 {
13951407
let power_on = protocol::FdoD0Entry {
13961408
message_type: protocol::MessageType::FDO_D0_ENTRY,
13971409
padding: 0,
@@ -1401,15 +1413,7 @@ mod tests {
14011413
self.write_packet(Some(transaction_id), &power_on)
14021414
.await
14031415
.unwrap();
1404-
1405-
let mut pkt_info = ReadPacketInfo::None;
1406-
let status: protocol::Status = self.read_packet(&mut pkt_info).await.unwrap();
1407-
if let ReadPacketInfo::Completion(id) = pkt_info {
1408-
assert_eq!(id, transaction_id);
1409-
assert_eq!(status, protocol::Status::SUCCESS);
1410-
} else {
1411-
panic!("Unexpected D0 (power on) reply");
1412-
}
1416+
transaction_id
14131417
}
14141418

14151419
fn verify_device_relations2(&self, message: &Relations2) {
@@ -1432,7 +1436,7 @@ mod tests {
14321436

14331437
async fn start_device(&mut self, base_address: u64) {
14341438
self.negotiate_version().await;
1435-
self.power_on(base_address).await;
1439+
let transaction_id = self.initiate_power_on(base_address).await;
14361440
let mut pkt_info = ReadPacketInfo::None;
14371441
let relations: Relations2 = self.read_packet(&mut pkt_info).await.unwrap();
14381442
if let ReadPacketInfo::NewTransaction = pkt_info {
@@ -1444,6 +1448,15 @@ mod tests {
14441448
} else {
14451449
panic!("Expecting QueryBusRelations2 message in response to version.");
14461450
}
1451+
1452+
let mut pkt_info = ReadPacketInfo::None;
1453+
let status: protocol::Status = self.read_packet(&mut pkt_info).await.unwrap();
1454+
if let ReadPacketInfo::Completion(id) = pkt_info {
1455+
assert_eq!(id, transaction_id);
1456+
assert_eq!(status, protocol::Status::SUCCESS);
1457+
} else {
1458+
panic!("Unexpected D0 (power on) reply");
1459+
}
14471460
}
14481461

14491462
// returns MSI address and data

0 commit comments

Comments
 (0)