linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* kmap_atomic and preemption
@ 2016-05-04 10:37 Vineet Gupta
  2016-05-04 13:47 ` Peter Zijlstra
  0 siblings, 1 reply; 9+ messages in thread
From: Vineet Gupta @ 2016-05-04 10:37 UTC (permalink / raw)
  To: Peter Zijlstra, Nicolas Pitre, Andrew Morton, David Hildenbrand,
	Thomas Petazzoni, Russell King
  Cc: lkml, linux-mm@kvack.org, linux-arch@vger.kernel.org

Hi,

I was staring at some recent ARC highmem crashes and see that kmap_atomic()
disables preemption even when page is in lowmem and call returns right away.
This seems to be true for other arches as well.

arch/arc/mm/highmem.c:

void *kmap_atomic(struct page *page)
{
	int idx, cpu_idx;
	unsigned long vaddr;

	preempt_disable();
	pagefault_disable();
	if (!PageHighMem(page))
		return page_address(page);

        /* do the highmem foo ... */
..
}

I would really like to implement a inline fastpath for !PageHighMem(page) case and
do the highmem foo out-of-line.

Is preemption disabling a requirement of kmap_atomic() callers independent of
where page is or is it only needed when page is in highmem and can trigger page
faults or TLB Misses between kmap_atomic() and kunmap_atomic and wants protection
against reschedules etc.

-Vineet

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: kmap_atomic and preemption
  2016-05-04 10:37 kmap_atomic and preemption Vineet Gupta
@ 2016-05-04 13:47 ` Peter Zijlstra
  2016-05-04 13:53   ` Thomas Petazzoni
                     ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Peter Zijlstra @ 2016-05-04 13:47 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: Nicolas Pitre, Andrew Morton, David Hildenbrand, Thomas Petazzoni,
	Russell King, lkml, linux-mm@kvack.org,
	linux-arch@vger.kernel.org

On Wed, May 04, 2016 at 04:07:40PM +0530, Vineet Gupta wrote:
> Hi,
> 
> I was staring at some recent ARC highmem crashes and see that kmap_atomic()
> disables preemption even when page is in lowmem and call returns right away.
> This seems to be true for other arches as well.
> 
> arch/arc/mm/highmem.c:
> 
> void *kmap_atomic(struct page *page)
> {
> 	int idx, cpu_idx;
> 	unsigned long vaddr;
> 
> 	preempt_disable();
> 	pagefault_disable();
> 	if (!PageHighMem(page))
> 		return page_address(page);
> 
>         /* do the highmem foo ... */
> ..
> }
> 
> I would really like to implement a inline fastpath for !PageHighMem(page) case and
> do the highmem foo out-of-line.
> 
> Is preemption disabling a requirement of kmap_atomic() callers independent of
> where page is or is it only needed when page is in highmem and can trigger page
> faults or TLB Misses between kmap_atomic() and kunmap_atomic and wants protection
> against reschedules etc.

Traditionally kmap_atomic() disables preemption; and the reason is that
the returned pointer must stay valid. This had a side effect in that it
also disabled pagefaults.

We've since de-coupled the pagefault from the preemption thing, so you
could disable pagefaults while leaving preemption enabled.

Now, I've also done preemptible kmap_atomic() on -rt; which appears to
work, suggesting nothing relies on it disabling preemption (on -rt).

So sure; you can try and leave preemption enabled for lowmem pages, see
what comes apart -- if anything. It gives weird semantics for
kmap_atomic() though, and I'm not sure the cost of doing that
preempt_disable/preempt_enable() is worth the pain.

If you want a fast-slow path splt, you can easily do something like:


static inline void *kmap_atomic(struct page *page)
{
	preempt_disable();
	pagefault_disable();
	if (!PageHighMem(page))
		return page_address(page);

	return __kmap_atomic(page);
}

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: kmap_atomic and preemption
  2016-05-04 13:47 ` Peter Zijlstra
