Re: Question/clarification on pmd accessors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Aneesh,

On Sun, Nov 02, 2014 at 07:18:46PM +0530, Aneesh Kumar K.V wrote:
> 
> Hi Andrea,
> 
> This came up when I was looking at how best we can implement generic GUP
> that can also handle sparc usecase. Below are the pmd accessors that
> would be nice to get documented. 
> 
> pmd_present():
>         I guess we should return true for both pointer to pte page and
>         huge page pte (THP and explicit hugepages). We will always find
>         THP and explicit hugepage present. If so how is it
>         different from pmd_none() ? (There is an expection of
>         __split_huge_page_map marking the pmd not
>         present. Should pmd_present() return false in that case ?)
> 
> pmd_none():
>         In some arch it is same as !pmd_present(). I am
>         not sure that is correct. Can we explain the difference between
>         !pmd_present and pmd_none ?

Originally pmd_present was different than !pmd_none. So I used
!pmd_none instead of pmd_present in some places to cover for the
pmdp_invalidate and pmd_mknotpresent race window (back when
pmd_present wouldn't return true unless the _PAGE_PRESENT bit was
set). However some place that still used pmd_present and wasn't
converted to a !pmd_none, got confused by the pmd_mknotpresent that
split_huge_page has to go through for the pmdp_invalidate() call
(immediately followed by pmd_populate).

The implementation of pmdp_invalidate with pmd_mknotpresent is
required to prevent TLBs of multiple size simultaneously co-existing
for the same physical page (some CPU need it and it sounds safer
anyway because at least one TLB flush after those two lines would be
needed anyway after the pmdp_establish, and the TLB flush is the only
runtime cost, the pmd_mknotpresent not).

These days they are equivalent, the details of this change is in
commit 027ef6c87853b0a9df53175063028edb4950d476.

The old behavior of pmd_present just happened to be a lowlevel version
that would show the effect of a pmd_mknotpresent, except it wasn't
useful like that, and it just created a tiny race window for some
places.

After the above commit they are equivalent and in fact as the commit
header already hinted, we could actually delete pmd_present and just
use !pmd_none.

The only reason I didn't delete pmd_present is that conceptually it is
different, and it is required in order to later swapout THP natively
in 2M blocks. If THP are swapped out natively pmd_present would be
false and pmd_none would be false, so they wouldn't be equivalent
anymore.

In short pmd_present/pmd_none are conceptually identical to
pte_present/pte_none, except we can't swap THP natively yet so
pmd_present and !pmd_none are practically the same now.

> pmd_trans_huge():
>         pmd value that represent a hugepage built via THP mechanism.
>         Also implies present.

pmd_trans_huge() would return true on a hugetlbfs hugepage too, just
by design pmd_trans_huge can never be run on any hugetlbfs page. The
hugetlbfs page table walking and mangling paths are totally separated
form the core VM paths and they're differentiated by VM_HUGETLB being
set on vm_flags well before any pmd_trans_huge could run.

pmd_trans_huge() is defined as false at build time if
CONFIG_TRANSPARENT_HUGEPAGE=n to optimize away code blocks at build
time in such case.

> pmd_huge():
>         Should cover both the THP and explicit hugepages

Yes, because they work the same, but again the difference here is made
by the fact pmd_huge is hugetlbfs private thing, and by design it's
never run by design on any pmd that could possibly point to a THP
page by differentiating using the VM_HUGETLB flag in vm_flags.

Following the same lines of pmd_trans_huge, pmd_huge is also defined
as 0 at build time if CONFIG_HUGETLB_PAGE=n.

They both are optimized away or not depending on
CONFIG_HUGETLB_PAGE=y/n and CONFIG_TRANSPARENT_HUGEPAGE=y/n at build
time.

> pmd_large():
>         This is confusing. On ppc64 this one also check for
>         _PAGE_PRESENT. I don't recollect how we end up with that.

pmd_large is the one that cannot be optimized away and it is only used
by the arch code (like pageattr) where it must be always available if
needed.

The whole exercise for pmd_huge/pmd_trans_huge is about optimizing
away code blocks at build time depending on config options and they're
doing the same thing (pmd_huge just with a slighter slower variation
with !! to return 0/1 instead of 0/_PAGE_PSE), but they're mutually
exclusive by design through the VM_HUGETLB vm_flags and the totally
separate paths of hugetlbfs vs core VM.

Thanks,
Andrea

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxx.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]