From c2e5e2f7156e73f189de834409ef9b74bed6cdc2 Mon Sep 17 00:00:00 2001 From: Julien THILLARD Date: Mon, 9 Mar 2026 17:53:06 +0100 Subject: [PATCH] Sync computers --- Cargo.toml | 2 +- crates/shared/src/endian.rs | 0 crates/shared/src/lib.rs | 1 + src/main.rs | 6 +- src/pci.rs | 195 +++++++++++++++++++++++++++++------- src/volatile.rs | 12 +++ 6 files changed, 179 insertions(+), 37 deletions(-) create mode 100644 crates/shared/src/endian.rs create mode 100644 src/volatile.rs diff --git a/Cargo.toml b/Cargo.toml index ca968b0..9a26578 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ version = "0.1.0" edition = "2024" [dependencies] +bitflags = "2" embedded-alloc = "0.7" kernel-macros = { path = "crates/kernel-macros" } log = "0.4" @@ -15,6 +16,5 @@ critical-section = { version = "1", features = ["restore-state-bool"] } bffs = { path = "crates/bffs", features = ["alloc"] } io = { path = "crates/io", features = ["alloc"] } shared = { path = "crates/shared", features = ["kernel"] } -# ELF parsing helper goblin = { version = "0.7", default-features = false, features = ["elf32", "elf64", "endian_fd"] } hashbrown = "0.16" diff --git a/crates/shared/src/endian.rs b/crates/shared/src/endian.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index 866f9c0..dbe4616 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -2,3 +2,4 @@ pub mod fs; pub mod syscall; +pub mod endian; diff --git a/src/main.rs b/src/main.rs index 0f2411b..9ddfa5a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ #![no_main] // #![warn(clippy::pedantic)] #![allow(static_mut_refs)] -#![feature(riscv_ext_intrinsics, str_from_raw_parts)] +#![feature(riscv_ext_intrinsics, str_from_raw_parts, arbitrary_self_types_pointers)] use core::sync::atomic::AtomicBool; @@ -16,7 +16,7 @@ use log::info; use crate::{ io::init_log, - pci::{PciDeviceIterator, scan_pci_for_virtio_keyboard}, + pci::{PciDeviceIterator, scan_pci_for_virtio_keyboard, scan_pci_for_virtio_keyboard2}, riscv::enable_supervisor_interrupt, scheduler::{SCHEDULER, idle}, user::{proc2, test}, @@ -29,6 +29,7 @@ use crate::{ }; extern crate alloc; +mod volatile; mod boot; mod critical_section; mod draw; @@ -95,6 +96,7 @@ pub extern "C" fn supervisor_mode_entry() { } unsafe { + scan_pci_for_virtio_keyboard2(); let pci_info = scan_pci_for_virtio_keyboard().unwrap(); KBD_DRIVER = Some(VirtioPciDriver::new( pci_info.common_cfg, diff --git a/src/pci.rs b/src/pci.rs index 8079569..6f129a4 100644 --- a/src/pci.rs +++ b/src/pci.rs @@ -1,4 +1,6 @@ -use crate::println; +use core::ops::{Deref, DerefMut}; + +use crate::{println, volatile::Volatile}; // Configuration pour RISC-V Virt const PCI_ECAM_BASE: usize = 0x3000_0000; @@ -41,42 +43,155 @@ pub struct VirtioPciCaps { pub struct PciDevice { pub bus: u8, pub device: u8, + pub inner: *mut PciHeader, } -pub struct PciGeneralDevice(PciDevice); +#[repr(C, packed)] +pub struct PciHeader { + pub vendor_id: Volatile, + pub device_id: Volatile, + pub command: Volatile, + pub status: Volatile, + pub revision_id: Volatile, + pub programming_interface_bytes: Volatile, + pub subclass: Volatile, + pub class_code: Volatile, + pub cache_line_size: Volatile, + pub latency_timer: Volatile, + pub header_type: Volatile, + pub bist: Volatile, +} + +#[derive(Debug, Clone, Copy)] +pub enum PciBar { + B32(PciBar32), + B64(PciBar64), +} + +#[derive(Debug, Clone, Copy)] +pub struct PciBar32(*mut u32); + +#[derive(Debug, Clone, Copy)] +pub struct PciBar64(*mut u64); + +#[repr(C, packed)] +pub struct PciGeneralHeader { + pub common_header: Volatile, + pub bars: [Volatile; 6], + pub cardbus_cis_pointer: Volatile, + pub subsystem_vendor_id: Volatile, + pub subsystem_id: Volatile, + pub expansion_rom_base_address: Volatile, + pub capabilities_pointer: Volatile, + pub _reserved1: [Volatile; 7], + pub interrupt_line: Volatile, + pub interrupt_pin: Volatile, + pub min_grant: Volatile, + pub max_lantency: Volatile, +} + +pub struct PciGeneralDevice { + pub bus: u8, + pub device: u8, + pub inner: *mut PciGeneralHeader, +} + +impl Deref for PciGeneralDevice { + type Target = PciDevice; + + fn deref(&self) -> &Self::Target { + unsafe { &*(self as *const Self as *const Self::Target) } + } +} + +impl DerefMut for PciGeneralDevice { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *(self as *mut Self as *mut Self::Target) } + } +} impl PciDevice { pub fn new(bus: u8, device: u8) -> Self { - Self { bus, device } + let addr = PCI_ECAM_BASE | ((bus as usize) << 20) | ((device as usize) << 15); + Self { + bus, + device, + inner: addr as *mut PciHeader, + } } pub fn vendor_and_device_id(&self) -> (u16, u16) { - let id = self.read::(0); - ((id & 0xFFFF) as u16, (id >> 16) as u16) + (self.get_vendor_id(), self.get_device_id()) } - pub fn device_id(&self) -> u16 { - self.vendor_and_device_id().1 + pub fn get_device_id(&self) -> u16 { + unsafe { (&raw const (*self.inner).device_id).read() } } - pub fn vendor_id(&self) -> u16 { - self.vendor_and_device_id().0 + pub fn get_vendor_id(&self) -> u16 { + unsafe { (*self.inner).vendor_id } } - pub fn interrupt_pin(&self) -> u8 { - self.read(0x3D) + pub fn get_command(&self) -> u16 { + unsafe { (*self.inner).command } } - - fn read(&self, offset: u16) -> T { - pci_read(self.bus, self.device, 0, offset) - } - - fn write_u32(&self, offset: u16, value: u32) { - pci_write(self.bus, self.device, 0, offset, value) + pub fn set_command(&mut self, command: u16) { + unsafe { (*self.inner).command = command } } /// # Safety /// `self` must be a valid general PCI device. pub unsafe fn to_general_device(self) -> PciGeneralDevice { - PciGeneralDevice(self) + unsafe { core::mem::transmute::(self) } + } +} + +impl PciGeneralDevice { + pub fn get_interrupt_pin(&self) -> u8 { + unsafe { (*self.inner).interrupt_pin } + } + pub fn set_interrupt_irq(&mut self, irq: u8) { + unsafe { (*self.inner).interrupt_line = irq } + } + + pub fn get_bar(&mut self, i: u8) -> PciBar { + unsafe { PciBar((&raw mut (*self.inner).bars as *mut u32).add(i as usize)) } + } +} + +pub struct PciBarIterator { + pub current: u8, + pub base_addr: *mut u32, +} + +impl Iterator for PciBarIterator { + type Item = PciBar; + + fn next(&mut self) -> Option { + if self.current >= 6 { + None + } else { + let res = if unsafe { *(self.base_addr.add(self.current as usize)) & 0b100 != 0 } { + self.current += 1; + PciBar64 + } else { + }; + self.current += 1; + res + } + } +} + +impl PciBar { + pub fn as_ptr(self) -> *const u8 { + self.0 as *const u8 + } + pub fn as_mut_ptr(self) -> *mut u8 { + self.0 as *mut u8 + } + pub fn is_64bits(self) -> bool { + unsafe { *self.0 & 0b100 != 0 } + } + pub fn is_prefetchable(self) -> bool { + unsafe { *self.0 & 0b1000 != 0 } } } @@ -115,10 +230,22 @@ pub fn scan_pci_for_virtio_keyboard2() -> Option { let device = PciDeviceIterator::new() .find(|device| device.vendor_and_device_id() == (0x1af4, 0x1052)) .unwrap(); - let device = unsafe { + let mut device = unsafe { // VirtIO keyboard is a general PCI device device.to_general_device() }; + let interrupt_pin = device.get_interrupt_pin(); + let irq = 32 + (device.device + interrupt_pin - 1) % 4; + device.set_interrupt_irq(irq); + + let command = device.get_command() | 0b110; + device.set_command(command); + + for i in 0..6 { + let bar = device.get_bar(i); + println!("bar {} {:x?} 64: {}", i, bar, bar.is_64bits()) + } + None } @@ -133,22 +260,22 @@ pub fn scan_pci_for_virtio_keyboard() -> Option { // et le Device ID Keyboard (0x1012 ou 0x1052 pour Modern) if vendor == 0x1af4 && (device >= 0x1000 && device <= 0x107f) { // Dans ta boucle de scan, après avoir trouvé le device - let interrupt_pin = (pci_read::(0, dev, 0, 0x3C) >> 8) & 0xFF; // Offset 0x3D - let irq = 32 + (dev as u32 + interrupt_pin - 1) % 4; + // let interrupt_pin = (pci_read::(0, dev, 0, 0x3C) >> 8) & 0xFF; // Offset 0x3D + // let irq = 32 + (dev as u32 + interrupt_pin - 1) % 4; - let old_val = pci_read::(0, 2, 0, 0x3C); + // // let old_val = pci_read::(0, 2, 0, 0x3C); - // On garde les 24 bits du haut (Interrupt Pin, etc.) et on change les 8 bits du bas - let new_val = (old_val & 0xFFFFFF00) | irq; + // // On garde les 24 bits du haut (Interrupt Pin, etc.) et on change les 8 bits du bas + // // let new_val = (old_val & 0xFFFFFF00) | irq; - pci_write(0, 2, 0, 0x3C, new_val); + // // pci_write(0, 2, 0, 0x3C, new_val); - println!( - "VirtIO Keyboard sur Slot {}, PIN {}, mappé sur IRQ PLIC {}", - dev, interrupt_pin, irq - ); // ACTIVER l'accès mémoire et le bus mastering (PCI Command) - let cmd = pci_read::(0, dev, 0, 0x04); - pci_write(0, dev, 0, 0x04, cmd | 0x6); + // println!( + // "VirtIO Keyboard sur Slot {}, PIN {}, mappé sur IRQ PLIC {}", + // dev, interrupt_pin, irq + // ); // ACTIVER l'accès mémoire et le bus mastering (PCI Command) + // let cmd = pci_read::(0, dev, 0, 0x04); + // pci_write(0, dev, 0, 0x04, cmd | 0x6); let mut common_cfg = 0; let mut notify_cfg = 0; @@ -158,8 +285,8 @@ pub fn scan_pci_for_virtio_keyboard() -> Option { let mut notify_multiplier: u32 = 1; // 1. Activer le Bus Master et le Memory Space globalement pour ce périphérique avant de commencer - let old_cmd = pci_read::(0, dev, 0, 0x04); - pci_write(0, dev, 0, 0x04, old_cmd | 0x06); + // let old_cmd = pci_read::(0, dev, 0, 0x04); + // pci_write(0, dev, 0, 0x04, old_cmd | 0x06); // 2. Boucle d'assignation des BARs (AVANT de lire les capabilities) let mut bar_idx = 0; diff --git a/src/volatile.rs b/src/volatile.rs new file mode 100644 index 0000000..5a68c35 --- /dev/null +++ b/src/volatile.rs @@ -0,0 +1,12 @@ +#[repr(transparent)] +#[derive(Debug, Clone, Copy)] +pub struct Volatile(T); + +impl Volatile { + pub unsafe fn read(self: *const Self) -> T { + unsafe { core::ptr::read_volatile(self as *const T) } + } + pub unsafe fn write(self: *mut Self, value: T) { + unsafe { core::ptr::write_volatile(self as *mut T, value) } + } +}