@ 2016-05-04 13:53   ` Thomas Petazzoni
  2016-05-04 14:01     ` Vineet Gupta
  2016-05-04 14:16   ` Vineet Gupta
  2016-05-04 19:17   ` Russell King - ARM Linux
  2 siblings, 1 reply; 9+ messages in thread
From: Thomas Petazzoni @ 2016-05-04 13:53 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Vineet Gupta, Nicolas Pitre, Andrew Morton, David Hildenbrand,
	Russell King, lkml, linux-mm@kvack.org,
	linux-arch@vger.kernel.org

Hello,

On Wed, 4 May 2016 15:47:29 +0200, Peter Zijlstra wrote:

> static inline void *kmap_atomic(struct page *page)
> {
> 	preempt_disable();
> 	pagefault_disable();
> 	if (!PageHighMem(page))
> 		return page_address(page);
> 
> 	return __kmap_atomic(page);
> }

This is essentially what has been done on ARM in commit
9ff0bb5ba60638a688a46e93df8c5009896672eb, showing a pretty significant
improvement in network workloads.

Best regards,

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: kmap_atomic and preemption
  2016-05-04 13:53   ` Thomas Petazzoni
@ 2016-05-04 14:01     ` Vineet Gupta
  0 siblings, 0 replies; 9+ messages in thread
From: Vineet Gupta @ 2016-05-04 14:01 UTC (permalink / raw)
  To: Thomas Petazzoni, Peter Zijlstra
  Cc: Nicolas Pitre, Andrew Morton, David Hildenbrand, Russell King,
	lkml, linux-mm@kvack.org, linux-arch@vger.kernel.org

On Wednesday 04 May 2016 07:23 PM, Thomas Petazzoni wrote:
> Hello,
>
> On Wed, 4 May 2016 15:47:29 +0200, Peter Zijlstra wrote:
>
>> static inline void *kmap_atomic(struct page *page)
>> {
>> 	preempt_disable();
>> 	pagefault_disable();
>> 	if (!PageHighMem(page))
>> 		return page_address(page);
>>
>> 	return __kmap_atomic(page);
>> }
> This is essentially what has been done on ARM in commit
> 9ff0bb5ba60638a688a46e93df8c5009896672eb, showing a pretty significant
> improvement in network workloads.

ARC already has that semantically - only not inline ! I really want to avoid 2
needless LD-ADD-ST for the disabling of preemption and page fault for the low mem
pages by returning early !

static inline void *kmap_atomic(struct page *page)
{
        if (!PageHighMem(page))
		return page_address(page);

	preempt_disable();
	pagefault_disable();
	
	return __kmap_atomic(page);

}

>
> Best regards,
>
> Thomas


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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: kmap_atomic and preemption
  2016-05-04 13:47 ` Peter Zijlstra
  2016-05-04 13:53   ` Thomas Petazzoni
