1 use crate::include::bindings::bindings::{ 2 initial_mm, mm_map, mm_struct, pci_read_config, pci_write_config, VM_DONTCOPY, VM_IO, 3 }; 4 use crate::mm::mmio_buddy::MMIO_POOL; 5 use crate::{kdebug, kerror, kwarn}; 6 use bitflags::bitflags; 7 use core::{ 8 convert::TryFrom, 9 fmt::{self, Display, Formatter}, 10 }; 11 //Bar0寄存器的offset 12 const BAR0_OFFSET: u8 = 0x10; 13 //Status、Command寄存器的offset 14 const STATUS_COMMAND_OFFSET: u8 = 0x04; 15 /// ID for vendor-specific PCI capabilities.(Virtio Capabilities) 16 pub const PCI_CAP_ID_VNDR: u8 = 0x09; 17 18 bitflags! { 19 /// The status register in PCI configuration space. 20 pub struct Status: u16 { 21 // Bits 0-2 are reserved. 22 /// The state of the device's INTx# signal. 23 const INTERRUPT_STATUS = 1 << 3; 24 /// The device has a linked list of capabilities. 25 const CAPABILITIES_LIST = 1 << 4; 26 /// The device is capabile of running at 66 MHz rather than 33 MHz. 27 const MHZ_66_CAPABLE = 1 << 5; 28 // Bit 6 is reserved. 29 /// The device can accept fast back-to-back transactions not from the same agent. 30 const FAST_BACK_TO_BACK_CAPABLE = 1 << 7; 31 /// The bus agent observed a parity error (if parity error handling is enabled). 32 const MASTER_DATA_PARITY_ERROR = 1 << 8; 33 // Bits 9-10 are DEVSEL timing. 34 /// A target device terminated a transaction with target-abort. 35 const SIGNALED_TARGET_ABORT = 1 << 11; 36 /// A master device transaction was terminated with target-abort. 37 const RECEIVED_TARGET_ABORT = 1 << 12; 38 /// A master device transaction was terminated with master-abort. 39 const RECEIVED_MASTER_ABORT = 1 << 13; 40 /// A device asserts SERR#. 41 const SIGNALED_SYSTEM_ERROR = 1 << 14; 42 /// The device detects a parity error, even if parity error handling is disabled. 43 const DETECTED_PARITY_ERROR = 1 << 15; 44 } 45 } 46 47 bitflags! { 48 /// The command register in PCI configuration space. 49 pub struct CommandRegister: u16 { 50 /// The device can respond to I/O Space accesses. 51 const IO_SPACE = 1 << 0; 52 /// The device can respond to Memory Space accesses. 53 const MEMORY_SPACE = 1 << 1; 54 /// The device can behave as a bus master. 55 const BUS_MASTER = 1 << 2; 56 /// The device can monitor Special Cycle operations. 57 const SPECIAL_CYCLES = 1 << 3; 58 /// The device can generate the Memory Write and Invalidate command. 59 const MEMORY_WRITE_AND_INVALIDATE_ENABLE = 1 << 4; 60 /// The device will snoop palette register data. 61 const VGA_PALETTE_SNOOP = 1 << 5; 62 /// The device should take its normal action when a parity error is detected. 63 const PARITY_ERROR_RESPONSE = 1 << 6; 64 // Bit 7 is reserved. 65 /// The SERR# driver is enabled. 66 const SERR_ENABLE = 1 << 8; 67 /// The device is allowed to generate fast back-to-back transactions. 68 const FAST_BACK_TO_BACK_ENABLE = 1 << 9; 69 /// Assertion of the device's INTx# signal is disabled. 70 const INTERRUPT_DISABLE = 1 << 10; 71 } 72 } 73 74 /// Gets the capabilities 'pointer' for the device function, if any. 75 ///@brief 获取第一个capability 的offset 76 ///@param device_function PCI设备的唯一标识 77 ///@return Option<u8> offset 78 pub fn capabilities_offset(device_function: DeviceFunction) -> Option<u8> { 79 let status: Status = unsafe { 80 let temp = pci_read_config( 81 device_function.bus, 82 device_function.device, 83 device_function.function, 84 STATUS_COMMAND_OFFSET, 85 ); 86 Status::from_bits_truncate((temp >> 16) as u16) 87 }; 88 if status.contains(Status::CAPABILITIES_LIST) { 89 let cap_pointer = unsafe { 90 let temp = pci_read_config( 91 device_function.bus, 92 device_function.device, 93 device_function.function, 94 0x34, 95 ); 96 temp as u8 & 0xFC 97 }; 98 Some(cap_pointer) 99 } else { 100 None 101 } 102 } 103 /// An identifier for a PCI bus, device and function. 104 /// PCI设备的唯一标识 105 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 106 pub struct DeviceFunction { 107 /// The PCI bus number, between 0 and 255. 108 pub bus: u8, 109 /// The device number on the bus, between 0 and 31. 110 pub device: u8, 111 /// The function number of the device, between 0 and 7. 112 pub function: u8, 113 } 114 ///PCI的Error 115 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 116 pub enum PciError { 117 /// The device reported an invalid BAR type. 118 InvalidBarType, 119 CreateMmioError, 120 } 121 ///实现PciError的Display trait,使其可以直接输出 122 impl Display for PciError { 123 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 124 match self { 125 Self::InvalidBarType => write!(f, "Invalid PCI BAR type."), 126 Self::CreateMmioError => write!(f, "Error occurred while creating mmio"), 127 } 128 } 129 } 130 131 impl DeviceFunction { 132 /// Returns whether the device and function numbers are valid, i.e. the device is between 0 and 133 /// 31, and the function is between 0 and 7. 134 /// @brief 检测DeviceFunction实例是否有效 135 /// @param self 136 /// @return bool 是否有效 137 #[allow(dead_code)] 138 pub fn valid(&self) -> bool { 139 self.device < 32 && self.function < 8 140 } 141 } 142 ///实现DeviceFunction的Display trait,使其可以直接输出 143 impl Display for DeviceFunction { 144 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 145 write!(f, "{:02x}:{:02x}.{}", self.bus, self.device, self.function) 146 } 147 } 148 /// The location allowed for a memory BAR. 149 /// memory BAR的三种情况 150 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 151 pub enum MemoryBarType { 152 /// The BAR has a 32-bit address and can be mapped anywhere in 32-bit address space. 153 Width32, 154 /// The BAR must be mapped below 1MiB. 155 Below1MiB, 156 /// The BAR has a 64-bit address and can be mapped anywhere in 64-bit address space. 157 Width64, 158 } 159 ///实现MemoryBarType与u8的类型转换 160 impl From<MemoryBarType> for u8 { 161 fn from(bar_type: MemoryBarType) -> Self { 162 match bar_type { 163 MemoryBarType::Width32 => 0, 164 MemoryBarType::Below1MiB => 1, 165 MemoryBarType::Width64 => 2, 166 } 167 } 168 } 169 ///实现MemoryBarType与u8的类型转换 170 impl TryFrom<u8> for MemoryBarType { 171 type Error = PciError; 172 fn try_from(value: u8) -> Result<Self, Self::Error> { 173 match value { 174 0 => Ok(Self::Width32), 175 1 => Ok(Self::Below1MiB), 176 2 => Ok(Self::Width64), 177 _ => Err(PciError::InvalidBarType), 178 } 179 } 180 } 181 182 /// Information about a PCI Base Address Register. 183 /// BAR的三种类型 Memory/IO/Unused 184 #[derive(Clone, Debug, Eq, PartialEq)] 185 pub enum BarInfo { 186 /// The BAR is for a memory region. 187 Memory { 188 /// The size of the BAR address and where it can be located. 189 address_type: MemoryBarType, 190 /// If true, then reading from the region doesn't have side effects. The CPU may cache reads 191 /// and merge repeated stores. 192 prefetchable: bool, 193 /// The memory address, always 16-byte aligned. 194 address: u64, 195 /// The size of the BAR in bytes. 196 size: u32, 197 /// The virtaddress for a memory bar(mapped). 198 virtaddress: u64, 199 }, 200 /// The BAR is for an I/O region. 201 IO { 202 /// The I/O address, always 4-byte aligned. 203 address: u32, 204 /// The size of the BAR in bytes. 205 size: u32, 206 }, 207 Unused, 208 } 209 210 impl BarInfo { 211 /// Returns the address and size of this BAR if it is a memory bar, or `None` if it is an IO 212 /// BAR. 213 ///@brief 得到某个bar的memory_address与size(前提是他的类型为Memory Bar) 214 ///@param self 215 ///@return Option<(u64, u32) 是Memory Bar返回内存地址与大小,不是则返回None 216 pub fn memory_address_size(&self) -> Option<(u64, u32)> { 217 if let Self::Memory { address, size, .. } = self { 218 Some((*address, *size)) 219 } else { 220 None 221 } 222 } 223 ///@brief 得到某个bar的virtaddress(前提是他的类型为Memory Bar) 224 ///@param self 225 ///@return Option<(u64) 是Memory Bar返回映射的虚拟地址,不是则返回None 226 pub fn virtual_address(&self) -> Option<u64> { 227 if let Self::Memory { virtaddress, .. } = self { 228 Some(*virtaddress) 229 } else { 230 None 231 } 232 } 233 } 234 ///实现BarInfo的Display trait,使其可以直接输出 235 impl Display for BarInfo { 236 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 237 match self { 238 Self::Memory { 239 address_type, 240 prefetchable, 241 address, 242 size, 243 virtaddress, 244 } => write!( 245 f, 246 "Memory space at {:#010x}, size {}, type {:?}, prefetchable {},mapped at {:#x}", 247 address, size, address_type, prefetchable, virtaddress 248 ), 249 Self::IO { address, size } => { 250 write!(f, "I/O space at {:#010x}, size {}", address, size) 251 } 252 Self::Unused => { 253 write!(f, "Unused bar") 254 } 255 } 256 } 257 } 258 ///一个PCI设备有6个BAR寄存器,PciDeviceBar存储其全部信息 259 #[derive(Clone, Debug, Eq, PartialEq)] 260 pub struct PciDeviceBar { 261 bar0: BarInfo, 262 bar1: BarInfo, 263 bar2: BarInfo, 264 bar3: BarInfo, 265 bar4: BarInfo, 266 bar5: BarInfo, 267 } 268 269 impl PciDeviceBar { 270 ///@brief 得到某个bar的barinfo 271 ///@param self ,bar_index(0-5) 272 ///@return Result<&BarInfo, PciError> bar_index在0-5则返回对应的bar_info结构体,超出范围则返回错误 273 pub fn get_bar(&self, bar_index: u8) -> Result<&BarInfo, PciError> { 274 match bar_index { 275 0 => Ok(&self.bar0), 276 1 => Ok(&self.bar1), 277 2 => Ok(&self.bar2), 278 3 => Ok(&self.bar3), 279 4 => Ok(&self.bar4), 280 _ => Err(PciError::InvalidBarType), 281 } 282 } 283 } 284 ///实现PciDeviceBar的Display trait,使其可以直接输出 285 impl Display for PciDeviceBar { 286 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 287 write!( 288 f, 289 "\r\nBar0:{}\r\n Bar1:{}\r\n Bar2:{}\r\n Bar3:{}\r\nBar4:{}\r\nBar5:{}", 290 self.bar0, self.bar1, self.bar2, self.bar3, self.bar4, self.bar5 291 ) 292 } 293 } 294 ///实现PciDeviceBar的Default trait,使其可以简单初始化 295 impl Default for PciDeviceBar { 296 fn default() -> Self { 297 PciDeviceBar { 298 bar0: BarInfo::Unused, 299 bar1: BarInfo::Unused, 300 bar2: BarInfo::Unused, 301 bar3: BarInfo::Unused, 302 bar4: BarInfo::Unused, 303 bar5: BarInfo::Unused, 304 } 305 } 306 } 307 308 ///@brief 将某个pci设备的bar全部初始化,memory 309 ///@param self ,device_function PCI设备的唯一标识符 310 ///@return Result<PciDeviceBar, PciError> 成功则返回对应的PciDeviceBar结构体,失败则返回错误类型 311 pub fn pci_bar_init(device_function: DeviceFunction) -> Result<PciDeviceBar, PciError> { 312 let mut device_bar: PciDeviceBar = PciDeviceBar::default(); 313 let mut bar_index_ignore: u8 = 255; 314 for bar_index in 0..6 { 315 if bar_index == bar_index_ignore { 316 continue; 317 } 318 let bar_info; 319 let mut virtaddress: u64 = 0; 320 let bar_orig = unsafe { 321 let bar_temp = pci_read_config( 322 device_function.bus, 323 device_function.device, 324 device_function.function, 325 BAR0_OFFSET + 4 * bar_index, 326 ); 327 bar_temp 328 }; 329 unsafe { 330 pci_write_config( 331 device_function.bus, 332 device_function.device, 333 device_function.function, 334 BAR0_OFFSET + 4 * bar_index, 335 0xffffffff, 336 ); 337 } 338 let size_mask = unsafe { 339 let bar_temp = pci_read_config( 340 device_function.bus, 341 device_function.device, 342 device_function.function, 343 BAR0_OFFSET + 4 * bar_index, 344 ); 345 bar_temp 346 }; 347 // A wrapping add is necessary to correctly handle the case of unused BARs, which read back 348 // as 0, and should be treated as size 0. 349 let size = (!(size_mask & 0xfffffff0)).wrapping_add(1); 350 //kdebug!("bar_orig:{:#x},size: {:#x}", bar_orig,size); 351 // Restore the original value. 352 unsafe { 353 pci_write_config( 354 device_function.bus, 355 device_function.device, 356 device_function.function, 357 BAR0_OFFSET + 4 * bar_index, 358 bar_orig, 359 ); 360 } 361 if size == 0 { 362 continue; 363 } 364 if bar_orig & 0x00000001 == 0x00000001 { 365 // I/O space 366 let address = bar_orig & 0xfffffffc; 367 bar_info = BarInfo::IO { address, size }; 368 } else { 369 // Memory space 370 let mut address = u64::from(bar_orig & 0xfffffff0); 371 let prefetchable = bar_orig & 0x00000008 != 0; 372 let address_type = MemoryBarType::try_from(((bar_orig & 0x00000006) >> 1) as u8)?; 373 if address_type == MemoryBarType::Width64 { 374 if bar_index >= 5 { 375 return Err(PciError::InvalidBarType); 376 } 377 let address_top = unsafe { 378 let bar_temp = pci_read_config( 379 device_function.bus, 380 device_function.device, 381 device_function.function, 382 BAR0_OFFSET + 4 * (bar_index + 1), 383 ); 384 bar_temp 385 }; 386 address |= u64::from(address_top) << 32; 387 bar_index_ignore = bar_index + 1; //下个bar跳过,因为64位的memory bar覆盖了两个bar 388 } 389 //kdebug!("address={:#x},size={:#x}",address,size); 390 unsafe { 391 let vaddr_ptr = &mut virtaddress as *mut u64; 392 let mut virtsize: u64 = 0; 393 let virtsize_ptr = &mut virtsize as *mut u64; 394 let initial_mm_ptr = &mut initial_mm as *mut mm_struct; 395 //kdebug!("size want={:#x}", size); 396 if let Err(_) = MMIO_POOL.create_mmio( 397 size, 398 (VM_IO | VM_DONTCOPY) as u64, 399 vaddr_ptr, 400 virtsize_ptr, 401 ) { 402 kerror!("Create mmio failed when initing pci bar"); 403 return Err(PciError::CreateMmioError); 404 }; 405 //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize); 406 mm_map(initial_mm_ptr, virtaddress, size as u64, address); 407 } 408 bar_info = BarInfo::Memory { 409 address_type, 410 prefetchable, 411 address, 412 size, 413 virtaddress, 414 }; 415 } 416 match bar_index { 417 0 => { 418 device_bar.bar0 = bar_info; 419 } 420 1 => { 421 device_bar.bar1 = bar_info; 422 } 423 2 => { 424 device_bar.bar2 = bar_info; 425 } 426 3 => { 427 device_bar.bar3 = bar_info; 428 } 429 4 => { 430 device_bar.bar4 = bar_info; 431 } 432 5 => { 433 device_bar.bar5 = bar_info; 434 } 435 _ => {} 436 } 437 } 438 kdebug!("pci_device_bar:{}", device_bar); 439 return Ok(device_bar); 440 } 441 442 /// Information about a PCI device capability. 443 /// PCI设备的capability的信息 444 #[derive(Debug, Copy, Clone, Eq, PartialEq)] 445 pub struct CapabilityInfo { 446 /// The offset of the capability in the PCI configuration space of the device function. 447 pub offset: u8, 448 /// The ID of the capability. 449 pub id: u8, 450 /// The third and fourth bytes of the capability, to save reading them again. 451 pub private_header: u16, 452 } 453 454 /// Iterator over capabilities for a device. 455 /// 创建迭代器以遍历PCI设备的capability 456 #[derive(Debug)] 457 pub struct CapabilityIterator { 458 pub device_function: DeviceFunction, 459 pub next_capability_offset: Option<u8>, 460 } 461 462 impl Iterator for CapabilityIterator { 463 type Item = CapabilityInfo; 464 fn next(&mut self) -> Option<Self::Item> { 465 let offset = self.next_capability_offset?; 466 467 // Read the first 4 bytes of the capability. 468 let capability_header = unsafe { 469 let temp = pci_read_config( 470 self.device_function.bus, 471 self.device_function.device, 472 self.device_function.function, 473 offset, 474 ); 475 temp 476 }; 477 let id = capability_header as u8; 478 let next_offset = (capability_header >> 8) as u8; 479 let private_header = (capability_header >> 16) as u16; 480 481 self.next_capability_offset = if next_offset == 0 { 482 None 483 } else if next_offset < 64 || next_offset & 0x3 != 0 { 484 kwarn!("Invalid next capability offset {:#04x}", next_offset); 485 None 486 } else { 487 Some(next_offset) 488 }; 489 490 Some(CapabilityInfo { 491 offset, 492 id, 493 private_header, 494 }) 495 } 496 } 497 498 /// @brief 设置PCI Config Space里面的Command Register 499 /// 500 /// @param device_function 设备 501 /// @param value command register要被设置成的值 502 pub fn set_command_register(device_function: &DeviceFunction, value: CommandRegister) { 503 unsafe { 504 pci_write_config( 505 device_function.bus, 506 device_function.device, 507 device_function.function, 508 STATUS_COMMAND_OFFSET, 509 value.bits().into(), 510 ); 511 } 512 } 513 /// @brief 使能对PCI Memory/IO空间的写入,使能PCI设备作为主设备(主动进行Memory的写入等,msix中断使用到) 514 /// 515 /// @param device_function 设备 516 pub fn pci_enable_master(device_function: DeviceFunction) { 517 set_command_register( 518 &device_function, 519 CommandRegister::IO_SPACE | CommandRegister::MEMORY_SPACE | CommandRegister::BUS_MASTER, 520 ); 521 } 522