修复ecam无法获取MCFG table的问题 (#241)

This commit is contained in:
YJwu2023 2023-04-14 12:21:08 +08:00 committed by GitHub
parent 79a452ce8f
commit 5c1e552cc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 17 deletions

View File

@ -3,7 +3,7 @@ pub mod x86_64;
pub use self::x86_64::pci::pci::X86_64PciArch as PciArch;
#[cfg(target_arch = "x86_64")]
pub use self::x86_64::*; //公开x86_64架构下的函数使外界接口统一
use crate::driver::pci::pci::{BusDeviceFunction, PciError, PciRoot, SegmentGroupNumber};
use crate::driver::pci::pci::{BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber};
/// TraitPciArch Pci架构相关函数任何架构都应独立实现trait里的函数
pub trait TraitPciArch {
/// @brief 读取寄存器值x86_64架构通过读取两个特定io端口实现
@ -18,8 +18,8 @@ pub trait TraitPciArch {
fn write_config(bus_device_function: &BusDeviceFunction, offset: u8, data: u32);
/// @brief PCI域地址到存储器域地址的转换,x86_64架构为一一对应
/// @param address PCI域地址
/// @return Result<usize, PciError> 转换结果或出错原因
fn address_pci_to_address_memory(address: usize) -> Result<usize, PciError>;
/// @return usize 转换结果
fn address_pci_to_physical(pci_address: PciAddr) -> usize;
/// @brief 获取Segement的root地址,x86_64架构为acpi mcfg表中读取
/// @param segement 组id
/// @return Result<PciRoot, PciError> 转换结果或出错原因

View File

@ -1,7 +1,7 @@
use crate::arch::TraitPciArch;
use crate::driver::acpi::acpi::mcfg_find_segment;
use crate::driver::pci::pci::{
BusDeviceFunction, PciError, PciRoot, SegmentGroupNumber, PORT_PCI_CONFIG_ADDRESS,
BusDeviceFunction, PciAddr, PciError, PciRoot, SegmentGroupNumber, PORT_PCI_CONFIG_ADDRESS,
PORT_PCI_CONFIG_DATA,
};
use crate::include::bindings::bindings::{
@ -40,8 +40,8 @@ impl TraitPciArch for X86_64PciArch {
}
}
fn address_pci_to_address_memory(address: usize) -> Result<usize, PciError> {
Ok(address)
fn address_pci_to_physical(pci_address: PciAddr) -> usize {
return pci_address.data();
}
fn ecam_root(segement: SegmentGroupNumber) -> Result<PciRoot, PciError> {

View File

@ -11,10 +11,12 @@ use crate::{kdebug, kerror, kinfo, kwarn};
use alloc::vec::Vec;
use alloc::{boxed::Box, collections::LinkedList};
use bitflags::bitflags;
use core::{
convert::TryFrom,
fmt::{self, Display, Formatter},
fmt::{self, Debug, Display, Formatter},
};
// PCI_DEVICE_LINKEDLIST 添加了读写锁的全局链表里面存储了检索到的PCI设备结构体
// PCI_ROOT_0 Segment为0的全局PciRoot
lazy_static! {
@ -29,6 +31,40 @@ lazy_static! {
}
};
}
/// PCI域地址
#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct PciAddr(usize);
impl PciAddr {
#[inline(always)]
pub const fn new(address: usize) -> Self {
Self(address)
}
/// @brief 获取PCI域地址的值
#[inline(always)]
pub fn data(&self) -> usize {
self.0
}
/// @brief 将PCI域地址加上一个偏移量
#[inline(always)]
pub fn add(self, offset: usize) -> Self {
Self(self.0 + offset)
}
/// @brief 判断PCI域地址是否按照指定要求对齐
#[inline(always)]
pub fn check_aligned(&self, align: usize) -> bool {
return self.0 & (align - 1) == 0;
}
}
impl Debug for PciAddr {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "PciAddr({:#x})", self.0)
}
}
/// 添加了读写锁的链表存储PCI设备结构体
pub struct PciDeviceLinkedList {
@ -489,7 +525,7 @@ impl Display for PciRoot {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"PCI Root with segement:{}, bus begin at {}, bus end at {}, physical address at {},mapped at {:#x}",
"PCI Root with segement:{}, bus begin at {}, bus end at {}, physical address at {:#x},mapped at {:#x}",
self.segement_group_number, self.bus_begin, self.bus_end, self.physical_address_base, self.mmio_base.unwrap() as usize
)
}
@ -506,13 +542,14 @@ impl PciRoot {
/// @brief 完成物理地址到虚拟地址的映射并将虚拟地址加入mmio_base变量
/// @return 返回错误或Ok(0)
fn map(&mut self) -> Result<u8, PciError> {
let bus_number = self.bus_end - self.bus_begin + 1;
let bus_number_double = (bus_number + 1) / 2;
//kdebug!("bus_begin={},bus_end={}", self.bus_begin,self.bus_end);
let bus_number = (self.bus_end - self.bus_begin) as u32 + 1;
let bus_number_double = (bus_number - 1) / 2 + 1; //一个bus占据1MB空间计算全部bus占据空间相对于2MB空间的个数
let mut virtaddress: u64 = 0;
let vaddr_ptr = &mut virtaddress as *mut u64;
let mut virtsize: u64 = 0;
let virtsize_ptr = &mut virtsize as *mut u64;
let size = bus_number_double as u32 * PAGE_2M_SIZE;
let size = bus_number_double * PAGE_2M_SIZE;
unsafe {
let initial_mm_ptr = &mut initial_mm as *mut mm_struct;
if let Err(_) =
@ -978,7 +1015,19 @@ fn pci_check_bus(bus: u8) -> Result<u8, PciError> {
#[no_mangle]
pub extern "C" fn rs_pci_init() {
pci_init();
//kdebug!("{}",PCI_ROOT_0.unwrap());
if PCI_ROOT_0.is_some() {
kdebug!("{}", PCI_ROOT_0.unwrap());
//以下为ecam的读取寄存器值测试经测试可正常读取
// let bus_device_function = BusDeviceFunction {
// bus: 0,
// device: 2,
// function: 0,
// };
// kdebug!(
// "Ecam read virtio-net device status={:#x}",
// (PCI_ROOT_0.unwrap().read_config(bus_device_function, 4)>>16) as u16
// );
}
}
/// @brief pci初始化函数
pub fn pci_init() {
@ -996,7 +1045,7 @@ pub fn pci_init() {
let common_header = box_pci_device.common_header();
match box_pci_device.header_type() {
HeaderType::Standard if common_header.status & 0x10 != 0 => {
kinfo!("Found pci standard device with class code ={} subclass={} status={:#x} cap_pointer={:#x} vendor={:#x}, device id={:#x}", common_header.class_code, common_header.subclass, common_header.status, box_pci_device.as_standard_device().unwrap().capabilities_pointer,common_header.vendor_id, common_header.device_id);
kinfo!("Found pci standard device with class code ={} subclass={} status={:#x} cap_pointer={:#x} vendor={:#x}, device id={:#x},bdf={}", common_header.class_code, common_header.subclass, common_header.status, box_pci_device.as_standard_device().unwrap().capabilities_pointer,common_header.vendor_id, common_header.device_id,common_header.bus_device_function);
}
HeaderType::Standard => {
kinfo!(
@ -1055,7 +1104,11 @@ impl BusDeviceFunction {
///实现BusDeviceFunction的Display trait使其可以直接输出
impl Display for BusDeviceFunction {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{:02x}:{:02x}.{}", self.bus, self.device, self.function)
write!(
f,
"bus {} device {} function{}",
self.bus, self.device, self.function
)
}
}
/// The location allowed for a memory BAR.
@ -1267,7 +1320,8 @@ pub fn pci_bar_init(
address |= u64::from(address_top) << 32;
bar_index_ignore = bar_index + 1; //下个bar跳过因为64位的memory bar覆盖了两个bar
}
//kdebug!("address={:#x},size={:#x}",address,size);
let pci_address = PciAddr::new(address as usize);
address = PciArch::address_pci_to_physical(pci_address) as u64; //PCI总线域物理地址转换为存储器域物理地址
unsafe {
let vaddr_ptr = &mut virtaddress as *mut u64;
let mut virtsize: u64 = 0;

View File

@ -9,7 +9,6 @@ use crate::libs::rwlock::RwLockWriteGuard;
use crate::{kdebug, kerror, kwarn};
use alloc::{boxed::Box, collections::LinkedList};
use virtio_drivers::transport::{DeviceType, Transport};
const NETWORK_CLASS: u8 = 0x2;
const ETHERNET_SUBCLASS: u8 = 0x0;

View File

@ -29,7 +29,7 @@ QEMU_RTC_CLOCK="clock=host,base=localtime"
QEMU_SERIAL="file:../serial_opt.txt"
QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -nic user,model=virtio-net-pci -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel}"
QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -nic user,model=virtio-net-pci -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel} -machine q35"
QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d -monitor ${QEMU_MONITOR} -d ${qemu_trace_std} "