Messages in this thread | | | Date | Fri, 13 Nov 1998 06:29:52 +0000 | From | Jamie Lokier <> | Subject | Re: virt_to_bus and >1G of memory (was MAX_DMA_ADDRESS ...) |
| |
On Thu, Nov 12, 1998 at 09:07:38AM +0000, Linus Torvalds wrote: > But the one using logical operations is safer in the presense of old > drivers that don't do the right thing. There are some historical > drivers that may mix physical and virtual addresses, and just masking > off (or turning on) the high bits makes them work even though they > shouldn't. > > For 2.3.x we definitely want to use the +-PAGE_OFFSET version.
There are indeed lots of mistakes, bugs and pitfalls with the existing implementation.
One thing I've seen in some drivers is that virt_to_bus doesn't work on a user-space address, _or_ an address in a module. So some drivers do some pte lookups to get the right value. Those things don't work on addresses in kernel space (because of 4M pages), but they do work on addresses in a kernel module!
Fair enough technically, but the information that an address is (or may be) in paged space isn't made very clear as these values are passed around. unsigned longs are also passed around as virtual addresses from time to time, which only makes things more confusing.
Then there are drivers which do virt_to_bus and bus_to_virt willy-nilly. I'm under the impression from IO-mapping.txt that not every bus address has a valid virt address. (Need ioremap in _some_, poorly specified cases). And not every virt address has a valid bus address. But the translation macros never return error codes and don't, in general, even check the address ranges. Though some do (e.g. some ARM ones).
I'm of the opinion that (1) the address translation functions should at least check the address ranges and print loud messages when they're wrong (this can be done efficiently with a test and branch like the locking functions); (2) all drivers should use ioremap/iounmap, which should not do anything when the bus addresses are in the directly addressable range.
Another possibility is to wrap the various address types in a struct, just like the debugging code for pte_t et al.
E.g., ioaddr_t (bus), physaddr_t (CPU physical), kaddr_t (kernel virtual), uaddr_t (user space) and char * (anything addressable in the kernel -- all or kaddr_t and user-space and module addresses). Or some other scheme.
I understand EGCS is getting better at treating structs containing a single field as efficiently is plain old longs, so it might be reasonably to enforce this typing. That would catch a lot of translation errors.
Er, there's always C++ to automate conversions... Didn't think so ;-)
-- Jamie
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |