2019-06-11 14:42:11

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH 01/16] mm: use untagged_addr() for get_user_pages_fast addresses

This will allow sparc64 to override its ADI tags for
get_user_pages and get_user_pages_fast.

Signed-off-by: Christoph Hellwig <[email protected]>
---
mm/gup.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/gup.c b/mm/gup.c
index ddde097cf9e4..6bb521db67ec 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2146,7 +2146,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
unsigned long flags;
int nr = 0;

- start &= PAGE_MASK;
+ start = untagged_addr(start) & PAGE_MASK;
len = (unsigned long) nr_pages << PAGE_SHIFT;
end = start + len;

@@ -2219,7 +2219,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages,
unsigned long addr, len, end;
int nr = 0, ret = 0;

- start &= PAGE_MASK;
+ start = untagged_addr(start) & PAGE_MASK;
addr = start;
len = (unsigned long) nr_pages << PAGE_SHIFT;
end = start + len;
--
2.20.1


2019-06-11 23:46:28

by Khalid Aziz

[permalink] [raw]
Subject: Re: [PATCH 01/16] mm: use untagged_addr() for get_user_pages_fast addresses

On 6/11/19 8:40 AM, Christoph Hellwig wrote:
> This will allow sparc64 to override its ADI tags for
> get_user_pages and get_user_pages_fast.
>
> Signed-off-by: Christoph Hellwig <[email protected]>
> ---

Commit message is sparc64 specific but the goal here is to allow any
architecture with memory tagging to use this. So I would suggest
rewording the commit log. Other than that:

Reviewed-by: Khalid Aziz <[email protected]>

> mm/gup.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/mm/gup.c b/mm/gup.c
> index ddde097cf9e4..6bb521db67ec 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -2146,7 +2146,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> unsigned long flags;
> int nr = 0;
>
> - start &= PAGE_MASK;
> + start = untagged_addr(start) & PAGE_MASK;
> len = (unsigned long) nr_pages << PAGE_SHIFT;
> end = start + len;
>
> @@ -2219,7 +2219,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages,
> unsigned long addr, len, end;
> int nr = 0, ret = 0;
>
> - start &= PAGE_MASK;
> + start = untagged_addr(start) & PAGE_MASK;
> addr = start;
> len = (unsigned long) nr_pages << PAGE_SHIFT;
> end = start + len;
>


2019-06-21 13:16:35

by Jason Gunthorpe

[permalink] [raw]
Subject: Re: [PATCH 01/16] mm: use untagged_addr() for get_user_pages_fast addresses

On Tue, Jun 11, 2019 at 04:40:47PM +0200, Christoph Hellwig wrote:
> This will allow sparc64 to override its ADI tags for
> get_user_pages and get_user_pages_fast.
>
> Signed-off-by: Christoph Hellwig <[email protected]>
> ---
> mm/gup.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)

Reviewed-by: Jason Gunthorpe <[email protected]>

2019-06-21 13:41:02

by Jason Gunthorpe

[permalink] [raw]
Subject: Re: [PATCH 01/16] mm: use untagged_addr() for get_user_pages_fast addresses

On Tue, Jun 11, 2019 at 04:40:47PM +0200, Christoph Hellwig wrote:
> This will allow sparc64 to override its ADI tags for
> get_user_pages and get_user_pages_fast.
>
> Signed-off-by: Christoph Hellwig <[email protected]>
> mm/gup.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/mm/gup.c b/mm/gup.c
> index ddde097cf9e4..6bb521db67ec 100644
> +++ b/mm/gup.c
> @@ -2146,7 +2146,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> unsigned long flags;
> int nr = 0;
>
> - start &= PAGE_MASK;
> + start = untagged_addr(start) & PAGE_MASK;
> len = (unsigned long) nr_pages << PAGE_SHIFT;
> end = start + len;

Hmm, this function, and the other, goes on to do:

if (unlikely(!access_ok((void __user *)start, len)))
return 0;

and I thought that access_ok takes in the tagged pointer?

How about re-order it a bit?

diff --git a/mm/gup.c b/mm/gup.c
index ddde097cf9e410..f48747ced4723b 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2148,11 +2148,12 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,

start &= PAGE_MASK;
len = (unsigned long) nr_pages << PAGE_SHIFT;
- end = start + len;
-
if (unlikely(!access_ok((void __user *)start, len)))
return 0;

