Search code examples
linuxpointerskernelsemantics

"address_space()" definition as a "Sparse" annotation in the linux kernel


I came across some macros with the definitions like this:

#ifdef __CHECKER__
# define __user     __attribute__((noderef, address_space(1)))

And I know those are merely to be used with sparse(__CHECKER__) and GCC ignores them completely.But what I don't get is that what does address_space() actually mean? What are the possible values for it? Looks like the only documentation for it is a post from linus in the mailing list around 16 years ago which says:

When you do use parse, it is another matter entirely. For "sparse", that "__iomem" has lots of meaning:
# define __iomem __attribute__((noderef, address_space(2)))

ie "iomem" means two separate things: it means that sparse should complain if the pointer is ever dereferenced (it's a "noderef" pointer) directly, and it's in "address space 2" as opposed to the normal address space (0).

From similar Q&As like this and this I figured out that 3 means per-cpu pointers and 1 seems to be related to the pointers received from userspace.And also 0 for normal pointers.

But what does address_space(2) actually mean?
Are {0,1,2,3} the only possible values?

Thanks.


Solution

  • address_space() and noderef are attributes. What may be confusing is that they are not GCC attributes. They are Sparse attributes and so they only are meaningful to Sparse when __CHECKER__ is defined and Sparse is enabled.

    address_space() attribute puts a specific restriction on a pointer marking it as such. My understanding is that the numbers that are arguments were chosen arbitrarily and denote that a pointer belongs to a certain class. Thus, if you follow the rules, you should clearly annotate a pointer as belonging to a specific class (such as __user or __iomem, etc) and not mix pointers from different classes. Using these annotations, Sparse as a static checker helps you to spot cases of incorrect usage.

    For address_space(2) aka __iomem I have found a good description here: What is the use of __iomem in linux while writing device drivers? The post from Linus is a excellent description as well.

    Besides {0,1,2,3} there's also {4} which marks __rcu pointers as a separate class. I don't think there are more at this time.