linux __iomem

来源:互联网 发布:淘宝麦克先生 编辑:程序博客网 时间:2024/05/16 07:25

__iomem是linux2.6.9内核中加入的特性。是用来个表示指针是指向一个I/O的内存空间。

主要是为了驱动程序的通用性考虑。由于不同的CPU体系结构对I/O空间的表示可能不同。

当使用__iomem时,编译器会忽略对变量的检查(因为用的是void __iomem)。

若要对它进行检查,当__iomem的指针和正常的指针混用时,就会发出一些警告。

见http://lwn.net/Articles/102240/

From: Linus Torvalds <torvalds-AT-osdl.org>To: Kernel Mailing List <linux-kernel-AT-vger.kernel.org>Subject: Being more anal about iospace accesses..Date: Wed, 15 Sep 2004 09:30:42 -0700 (PDT)

This is a background mail mainly for driver writers and/or architecturepeople. Or others that are just interested in really low-level hw accessdetails. Others - please feel free to ignore.[ This has been discussed to some degree already on the architecture   mailing lists and obviously among the people who actually worked on it,   but I thought I'd bounce it off linux-kernel too, in order to make  people more aware of what the new type-checking does. Most people may  have seen it as only generating a ton of new warnings for some crufty  device drivers. ]The background for this iospace type-checking change is that we've longhad some serious confusion about how to access PCI memory mapped IO(MMIO), mainly because on a PC (and some non-PC's too) that IO really does look like regular memory, so you can have a driver that just accesses a pointer directly, and it will actually work on most machines.At the same time, we've had the proper "accessor" functions (read[bwl](), write[bwl]() and friends) that on purpose dropped all type information from the MMIO pointer, mostly just because of historical reasons, and as a result some drivers didn't use a pointer at all, but some kind of integer. Sometimes even one that couldn't _fit_ a MMIO address in it on a 64-bit machine.In short, the PCI MMIO access case was largely the same as the userpointer case, except the access functions were different (readb vsget_user) and they were even less lax about checking for sanity. At leastthe user access code required a pointer with the right size.We've been very successful in annotating user pointers, and that found acouple of bugs, and more importantly it made the kernel code much more"aware" of what kind of pointer was passed around. In general, a bigsuccess, I think. And an obvious example for what MMIO pointers should do.So lately, the kernel infrastructure for MMIO accesses has become a _lot_more strict about what it accepts. Not only do the MMIO access functionswant a real pointer (which is already more type-checking than we didbefore, and causes gcc to spew out lots of warnings for some drivers), but as with user pointers, sparse annotations mark them as being in a different address space, and building the kernel with checking on will warn about mixing up address spaces. So far so good.So right now the current snapshots (and 2.6.9-rc2) have this enabled, andsome drivers will be _very_ noisy when compiled. Most of the regular onesare fine, so maybe people haven't even noticed it that much, but some ofthem were using things like "u32" to store MMIO pointers, and aregenerally extremely broken on anything but an x86.  We'll hopefully getaround to fixing them up eventually, but in the meantime this should at least explain the background for some of the new noise people may see.Perhaps even more interesting is _another_ case of driver, though: onethat started warning not because it was ugly and broken, but because itdid something fairly rare but something that does happen occasionally: itmixed PIO and MMIO accesses on purpose, because it drove hardware thatliterally uses one or the other.Sometimes such a "mixed interface" driver does it based on a compileoption that just #defines 'writel()' to 'inl()', sometimes it's a runtimedecision depending on the hardware or configuration. The anal typechecking obviously ended up being very unhappy about this, since it wants "void __iomem *" for MMIO pointers, and a normal "unsigned long" for PIO accesses. The compile-time option could have been easily fixed up by adding the proper cast when re-defining the IO accessor, but that doesn't work for the dynamic case.Also, the compile-time switchers often really _wanted_ to be dynamic, butit was just too painful with the regular Linux IO interfaces to duplicate the code and do things conditionally one way or the other.To make a long story even longer: rather than scrapping the typechecking,or requiring drivers to do strange and nasty casts all over the place,there's now a new interface in town. It's called "iomap", because itextends the old "ioremap()" interface to work on the PIO accesses too.That way, the drivers that really want to mix both PIO and MMIO accessescan very naturally do it: they just need to remap the PIO space too, thesame way that we've required people to remap the MMIO space for a longlong time.For example, if you don't know (or, more importantly - don't care) what kind of IO interface you use, you can now do something likevoid __iomem * map = pci_iomap(dev, bar, maxbytes);...status = ioread32(map + DRIVER_STATUS_OFFSET);and it will do the proper IO mapping for the named PCI BAR for thatdevice. Regardless of whether the BAR was an IO or MEM mapping. Veryconvenient for cases where the hardware migt expose its IO window ineither (or sometimes both).Nothing in the current tree actually uses this new interface, althoughJeff has patches for SATA for testing (and they clean up the code quitenoticeably, never mind getting rid of the warnings).  The interface hasbeen implemented by yours truly for x86 and ppc64, and David did afirst-pass version for sparc64 too (missing the "xxxx_rep()" functionsthat were added a bit later, I believe).So far experience seems to show that it's a very natural interface formost non-x86 hardware - they all tend to map in both PIO and MMIO into oneaddress space _anyway_, so the two aren't really any different. It'smainly just x86 and it's ilk that actually have two different interfacesfor the two kinds of PCI accesses, and at least in that case it's trivialto encode the difference in the virtual ioremap pointer.The best way to explain the interface is to just point you guys at the<asm-generic/iomap.h> file, which isn't very big, has about as muchcomments than code, and contains nothing but the necessary functiondeclarations. The actual meaning of the functions should be prettyobvious even without the comments.Feel free to flame or discuss rationally,Linus