@ 2016-05-04 14:16   ` Vineet Gupta
  2016-05-04 15:01     ` Peter Zijlstra
  2016-05-04 19:17   ` Russell King - ARM Linux
  2 siblings, 1 reply; 9+ messages in thread
From: Vineet Gupta @ 2016-05-04 14:16 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Nicolas Pitre, Andrew Morton, David Hildenbrand, Thomas Petazzoni,
	Russell King, lkml, linux-mm@kvack.org,
	linux-arch@vger.kernel.org

On Wednesday 04 May 2016 07:17 PM, Peter Zijlstra wrote:
> On Wed, May 04, 2016 at 04:07:40PM +0530, Vineet Gupta wrote:
>> Is preemption disabling a requirement of kmap_atomic() callers independent of
>> where page is or is it only needed when page is in highmem and can trigger page
>> faults or TLB Misses between kmap_atomic() and kunmap_atomic and wants protection
>> against reschedules etc.
> Traditionally kmap_atomic() disables preemption; and the reason is that
> the returned pointer must stay valid. This had a side effect in that it
> also disabled pagefaults.

But how could the ptr possibly get invalid. Say despite the disable calls, we
could actually take the page fault (or TLB Miss on ARC) - the pagefault_disable()
only makes do_page_fault() do reduced handling vs. calling handle_mm_fault() etc.
It is essentially restricting the fault handling to a kernel mode fixup only.

Now if we didn't do disable, on ARC the semantics of do_page_fault() are still the
same - since the address would be for fixmap which is handled under "kernel" only
category as well.

void do_page_fault(unsigned long address, struct pt_regs *regs)
{

    if (address >= VMALLOC_START) {
        ret = handle_kernel_vaddr_fault(address);
        return;
...
    if (faulthandler_disabled() || !mm)
        goto no_context;
...

> We've since de-coupled the pagefault from the preemption thing, so you
> could disable pagefaults while leaving preemption enabled.

Right - I've seen that patch set from David H.

> ...
>
> If you want a fast-slow path splt, you can easily do something like:
>
> static inline void *kmap_atomic(struct page *page)
> {
> 	preempt_disable();
> 	pagefault_disable();
> 	if (!PageHighMem(page))
> 		return page_address(page);
>
> 	return __kmap_atomic(page);
> }

I actually want to return early for !PageHighMem and avoid the pointless 2
LD-ADD-ST to memory for map and 2 LD-SUB-ST for unmap for regular pages for such
cases.


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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: kmap_atomic and preemption
  2016-05-04 14:16   ` Vineet Gupta
@ 2016-05-04 15:01     ` Peter Zijlstra
  2016-05-05 12:37       ` Vineet Gupta
  0 siblings, 1 reply; 9+ messages in thread
From: Peter Zijlstra @ 2016-05-04 15:01 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: Nicolas Pitre, Andrew Morton, David Hildenbrand, Thomas Petazzoni,
	Russell King, lkml, linux-mm@kvack.org,
	linux-arch@vger.kernel.org

On Wed, May 04, 2016 at 02:16:11PM +0000, Vineet Gupta wrote:
> > static inline void *kmap_atomic(struct page *page)
> > {
> > 	preempt_disable();
> > 	pagefault_disable();
> > 	if (!PageHighMem(page))
> > 		return page_address(page);
> >
> > 	return __kmap_atomic(page);
> > }
> 
> I actually want to return early for !PageHighMem and avoid the pointless 2
> LD-ADD-ST to memory for map and 2 LD-SUB-ST for unmap for regular pages for such
> cases.

So I'm fairly sure people rely on the fact you cannot have pagefault
inside a kmap_atomic().

But you could potentially get away with leaving preemption enabled. Give
it a try, see if something goes *bang* ;-)

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: kmap_atomic and preemption
  2016-05-04 13:47 ` Peter Zijlstra
  2016-05-04 13:53   ` Thomas Petazzoni
  2016-05-04 14:16   ` Vineet Gupta
@ 2016-05-04 19:17   ` Russell King - ARM Linux
  2016-05-05  9:37     ` Peter Zijlstra
  2 siblings, 1 reply; 9+ messages in thread
From: Russell King - ARM Linux @ 2016-05-04 19:17 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Vineet Gupta, Nicolas Pitre, Andrew Morton, David Hildenbrand,
	Thomas Petazzoni, lkml, linux-mm@kvack.org,
	linux-arch@vger.kernel.org

On Wed, May 04, 2016 at 03:47:29PM +0200, Peter Zijlstra wrote:
> Traditionally kmap_atomic() disables preemption; and the reason is that
> the returned pointer must stay valid. This had a side effect in that it
> also disabled pagefaults.

A lowmem page should never change its page_address(), so that much is
safe.  I think the question is whether there is any driver code which
assumes that preemption is unconditionally disabled between a
kmap_atomic() has been called.

That wouldn't be an unreasonable assumption given the name of the
function, so I'd suggest caution with making kmap_atomic() have these
kinds of differing behaviours depending on whether we're asking to
kmap a high or lowmem page.

If we are going to allow this, I think it at least needs to be well
documented.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: kmap_atomic and preemption
  2016-05-04 19:17   ` Russell King - ARM Linux
