On Thu, 10 Sep 2020 10:02:33 -0300 Jason Gunthorpe <jgg@xxxxxxxx> wrote: > On Thu, Sep 10, 2020 at 11:39:25AM +0200, Alexander Gordeev wrote: > > > As Gerald mentioned, it is very difficult to explain in a clear way. > > Hopefully, one could make sense ot of it. > > I would say the page table API requires this invariant: > > pud = pud_offset(p4d, addr); > do { > WARN_ON(pud != pud_offset(p4d, addr); > next = pud_addr_end(addr, end); > } while (pud++, addr = next, addr != end); > > ie pud++ is supposed to be a shortcut for > pud_offset(p4d, next) > Hmm, IIUC, all architectures with static folding will simply return the passed-in p4d pointer for pud_offset(p4d, addr), for 3-level pagetables. There is no difference for s390. For gup_fast, that p4d pointer is not really a pointer to a value in a pagetable, but to some local copy of such a value, and not just for s390. So, pud = p4d = pointer to copy, and increasing that pud pointer cannot be the same as pud_offset(p4d, next). I do see your point however, at last I think :-) My problem is that I do not see where we would have an s390-specific issue here. Maybe my understanding of how it works for others with static folding is wrong. That would explain my difficulties in getting your point... > While S390 does not follow this. Fixing addr_end brings it into > alignment by preventing pud++ from happening. Exactly, only that nobody seems to follow it, IIUC. Fixing it up with pXd_addr_end was my impression of what we need to do, in order to have it work the same way as for others. > The only currently known side effect is that gup_fast crashes, but it > sure is an unexpected thing. Well, from my understanding it feels more unexpected that something that is supposed to be a pointer to an entry in a page table, really is just a pointer to some copy somewhere.