5 ms·
> with abstractions that don't require interaction with the rest of the system I have no idea what this is supposed to mean. Drivers obviously interact with ea
by megous 5y ago
> with abstractions that don't require interaction with the rest of the system
I have no idea what this is supposed to mean. Drivers obviously interact with each other and with the rest of the system via all kinds of in-kernel interfaces.
Drivers are also not inherently system dependent. Even the sample rust driver is for android binder, which is not a real HW device, but some kind of IPC mechanism. So that one is quite system independent.
- tatref 5y agoThe target architectures of the rust compiler are very limited compared to GCC. So if you port some core functionality of the kernel to rust, that would make rust a hard dependency for the whole kernel.
- megous 5y agoYou missed the point.
- fault1 5y agoOTOH, it may cause companies to invest in creating a well maintained Rust frontend for gcc. People have already done much of the grunt work for this, so it seems like it's just a matter of manpower, and something that acceptance into the edges of the kernel might cause more investment in.
- Tuna-Fish 5y ago> I have no idea what this is supposed to mean. Drivers obviously interact with each other and with the rest of the system via all kinds of in-kernel interfaces. But the total footprint of the interfaces that typical drivers use is fairly small. When a rusty shim is provided that provides access to those interfaces, you can write pure rust drivers.
- megous 5y agoTypical device drivers with limited interface footprint also barely do anything interesting. For example look at typical audio codec drivers. They barely have any procedural code (and when they do it's just some form of register value mapping anyway), locking/concurency and almost all resource management is handled at the higher level and the driver is not exposed to it. Another kind of a driver that features a very limited dependency on Linux interfaces is a SoC clock/reset driver. And clock drivers are even more boring in this aspect. Code vs data ratio is probably < 0.1 in many of those. I guess some drivers that do more complicated stuff, and deal with concurrency issues or more complicated resource management may benefit, but they'll likely need to touch much larger API surface, too. And I dunno, even the sample driver in the patchset has things like this: let mut data = kernel::new_device_data!( gpio::RegistrationWithIrqChip::new(), PL061Resources { // SAFETY: This device doesn't support DMA. base: unsafe { IoMem::try_new(res)? }, parent_irq: irq, }, // SAFETY: We call `spinlock_init` below. unsafe { SpinLock::new(PL061Data::default()) }, "PL061::Registrations" )?; // SAFETY: General part of the data is pinned when `data` is. let gen = unsafe { data.as_mut().map_unchecked_mut(|d| &mut **d) }; kernel::spinlock_init!(gen, "PL061::General"); let data = Ref::<DeviceData>::from(data); It's barely readable. I don't know what type `data` is, what `gen` is or how it's different from `data`. Variable names don't really help. `data.as_mut().map_unchecked_mut(|d| &mut *d)` also looks like some kind of WTF to the uninitiated, that is somehow retrieving some 'general part of data' whatever that is. When I look at the kernel's spinlock type https://elixir.bootlin.com/linux/latest/source/include/linux/spinlock_types.h#L17 https://elixir.bootlin.com/linux/latest/source/include/linux... that doesn't really help me determine why whatever this `gen` [variable?] is needs to be passed to `spinlock_init`. And what's with the two `let data`. Are they the same type or is the type now different and the first data variable now hidden? Because it looks like second `let data` gets somehow transformed from the first `data` into something else. So now we have two identically named `data` variables with different types in the same function? Wasn't this supposed to be some simpler language to draw more people to the kernel development? At least with C each variable has a type that's quickly identifiable. I guess after 15 minutes I see what this is trying to do. It passes some newly created spinlock object to `new_device_data` function and then calls `spinlock_init` on some part of the data returned from `new_device_data` that needs to be extracted from it via some really obtuse transformation, just to initialize the spinlock later instead of directly in `SpinLock::new` for some obscure reason, using two unsafe {} blocks in the process. But oh my god, if this kind of obfuscation is going to be the new standard for the kernel,... At least C is the devil I know. :)
- themulticaster 5y agoMost drivers don't interact with other drivers, only with kernel interfaces. A driver for a PCIe device has to interact with the PCI subsystem, but that subsystem isn't a driver in the traditional sense. Consider this: Does your GPU need to talk to your mouse or your real-time clock? Or does your sound chipset need to talk to your HDD? The answer to both should be no. Even a file system driver does not need to know about the underlying storage driver, since it operates on a block device abstraction. Of course, some kernel modules have dependencies on other kernel modules, but those dependencies generally don't cross subsystem boundaries. (There are of course exceptions to the examples I listed, but the argument should apply to the majority of device drivers.)
- megous 5y agoI guess I have to deal with wrong drivers then, but many of the drivers I had pleasure working with cross many boundaries. For example look at rockchip type-c port stuff I've been looking into last month: There's a phy driver for USB, phy driver for Type-C phy/mux, display port CDN driver, type-c TCPM controller driver, generic alternate mode DP driver, charger power supply driver, and more, and all these have to communicate together (and do so over extcon and type-c mux/role switch/orientation swtich interfaces) USB 2.0 phy driver detects what kind of device is connected using BC1.2 specification (what kind of charger basically), TCPM driver does the same over USB-PD, they race together basically trying to identify how much current the device will be able to draw from the charger. Because they are independent on HW and driver level, one of them takes it upon itself to get the information from the other, and decide what values will get more priority, and passes that over another interface to a charger driver, to make it configure the HW to not overload the power supply connected to the Type C port. This not a driver->subsystem but basically a driver<->driver interaction. There's a ton more communication going on between these 7 or so drivers. TCPM figures out the peer device supports Alt-display port mode, so it will tell the type-c phy to reconfigure itself for 2 SS lanes and 2 alt-dp lanes modes to support parallel use of USB and display output. Displayport CDN driver orchestrates this, but there's a problem that link training is needed for this to work well, and that needs coordination between CDN-DP and Type-C PHY drivers, because there's no standard kernel interface for it. So, yes I see a ton of inter-driver interaction. Many of it kinda ad-hoc, over some not perfectly well matching bus like interface like extcon or direct calls to other drivers, in addition to more common interfaces at the surface of various subsystems like clock, regulator, i2c, etc. Maybe in x86 land this is saner, but in ARM SoC land, the drivers are often not that independent. Things need to happen across drivers in right order with right timing. Not sure if that prevents these drivers to be implemented in rust, likely not, but the api surface is not small or simple, which was what I was trying to point out.