From 00de428d6bbbba51d6f926266ee4d29e76b18397 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 26 Jul 2022 17:20:34 -0600 Subject: [PATCH] Workarounds for x86 32-bit --- e1000d/src/device.rs | 4 +- ihdad/src/hda/cmdbuff.rs | 4 +- ihdad/src/hda/stream.rs | 2 +- ixgbed/src/device.rs | 4 +- nvmed/src/main.rs | 11 +++++- rtl8168d/src/device.rs | 6 +-- xhcid/src/main.rs | 83 +++++++++++++++++++++++++-------------- xhcid/src/xhci/context.rs | 2 +- xhcid/src/xhci/ring.rs | 4 +- xhcid/src/xhci/trb.rs | 12 +++--- 10 files changed, 82 insertions(+), 50 deletions(-) diff --git a/e1000d/src/device.rs b/e1000d/src/device.rs index c5b6902bbb..cde14975ff 100644 --- a/e1000d/src/device.rs +++ b/e1000d/src/device.rs @@ -364,7 +364,7 @@ impl Intel8254x { self.receive_ring[i].buffer = self.receive_buffer[i].physical() as u64; } - self.write_reg(RDBAH, (self.receive_ring.physical() >> 32) as u32); + self.write_reg(RDBAH, ((self.receive_ring.physical() as u64) >> 32) as u32); self.write_reg(RDBAL, self.receive_ring.physical() as u32); self.write_reg( RDLEN, @@ -378,7 +378,7 @@ impl Intel8254x { self.transmit_ring[i].buffer = self.transmit_buffer[i].physical() as u64; } - self.write_reg(TDBAH, (self.transmit_ring.physical() >> 32) as u32); + self.write_reg(TDBAH, ((self.transmit_ring.physical() as u64) >> 32) as u32); self.write_reg(TDBAL, self.transmit_ring.physical() as u32); self.write_reg( TDLEN, diff --git a/ihdad/src/hda/cmdbuff.rs b/ihdad/src/hda/cmdbuff.rs index a39998d3fb..afbeadaf79 100644 --- a/ihdad/src/hda/cmdbuff.rs +++ b/ihdad/src/hda/cmdbuff.rs @@ -130,7 +130,7 @@ impl Corb { pub fn set_address(&mut self, addr: usize) { self.regs.corblbase.write((addr & 0xFFFFFFFF) as u32); - self.regs.corbubase.write((addr >> 32) as u32); + self.regs.corbubase.write(((addr as u64) >> 32) as u32); } pub fn reset_read_pointer(&mut self) { @@ -268,7 +268,7 @@ impl Rirb { pub fn set_address(&mut self, addr: usize) { self.regs.rirblbase.write((addr & 0xFFFFFFFF) as u32); - self.regs.rirbubase.write((addr >> 32) as u32); + self.regs.rirbubase.write(((addr as u64) >> 32) as u32); } pub fn reset_write_pointer(&mut self) { diff --git a/ihdad/src/hda/stream.rs b/ihdad/src/hda/stream.rs index cf9cb90ada..0b20bd923a 100644 --- a/ihdad/src/hda/stream.rs +++ b/ihdad/src/hda/stream.rs @@ -156,7 +156,7 @@ impl StreamDescriptorRegs { pub fn set_address(&mut self, addr: usize) { self.buff_desc_list_lo.write( (addr & 0xFFFFFFFF) as u32); - self.buff_desc_list_hi.write( ( (addr >> 32) & 0xFFFFFFFF) as u32); + self.buff_desc_list_hi.write( ( ((addr as u64) >> 32) & 0xFFFFFFFF) as u32); } pub fn set_last_valid_index(&mut self, index:u16) { diff --git a/ixgbed/src/device.rs b/ixgbed/src/device.rs index 70452bc81a..c5a8a210b4 100644 --- a/ixgbed/src/device.rs +++ b/ixgbed/src/device.rs @@ -420,7 +420,7 @@ impl Intel8259x { self.write_reg(IXGBE_RDBAL(i), self.receive_ring.physical() as u32); - self.write_reg(IXGBE_RDBAH(i), (self.receive_ring.physical() >> 32) as u32); + self.write_reg(IXGBE_RDBAH(i), ((self.receive_ring.physical() as u64) >> 32) as u32); self.write_reg( IXGBE_RDLEN(i), (self.receive_ring.len() * mem::size_of::()) as u32, @@ -462,7 +462,7 @@ impl Intel8259x { // section 7.1.9 - setup descriptor ring self.write_reg(IXGBE_TDBAL(i), self.transmit_ring.physical() as u32); - self.write_reg(IXGBE_TDBAH(i), (self.transmit_ring.physical() >> 32) as u32); + self.write_reg(IXGBE_TDBAH(i), ((self.transmit_ring.physical() as u64) >> 32) as u32); self.write_reg( IXGBE_TDLEN(i), (self.transmit_ring.len() * mem::size_of::()) as u32, diff --git a/nvmed/src/main.rs b/nvmed/src/main.rs index b8368aea42..a8d290768a 100644 --- a/nvmed/src/main.rs +++ b/nvmed/src/main.rs @@ -217,13 +217,22 @@ fn get_int_method( } } +//TODO: MSI on non-x86_64? #[cfg(not(target_arch = "x86_64"))] fn get_int_method( pcid_handle: &mut PcidServerHandle, function: &PciFunction, allocated_bars: &AllocatedBars, ) -> Result<(InterruptMethod, InterruptSources)> { - todo!("handling of interrupts on non-x86_64") + if function.legacy_interrupt_pin.is_some() { + // INTx# pin based interrupts. + let irq_handle = File::open(format!("irq:{}", function.legacy_interrupt_line)) + .expect("nvmed: failed to open INTx# interrupt line"); + Ok((InterruptMethod::Intx, InterruptSources::Intx(irq_handle))) + } else { + // No interrupts at all + todo!("handling of no interrupts") + } } fn setup_logging() -> Option<&'static RedoxLogger> { diff --git a/rtl8168d/src/device.rs b/rtl8168d/src/device.rs index 6e3d0991dc..ff6231c32c 100644 --- a/rtl8168d/src/device.rs +++ b/rtl8168d/src/device.rs @@ -333,15 +333,15 @@ impl Rtl8168 { // Set tx low priority buffer address self.regs.tnpds[0].write(self.transmit_ring.physical() as u32); - self.regs.tnpds[1].write((self.transmit_ring.physical() >> 32) as u32); + self.regs.tnpds[1].write(((self.transmit_ring.physical() as u64) >> 32) as u32); // Set tx high priority buffer address self.regs.thpds[0].write(self.transmit_ring_h.physical() as u32); - self.regs.thpds[1].write((self.transmit_ring_h.physical() >> 32) as u32); + self.regs.thpds[1].write(((self.transmit_ring_h.physical() as u64) >> 32) as u32); // Set rx buffer address self.regs.rdsar[0].write(self.receive_ring.physical() as u32); - self.regs.rdsar[1].write((self.receive_ring.physical() >> 32) as u32); + self.regs.rdsar[1].write(((self.receive_ring.physical() as u64) >> 32) as u32); // Disable timer interrupt self.regs.timer_int.write(0); diff --git a/xhcid/src/main.rs b/xhcid/src/main.rs index c8b84180f9..5d199d23b6 100644 --- a/xhcid/src/main.rs +++ b/xhcid/src/main.rs @@ -82,38 +82,11 @@ fn setup_logging() -> Option<&'static RedoxLogger> { } } -fn main() { - // Daemonize - if unsafe { syscall::clone(CloneFlags::empty()).unwrap() } != 0 { - return; - } - - let _logger_ref = setup_logging(); - - let mut pcid_handle = PcidServerHandle::connect_default().expect("xhcid: failed to setup channel to pcid"); +#[cfg(target_arch = "x86_64")] +fn get_int_method(pcid_handle: &mut PcidServerHandle) -> (Option, InterruptMethod) { let pci_config = pcid_handle.fetch_config().expect("xhcid: failed to fetch config"); - info!("XHCI PCI CONFIG: {:?}", pci_config); - - let bar = pci_config.func.bars[0]; - let bar_size = pci_config.func.bar_sizes[0]; let irq = pci_config.func.legacy_interrupt_line; - let mut name = pci_config.func.name(); - name.push_str("_xhci"); - - let bar_ptr = match bar { - pcid_interface::PciBar::Memory(ptr) => match ptr { - 0 => panic!("BAR 0 is mapped to address 0"), - _ => ptr, - }, - other => panic!("Expected memory bar, found {}", other), - }; - - let address = unsafe { - syscall::physmap(bar_ptr as usize, bar_size as usize, PHYSMAP_WRITE | PHYSMAP_NO_CACHE) - .expect("xhcid: failed to map address") - }; - let all_pci_features = pcid_handle.fetch_all_features().expect("xhcid: failed to fetch pci features"); info!("XHCI PCI FEATURES: {:?}", all_pci_features); @@ -127,7 +100,7 @@ fn main() { msix_enabled = true; } - let (mut irq_file, interrupt_method) = if msi_enabled && !msix_enabled { + if msi_enabled && !msix_enabled { use pcid_interface::msi::x86_64::{DeliveryMode, self as x86_64_msix}; let mut capability = match pcid_handle.feature_info(PciFeature::MsiX).expect("xhcid: failed to retrieve the MSI capability structure from pcid") { @@ -226,8 +199,58 @@ fn main() { } else { // no interrupts at all (None, InterruptMethod::Polling) + } +} + +//TODO: MSI on non-x86_64? +#[cfg(not(target_arch = "x86_64"))] +fn get_int_method(pcid_handle: &mut PcidServerHandle) -> (Option, InterruptMethod) { + let pci_config = pcid_handle.fetch_config().expect("xhcid: failed to fetch config"); + let irq = pci_config.func.legacy_interrupt_line; + + if pci_config.func.legacy_interrupt_pin.is_some() { + // legacy INTx# interrupt pins. + (Some(File::open(format!("irq:{}", irq)).expect("xhcid: failed to open legacy IRQ file")), InterruptMethod::Intx) + } else { + // no interrupts at all + (None, InterruptMethod::Polling) + } +} + +fn main() { + // Daemonize + if unsafe { syscall::clone(CloneFlags::empty()).unwrap() } != 0 { + return; + } + + let _logger_ref = setup_logging(); + + let mut pcid_handle = PcidServerHandle::connect_default().expect("xhcid: failed to setup channel to pcid"); + let pci_config = pcid_handle.fetch_config().expect("xhcid: failed to fetch config"); + info!("XHCI PCI CONFIG: {:?}", pci_config); + + let bar = pci_config.func.bars[0]; + let bar_size = pci_config.func.bar_sizes[0]; + let irq = pci_config.func.legacy_interrupt_line; + + let mut name = pci_config.func.name(); + name.push_str("_xhci"); + + let bar_ptr = match bar { + pcid_interface::PciBar::Memory(ptr) => match ptr { + 0 => panic!("BAR 0 is mapped to address 0"), + _ => ptr, + }, + other => panic!("Expected memory bar, found {}", other), }; + let address = unsafe { + syscall::physmap(bar_ptr as usize, bar_size as usize, PHYSMAP_WRITE | PHYSMAP_NO_CACHE) + .expect("xhcid: failed to map address") + }; + + let (mut irq_file, interrupt_method) = get_int_method(&mut pcid_handle); + print!( "{}", format!(" + XHCI {} on: {} IRQ: {}\n", name, bar, irq) diff --git a/xhcid/src/xhci/context.rs b/xhcid/src/xhci/context.rs index e6f56427e6..c40f000805 100644 --- a/xhcid/src/xhci/context.rs +++ b/xhcid/src/xhci/context.rs @@ -182,7 +182,7 @@ impl ScratchpadBufferArray { let pages = entries.iter_mut().map(|entry: &mut ScratchpadBufferEntry| -> Result { let pointer = unsafe { syscall::physalloc(page_size)? }; - assert_eq!(pointer & 0xFFFF_FFFF_FFFF_F000, pointer, "physically allocated pointer (physalloc) wasn't 4k page-aligned"); + assert_eq!((pointer as u64) & 0xFFFF_FFFF_FFFF_F000, pointer as u64, "physically allocated pointer (physalloc) wasn't 4k page-aligned"); entry.set_addr(pointer as u64); Ok(pointer) }).collect::, _>>()?; diff --git a/xhcid/src/xhci/ring.rs b/xhcid/src/xhci/ring.rs index 8326217858..ae7da564b4 100644 --- a/xhcid/src/xhci/ring.rs +++ b/xhcid/src/xhci/ring.rs @@ -66,8 +66,8 @@ impl Ring { /// # Panics /// Panics if paddr is not a multiple of 16 bytes, i.e. the size of a TRB. pub fn phys_addr_to_index(&self, ac64: bool, paddr: u64) -> Option { - let base = self.trbs.physical() & if ac64 { 0xFFFF_FFFF_FFFF_FFFF } else { 0xFFFF_FFFF }; - let offset = paddr.checked_sub(base as u64)? as usize; + let base = (self.trbs.physical() as u64) & if ac64 { 0xFFFF_FFFF_FFFF_FFFF } else { 0xFFFF_FFFF }; + let offset = paddr.checked_sub(base)? as usize; assert_eq!(offset % mem::size_of::(), 0, "unaligned TRB physical address"); diff --git a/xhcid/src/xhci/trb.rs b/xhcid/src/xhci/trb.rs index a26a28f626..66d30437be 100644 --- a/xhcid/src/xhci/trb.rs +++ b/xhcid/src/xhci/trb.rs @@ -245,8 +245,8 @@ impl Trb { pub fn address_device(&mut self, slot_id: u8, input_ctx_ptr: usize, bsr: bool, cycle: bool) { assert_eq!( - input_ctx_ptr & 0xFFFF_FFFF_FFFF_FFF0, - input_ctx_ptr, + (input_ctx_ptr as u64) & 0xFFFF_FFFF_FFFF_FFF0, + input_ctx_ptr as u64, "unaligned input context ptr" ); self.set( @@ -261,8 +261,8 @@ impl Trb { // Synchronizes the input context endpoints with the device context endpoints, I think. pub fn configure_endpoint(&mut self, slot_id: u8, input_ctx_ptr: usize, cycle: bool) { assert_eq!( - input_ctx_ptr & 0xFFFF_FFFF_FFFF_FFF0, - input_ctx_ptr, + (input_ctx_ptr as u64) & 0xFFFF_FFFF_FFFF_FFF0, + input_ctx_ptr as u64, "unaligned input context ptr" ); @@ -276,8 +276,8 @@ impl Trb { } pub fn evaluate_context(&mut self, slot_id: u8, input_ctx_ptr: usize, bsr: bool, cycle: bool) { assert_eq!( - input_ctx_ptr & 0xFFFF_FFFF_FFFF_FFF0, - input_ctx_ptr, + (input_ctx_ptr as u64) & 0xFFFF_FFFF_FFFF_FFF0, + input_ctx_ptr as u64, "unaligned input context ptr" ); self.set(