From c97d39c36b79fdbbf416cb1840e58e8080c8e2d3 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Fri, 31 Jan 2025 22:07:33 -0800 Subject: [PATCH] Make handle interrupt non-mutable in ahci controller. --- rust/sys/denali/src/ahci/controller.rs | 81 ++++++++++++++------------ rust/sys/denali/src/bin/denali.rs | 4 +- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/rust/sys/denali/src/ahci/controller.rs b/rust/sys/denali/src/ahci/controller.rs index 6ccd32e..6869c63 100644 --- a/rust/sys/denali/src/ahci/controller.rs +++ b/rust/sys/denali/src/ahci/controller.rs @@ -49,8 +49,9 @@ pub struct PciDeviceHeader { pub struct AhciController { pci_header: &'static mut PciDeviceHeader, - hba: &'static mut AhciHba, + hba: Mutex<&'static mut AhciHba>, ports: [Option; 32], + hba_vaddr: u64, } impl AhciController { @@ -62,15 +63,16 @@ impl AhciController { let hba = unsafe { (hba_vaddr as *mut AhciHba).as_mut().unwrap() }; let mut controller = Self { pci_header, - hba, + hba: Mutex::new(hba), ports: [const { None }; 32], + hba_vaddr, }; controller.init(); controller } fn init(&mut self) { - self.hba.init(); + self.hba.lock().init(); self.init_ports().unwrap(); } @@ -88,13 +90,14 @@ impl AhciController { } } - fn handle_irq(&mut self) { - for i in 0..self.hba.capabilities.read().num_ports() { + fn handle_irq(&self) { + let mut hba = self.hba.lock(); + for i in 0..hba.capabilities.read().num_ports() { let int_offset = 1 << i; - if (self.hba.interrupt_status.read() & int_offset) == int_offset { - if let Some(port) = &mut self.ports[i as usize] { + if (hba.interrupt_status.read() & int_offset) == int_offset { + if let Some(port) = &self.ports[i as usize] { port.handle_interrupt(); - self.hba.interrupt_status.update(|is| { + hba.interrupt_status.update(|is| { *is &= !int_offset; }); } @@ -103,16 +106,17 @@ impl AhciController { } fn init_ports(&mut self) -> Result<(), ZError> { - for i in 0..(self.hba.capabilities.read().num_ports() as usize) { + let hba = self.hba.lock(); + for i in 0..(hba.capabilities.read().num_ports() as usize) { let port_index = 1 << i; - if (self.hba.port_implemented.read() & port_index) != port_index { + if (hba.port_implemented.read() & port_index) != port_index { mammoth::debug!("Skipping port {}, not implemented", i); continue; } let port_offset: usize = 0x100 + (0x80 * i); let port = unsafe { - (((self.hba as *mut _ as usize) + port_offset) as *mut AhciPortHba) + ((self.hba_vaddr as usize + port_offset) as *mut AhciPortHba) .as_mut() .unwrap() }; @@ -137,17 +141,17 @@ impl AhciController { } } -pub fn spawn_irq_thread(controller: Arc>) -> thread::JoinHandle { +pub fn spawn_irq_thread(controller: Arc) -> thread::JoinHandle { let irq_thread = move || { - let irq_num = controller.lock().irq_num(); + let irq_num = controller.irq_num(); let irq_port = mammoth::port::PortServer::from_cap(mammoth::syscall::register_irq(irq_num).unwrap()); - controller.lock().hba.global_host_control.update(|ghc| { + controller.hba.lock().global_host_control.update(|ghc| { ghc.set_interrupt_enable(true); }); loop { irq_port.recv_null().unwrap(); - controller.lock().handle_irq(); + controller.handle_irq(); } }; thread::spawn(irq_thread) @@ -191,12 +195,12 @@ impl From<&Command> for HostToDeviceRegisterFis { } struct PortController { - ahci_port_hba: &'static mut AhciPortHba, + ahci_port_hba: Mutex<&'static mut AhciPortHba>, command_list: &'static mut CommandList, received_fis: &'static mut ReceivedFis, command_tables: &'static mut [CommandTable; 32], - command_slots: [Option>; 32], + command_slots: Mutex<[Option>; 32]>, // FIXME: These should probably be something like a OnceCell (or OnceLock). sector_size: Arc>>, @@ -227,18 +231,19 @@ impl PortController { } Self { - ahci_port_hba, + ahci_port_hba: Mutex::new(ahci_port_hba), command_list, received_fis, command_tables, - command_slots: [const { None }; 32], + command_slots: Mutex::new([const { None }; 32]), sector_size: Arc::new(Mutex::new(None)), sector_cnt: Arc::new(Mutex::new(None)), } } pub fn identify(&mut self) -> Result<(), ZError> { - if self.ahci_port_hba.signature.read() == 0x101 { + let sig = self.ahci_port_hba.lock().signature.read(); + if sig == 0x101 { let sector_size = self.sector_size.clone(); let sector_cnt = self.sector_cnt.clone(); let callback = move |c: &Command| { @@ -265,11 +270,10 @@ impl PortController { .lock() .deref_mut() .insert(new_sector_size as u64); - let _ = sector_cnt.lock().deref_mut().insert(lba_count as u64); + let _ = sector_cnt.lock().deref_mut().insert(lba_count); }; self.issue_command(Arc::from(Command::identify(Box::new(callback))?))?; } else { - let sig = self.ahci_port_hba.signature.read(); mammoth::debug!("Skipping non-sata sig: {:#0x}", sig); } Ok(()) @@ -277,7 +281,7 @@ impl PortController { fn issue_command(&mut self, command: Arc) -> Result<(), ZError> { let slot = self.select_slot()?; - self.command_slots[slot] = Some(command.clone()); + self.command_slots.lock()[slot] = Some(command.clone()); self.command_tables[slot].command_fis.host_to_device = command.clone().as_ref().into(); @@ -288,22 +292,22 @@ impl PortController { self.command_list[slot].command = (size_of::() as u16 / 4) & 0x1F; self.command_list[slot].command |= 1 << 7; - self.ahci_port_hba.issue_command(slot); + self.ahci_port_hba.lock().issue_command(slot); Ok(()) } fn select_slot(&self) -> Result { - for i in 0..self.command_slots.len() { - match self.command_slots[i] { - None => return Ok(i), - _ => {} + let slots = self.command_slots.lock(); + for i in 0..slots.len() { + if slots[i].is_none() { + return Ok(i); } } - return Err(ZError::EXHAUSTED); + Err(ZError::EXHAUSTED) } - fn handle_interrupt(&mut self) { - let int_status = self.ahci_port_hba.interrupt_status.read(); + fn handle_interrupt(&self) { + let int_status = self.ahci_port_hba.lock().interrupt_status.read(); if int_status.device_to_host_register_fis_interrupt() { assert_eq!( self.received_fis.device_to_host_register_fis.fis_type as u8, @@ -321,12 +325,13 @@ impl PortController { ); } - self.ahci_port_hba.interrupt_status.write( + self.ahci_port_hba.lock().interrupt_status.write( AhciPortInterruptStatus::new().with_device_to_host_register_fis_interrupt(true), ); } if int_status.pio_setup_fis_interrupt() { self.ahci_port_hba + .lock() .interrupt_status .write(AhciPortInterruptStatus::new().with_pio_setup_fis_interrupt(true)); } @@ -339,16 +344,16 @@ impl PortController { // FIXME: This could cause a race condition when issuing a command if a different // interrupt triggers between us setting the command in the command slot and // actually issuing the command. - if (self.ahci_port_hba.command_issue.read() & int_offset) != int_offset { - if let Some(_) = &self.command_slots[i] { - self.finish_command(i); - self.command_slots[i] = None; - } + if (self.ahci_port_hba.lock().command_issue.read() & int_offset) != int_offset + && self.command_slots.lock()[i].is_some() + { + self.finish_command(i); + self.command_slots.lock()[i] = None; } } } fn finish_command(&self, slot: usize) { - self.command_slots[slot].as_ref().unwrap().callback() + self.command_slots.lock()[slot].as_ref().unwrap().callback() } } diff --git a/rust/sys/denali/src/bin/denali.rs b/rust/sys/denali/src/bin/denali.rs index a25a8fd..5c2370e 100644 --- a/rust/sys/denali/src/bin/denali.rs +++ b/rust/sys/denali/src/bin/denali.rs @@ -20,8 +20,8 @@ extern "C" fn main() -> z_err_t { .get_ahci_info() .expect("Failed to get ahci info"); - let ahci_controller = Arc::new(Mutex::new(AhciController::new( - mammoth::cap::Capability::take(ahci_info.ahci_region), + let ahci_controller = Arc::new(AhciController::new(mammoth::cap::Capability::take( + ahci_info.ahci_region, ))); let thread = spawn_irq_thread(ahci_controller.clone());