@ 2016-05-05  9:37     ` Peter Zijlstra
  0 siblings, 0 replies; 9+ messages in thread
From: Peter Zijlstra @ 2016-05-05  9:37 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Vineet Gupta, Nicolas Pitre, Andrew Morton, David Hildenbrand,
	Thomas Petazzoni, lkml, linux-mm@kvack.org,
	linux-arch@vger.kernel.org

On Wed, May 04, 2016 at 08:17:55PM +0100, Russell King - ARM Linux wrote:
> On Wed, May 04, 2016 at 03:47:29PM +0200, Peter Zijlstra wrote:
> > Traditionally kmap_atomic() disables preemption; and the reason is that
> > the returned pointer must stay valid. This had a side effect in that it
> > also disabled pagefaults.
> 
> A lowmem page should never change its page_address(), so that much is
> safe. 

Agreed..

> I think the question is whether there is any driver code which
> assumes that preemption is unconditionally disabled between a
> kmap_atomic() has been called.

right, this and consistency. Having the function disable preemption
sometimes is just plain weird.

> That wouldn't be an unreasonable assumption given the name of the
> function, so I'd suggest caution with making kmap_atomic() have these
> kinds of differing behaviours depending on whether we're asking to
> kmap a high or lowmem page.

So for -rt I did a preemptible kmap_atomic() for x86 (and maybe someone
did other archs too, I cannot remember), now -rt is funny wrt locking
anyway, but I cannot remember anything breaking because of this, so
there is some hope it will actually work.

> If we are going to allow this, I think it at least needs to be well
> documented.

Indeed.

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: kmap_atomic and preemption
  2016-05-04 15:01     ` Peter Zijlstra
@ 2016-05-05 12:37       ` Vineet Gupta
  0 siblings, 0 replies; 9+ messages in thread
From: Vineet Gupta @ 2016-05-05 12:37 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Nicolas Pitre, Andrew Morton, David Hildenbrand, Thomas Petazzoni,
	Russell King, lkml, linux-mm@kvack.org,
	linux-arch@vger.kernel.org

On Wednesday 04 May 2016 08:31 PM, Peter Zijlstra wrote:
> So I'm fairly sure people rely on the fact you cannot have pagefault
> inside a kmap_atomic().

So this translates to: any hardware page faults inside kmap_atomic() can't lead to
do_page_fault() taking a lock - those can only be ex_table fixups, yes ?
Could you please also help explain your earlier comment about kmap_atomic needing
to disable preemption so that "returned pointer stayed valid". I can't quite
fathom how that can happen

> But you could potentially get away with leaving preemption enabled. Give
> it a try, see if something goes *bang* ;-)

So tried patch further below: on a quad core slowish FPGA setup, concurrent
hackbench and LMBench seem to run w/o issues  - so it is not obviously broken even
if not proven otherwise. But the point is highmem page is a slow path anyways -
needs a PTE update, new TLB entry etc. I hoped to not wiggle even a single cache
line for the low page - but seems like that is not possible.

OTOH, if we do keep the status quo - then making these 2 cache lines into 1 is not
possible either. From reading the orig "decoupling of prremption and page fault"
thread it seems to be because preempt count is per cpu on x86.

@@ -67,7 +67,6 @@ void *kmap_atomic(struct page *page)
        int idx, cpu_idx;
        unsigned long vaddr;
 
-       preempt_disable();
        pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
@@ -107,7 +106,6 @@ void __kunmap_atomic(void *kv)
        }
 
        pagefault_enable();
-       preempt_enable();
 }


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

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-05-05 12:37 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-04 10:37 kmap_atomic and preemption Vineet Gupta
2016-05-04 13:47 ` Peter Zijlstra
2016-05-04 13:53   ` Thomas Petazzoni
2016-05-04 14:01     ` Vineet Gupta
2016-05-04 14:16   ` Vineet Gupta
2016-05-04 15:01     ` Peter Zijlstra
2016-05-05 12:37       ` Vineet Gupta
2016-05-04 19:17   ` Russell King - ARM Linux
2016-05-05  9:37     ` Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).