+ start = untagged_ptr(start);
+ end = start + len;
+
/*
* Disable interrupts. We use the nested form as we can already have
* interrupts disabled by get_futex_key.

2019-06-21 15:37:53

by Khalid Aziz

[permalink] [raw]
Subject: Re: [PATCH 01/16] mm: use untagged_addr() for get_user_pages_fast addresses

On 6/21/19 7:39 AM, Jason Gunthorpe wrote:
> On Tue, Jun 11, 2019 at 04:40:47PM +0200, Christoph Hellwig wrote:
>> This will allow sparc64 to override its ADI tags for
>> get_user_pages and get_user_pages_fast.
>>
>> Signed-off-by: Christoph Hellwig <[email protected]>
>> mm/gup.c | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/mm/gup.c b/mm/gup.c
>> index ddde097cf9e4..6bb521db67ec 100644
>> +++ b/mm/gup.c
>> @@ -2146,7 +2146,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
>> unsigned long flags;
>> int nr = 0;
>>
>> - start &= PAGE_MASK;
>> + start = untagged_addr(start) & PAGE_MASK;
>> len = (unsigned long) nr_pages << PAGE_SHIFT;
>> end = start + len;
>
> Hmm, this function, and the other, goes on to do:
>
> if (unlikely(!access_ok((void __user *)start, len)))
> return 0;
>
> and I thought that access_ok takes in the tagged pointer?
>
> How about re-order it a bit?

access_ok() can handle tagged or untagged pointers. It just strips the
tag bits from the top bits. Current order doesn't really matter from
functionality point of view. There might be minor gain in delaying
untagging in __get_user_pages_fast() but I could go either way.

--
Khalid

>
> diff --git a/mm/gup.c b/mm/gup.c
> index ddde097cf9e410..f48747ced4723b 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -2148,11 +2148,12 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
>
> start &= PAGE_MASK;
> len = (unsigned long) nr_pages << PAGE_SHIFT;
> - end = start + len;
> -
> if (unlikely(!access_ok((void __user *)start, len)))
> return 0;
>
> + start = untagged_ptr(start);
> + end = start + len;
> +
> /*
> * Disable interrupts. We use the nested form as we can already have
> * interrupts disabled by get_futex_key.
>


2019-06-21 15:56:11

by Jason Gunthorpe

[permalink] [raw]
Subject: Re: [PATCH 01/16] mm: use untagged_addr() for get_user_pages_fast addresses

On Fri, Jun 21, 2019 at 09:35:11AM -0600, Khalid Aziz wrote:
> On 6/21/19 7:39 AM, Jason Gunthorpe wrote:
> > On Tue, Jun 11, 2019 at 04:40:47PM +0200, Christoph Hellwig wrote:
> >> This will allow sparc64 to override its ADI tags for
> >> get_user_pages and get_user_pages_fast.
> >>
> >> Signed-off-by: Christoph Hellwig <[email protected]>
> >> mm/gup.c | 4 ++--
> >> 1 file changed, 2 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/mm/gup.c b/mm/gup.c
> >> index ddde097cf9e4..6bb521db67ec 100644
> >> +++ b/mm/gup.c
> >> @@ -2146,7 +2146,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
> >> unsigned long flags;
> >> int nr = 0;
> >>
> >> - start &= PAGE_MASK;
> >> + start = untagged_addr(start) & PAGE_MASK;
> >> len = (unsigned long) nr_pages << PAGE_SHIFT;
> >> end = start + len;
> >
> > Hmm, this function, and the other, goes on to do:
> >
> > if (unlikely(!access_ok((void __user *)start, len)))
> > return 0;
> >
> > and I thought that access_ok takes in the tagged pointer?
> >
> > How about re-order it a bit?
>
> access_ok() can handle tagged or untagged pointers. It just strips the
> tag bits from the top bits. Current order doesn't really matter from
> functionality point of view. There might be minor gain in delaying
> untagging in __get_user_pages_fast() but I could go either way.

I understand the current ARM and SPARC implementations don't do much
with the tags, but it feels like a really big assumption for the core
code that all future uses of tags will be fine to have them stripped
out of 'void __user *' pointers. IMHO that is something we should not
be doing in the core kernel..

Jason

2019-06-25 07:53:31

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 01/16] mm: use untagged_addr() for get_user_pages_fast addresses

On Fri, Jun 21, 2019 at 10:39:11AM -0300, Jason Gunthorpe wrote:
>
> Hmm, this function, and the other, goes on to do:
>
> if (unlikely(!access_ok((void __user *)start, len)))
> return 0;
>
> and I thought that access_ok takes in the tagged pointer?
>
> How about re-order it a bit?

The patch doesn't really work as-as an misses the main
get_user_pages_fast fast path, but I'll add something equivalent.

2019-06-25 07:55:00

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 01/16] mm: use untagged_addr() for get_user_pages_fast addresses

On Fri, Jun 21, 2019 at 10:39:11AM -0300, Jason Gunthorpe wrote:
> Hmm, this function, and the other, goes on to do:
>
> if (unlikely(!access_ok((void __user *)start, len)))
> return 0;
>
> and I thought that access_ok takes in the tagged pointer?
>
> How about re-order it a bit?

Actually.. I we reorder this we'd need to to duplicate a few things
due to the zero/negative length checking. Given the feedback from
Khalid I'd thus rather skip the reorder for now. If we have a good
reason we could add it back, but it would be a bit involved.