Implement pci bus probing and fix a bug in virtio_mmio

master
Jiajie Chen 6 years ago
parent 05310dcd7d
commit 197bebb1d2

@ -61,6 +61,8 @@ endif
### qemu options ###
qemu_opts := \
-smp cores=$(smp)
qemu_net_opts := \
-netdev type=tap,id=net0,script=no,downscript=no
ifeq ($(arch), x86_64)
qemu_opts += \
@ -68,6 +70,8 @@ qemu_opts += \
-drive format=raw,file=$(SFSIMG),media=disk,cache=writeback \
-serial mon:stdio \
-device isa-debug-exit
qemu_net_opts += \
-device virtio-net-pci,netdev=net0
else ifeq ($(arch), riscv32)
qemu_opts += \
@ -75,6 +79,9 @@ qemu_opts += \
-kernel $(bin) \
-drive file=$(SFSIMG),format=raw,id=sfs \
-device virtio-blk-device,drive=sfs
qemu_net_opts += \
-device virtio-net-device,netdev=net0
ifdef m_mode
qemu_opts += -cpu rv32imacu-nommu
endif
@ -85,6 +92,9 @@ qemu_opts += \
-kernel $(bin) \
-drive file=$(SFSIMG),format=raw,id=sfs \
-device virtio-blk-device,drive=sfs
qemu_net_opts += \
-device virtio-net-device,netdev=net0
ifdef m_mode
qemu_opts += -cpu rv64imacu-nommu
endif
@ -182,9 +192,7 @@ justrun:
@qemu-system-$(arch) $(qemu_opts)
justrunnet: build
@sudo qemu-system-$(arch) $(qemu_opts) \
-netdev type=tap,id=net0,script=no,downscript=no \
-device virtio-net-device,netdev=net0 \
@sudo qemu-system-$(arch) $(qemu_opts) $(qemu_net_opts)
justrunui: build
@qemu-system-$(arch) $(qemu_opts) \

@ -43,6 +43,8 @@ pub extern "C" fn _start(boot_info: &'static BootInfo) -> ! {
driver::init();
crate::drivers::init();
crate::process::init();
AP_CAN_INIT.store(true, Ordering::Relaxed);

@ -1 +1,3 @@
pub mod virtio_mmio;
#[cfg(target_arch = "x86_64")]
pub mod pci;

@ -0,0 +1,98 @@
use x86_64::instructions::port::Port;
use crate::logging::*;
const VENDOR: u32 = 0x00;
const DEVICE: u32 = 0x02;
const STATUS: u32 = 0x06;
const SUBCLASS: u32 = 0x0a;
const CLASS: u32 = 0x0b;
const HEADER: u32 = 0x0e;
const PCI_ADDR_PORT: u16 = 0xcf8;
const PCI_DATA_PORT: u16 = 0xcfc;
struct PciTag(u32);
impl PciTag {
pub fn new(bus: u32, dev: u32, func: u32) -> PciTag {
PciTag(bus << 16 | dev << 11 | func << 8)
}
pub fn bus(&self) -> u32 {
(self.0 >> 16) & 0xFF
}
pub fn dev(&self) -> u32 {
(self.0 >> 11) & 0x1F
}
pub fn func(&self) -> u32 {
(self.0 >> 8) & 0x7
}
// biscuit/src/pci/pci.go
pub unsafe fn read(&self, reg: u32, width: u32) -> u32 {
// spans in one reg
assert_eq!(reg / 4, (reg + width - 1) / 4);
let enable = 1 << 31;
let rsh = reg % 4;
let r = reg - rsh;
let t = enable | self.0 | r;
let mut pci_addr: Port<u32> = Port::new(PCI_ADDR_PORT);
let mut pci_data: Port<u32> = Port::new(PCI_DATA_PORT);
pci_addr.write(t);
let d = pci_data.read();
pci_addr.write(0);
let ret = d >> (rsh * 8);
let m = (1 << (8 * width)) - 1;
return ret & m;
}
pub unsafe fn write(&self, reg: u32, val: u32) {
assert_eq!(reg & 3, 0);
let enable = 1 << 31;
let t = enable | self.0 | reg;
let mut pci_addr: Port<u32> = Port::new(PCI_ADDR_PORT);
let mut pci_data: Port<u32> = Port::new(PCI_DATA_PORT);
pci_addr.write(t);
pci_data.write(val);
pci_addr.write(0);
}
pub fn describe(&self) -> bool {
unsafe {
let v = self.read(VENDOR, 2);
if v == 0xffff {
return false;
}
let d = self.read(DEVICE, 2);
let mf = self.read(HEADER, 1);
let cl = self.read(CLASS, 1);
let scl = self.read(SUBCLASS, 1);
info!("{}: {}: {}: {:#X} {:#X} ({} {})", self.bus(), self.dev(), self.func(), v, d, cl, scl);
return mf & 0x80 != 0;
}
}
}
pub fn init() {
for bus in 0..256 {
for dev in 0..32 {
let tag = PciTag::new(bus, dev, 0);
if tag.describe() {
for func in 1..8 {
let tag = PciTag::new(bus, dev, func);
tag.describe();
}
}
}
}
info!("Init pci");
}

@ -208,7 +208,8 @@ impl VirtIOVirtqueue {
let mut output = Vec::new();
loop {
let flags = VirtIOVirtqueueFlag::from_bits_truncate(desc[cur].flags.read());
let buffer = unsafe { slice::from_raw_parts(desc[cur].addr.read() as *const u8, desc[cur].len.read() as usize) };
let addr = desc[cur].addr.read() as u64 - MEMORY_OFFSET as u64 + KERNEL_OFFSET as u64;
let buffer = unsafe { slice::from_raw_parts(addr as *const u8, desc[cur].len.read() as usize) };
if flags.contains(VirtIOVirtqueueFlag::WRITE) {
input.push(buffer);
} else {

@ -54,6 +54,12 @@ lazy_static! {
pub static ref NET_DRIVERS: SpinNoIrqLock<Vec<Box<NetDriver>>> = SpinNoIrqLock::new(Vec::new());
}
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
pub fn init(dtb: usize) {
device_tree::init(dtb);
}
#[cfg(target_arch = "x86_64")]
pub fn init() {
bus::pci::init();
}

@ -168,9 +168,8 @@ impl phy::TxToken for VirtIONetTxToken {
unsafe { slice::from_raw_parts_mut(page as *mut u8, PAGE_SIZE) }
}
};
let output_buffer = &mut output[size_of::<VirtIONetHeader>()..(size_of::<VirtIONetHeader>() +len)];
let output_buffer = &mut output[size_of::<VirtIONetHeader>()..(size_of::<VirtIONetHeader>() + len)];
let result = f(output_buffer);
println!("output {:?}", output_buffer);
let mut driver = (self.0).0.lock();
assert!(driver.queues[VIRTIO_QUEUE_TRANSMIT].add_and_notify(&[], &[output], 0));

Loading…
Cancel
Save