mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-22 04:25:21 +00:00
pci: Allow QWORD read and write to MSI-X table
As mentioned in the PCI specification, MSI-X table supports both DWORD and QWORD accesses: For all accesses to MSI-X Table and MSI-X PBA fields, software must use aligned full DWORD or aligned full QWORD transactions; otherwise, the result is undefined. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
00cdbbc673
commit
edd1279609
@ -56,10 +56,14 @@ impl MsixConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_table(&mut self, offset: u64, data: &mut [u8]) {
|
pub fn read_table(&mut self, offset: u64, data: &mut [u8]) {
|
||||||
assert!(data.len() == 4);
|
assert!((data.len() == 4 || data.len() == 8));
|
||||||
|
|
||||||
let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize;
|
let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize;
|
||||||
let value = match offset % MSIX_TABLE_ENTRIES_MODULO {
|
let modulo_offset = offset % MSIX_TABLE_ENTRIES_MODULO;
|
||||||
|
|
||||||
|
match data.len() {
|
||||||
|
4 => {
|
||||||
|
let value = match modulo_offset {
|
||||||
0x0 => self.table_entries[index].msg_addr_lo,
|
0x0 => self.table_entries[index].msg_addr_lo,
|
||||||
0x4 => self.table_entries[index].msg_addr_hi,
|
0x4 => self.table_entries[index].msg_addr_hi,
|
||||||
0x8 => self.table_entries[index].msg_data,
|
0x8 => self.table_entries[index].msg_data,
|
||||||
@ -71,17 +75,43 @@ impl MsixConfig {
|
|||||||
};
|
};
|
||||||
|
|
||||||
debug!("MSI_R TABLE offset 0x{:x} data 0x{:x}", offset, value);
|
debug!("MSI_R TABLE offset 0x{:x} data 0x{:x}", offset, value);
|
||||||
|
|
||||||
LittleEndian::write_u32(data, value);
|
LittleEndian::write_u32(data, value);
|
||||||
}
|
}
|
||||||
|
8 => {
|
||||||
|
let value = match modulo_offset {
|
||||||
|
0x0 => {
|
||||||
|
(u64::from(self.table_entries[index].msg_addr_hi) << 32)
|
||||||
|
| u64::from(self.table_entries[index].msg_addr_lo)
|
||||||
|
}
|
||||||
|
0x8 => {
|
||||||
|
(u64::from(self.table_entries[index].vector_ctl) << 32)
|
||||||
|
| u64::from(self.table_entries[index].msg_data)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!("invalid offset");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("MSI_R TABLE offset 0x{:x} data 0x{:x}", offset, value);
|
||||||
|
LittleEndian::write_u64(data, value);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!("invalid data length");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_table(&mut self, offset: u64, data: &[u8]) {
|
pub fn write_table(&mut self, offset: u64, data: &[u8]) {
|
||||||
assert!(data.len() == 4);
|
assert!((data.len() == 4 || data.len() == 8));
|
||||||
|
|
||||||
let value = LittleEndian::read_u32(data);
|
|
||||||
|
|
||||||
let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize;
|
let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize;
|
||||||
match offset % MSIX_TABLE_ENTRIES_MODULO {
|
let modulo_offset = offset % MSIX_TABLE_ENTRIES_MODULO;
|
||||||
|
|
||||||
|
match data.len() {
|
||||||
|
4 => {
|
||||||
|
let value = LittleEndian::read_u32(data);
|
||||||
|
match modulo_offset {
|
||||||
0x0 => self.table_entries[index].msg_addr_lo = value,
|
0x0 => self.table_entries[index].msg_addr_lo = value,
|
||||||
0x4 => self.table_entries[index].msg_addr_hi = value,
|
0x4 => self.table_entries[index].msg_addr_hi = value,
|
||||||
0x8 => self.table_entries[index].msg_data = value,
|
0x8 => self.table_entries[index].msg_data = value,
|
||||||
@ -91,6 +121,25 @@ impl MsixConfig {
|
|||||||
|
|
||||||
debug!("MSI_W TABLE offset 0x{:x} data 0x{:x}", offset, value);
|
debug!("MSI_W TABLE offset 0x{:x} data 0x{:x}", offset, value);
|
||||||
}
|
}
|
||||||
|
8 => {
|
||||||
|
let value = LittleEndian::read_u64(data);
|
||||||
|
match modulo_offset {
|
||||||
|
0x0 => {
|
||||||
|
self.table_entries[index].msg_addr_lo = (value & 0xffff_ffffu64) as u32;
|
||||||
|
self.table_entries[index].msg_addr_hi = (value >> 32) as u32;
|
||||||
|
}
|
||||||
|
0x8 => {
|
||||||
|
self.table_entries[index].msg_data = (value & 0xffff_ffffu64) as u32;
|
||||||
|
self.table_entries[index].vector_ctl = (value >> 32) as u32;
|
||||||
|
}
|
||||||
|
_ => error!("invalid offset"),
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("MSI_W TABLE offset 0x{:x} data 0x{:x}", offset, value);
|
||||||
|
}
|
||||||
|
_ => error!("invalid data length"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_pba(&mut self, offset: u64, data: &mut [u8]) {
|
pub fn read_pba(&mut self, offset: u64, data: &mut [u8]) {
|
||||||
assert!((data.len() == 4 || data.len() == 8));
|
assert!((data.len() == 4 || data.len() == 8));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user