Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1270796 > unrolled thread
| Started by | Dave Hansen <dave@sr71.net> |
|---|---|
| First post | 2015-11-17 04:40 +0100 |
| Last post | 2015-11-30 17:30 +0100 |
| Articles | 3 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH 19/37] x86, mm: simplify get_user_pages() PTE bit handling Dave Hansen <dave@sr71.net> - 2015-11-17 04:40 +0100
Re: [PATCH 19/37] x86, mm: simplify get_user_pages() PTE bit handling Thomas Gleixner <tglx@linutronix.de> - 2015-11-27 11:20 +0100
Re: [PATCH 19/37] x86, mm: simplify get_user_pages() PTE bit handling Dave Hansen <dave@sr71.net> - 2015-11-30 17:30 +0100
| From | Dave Hansen <dave@sr71.net> |
|---|---|
| Date | 2015-11-17 04:40 +0100 |
| Subject | [PATCH 19/37] x86, mm: simplify get_user_pages() PTE bit handling |
| Message-ID | <qvFhE-7YL-7@gated-at.bofh.it> |
From: Dave Hansen <dave.hansen@linux.intel.com>
The current get_user_pages() code is a wee bit more complicated
than it needs to be for pte bit checking. Currently, it establishes
a mask of required pte _PAGE_* bits and ensures that the pte it
goes after has all those bits.
This consolidates the three identical copies of this code.
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---
b/arch/x86/mm/gup.c | 46 +++++++++++++++++++++++++++++-----------------
1 file changed, 29 insertions(+), 17 deletions(-)
diff -puN arch/x86/mm/gup.c~pkeys-16-gup-swizzle arch/x86/mm/gup.c
--- a/arch/x86/mm/gup.c~pkeys-16-gup-swizzle 2015-11-16 12:35:43.690550937 -0800
+++ b/arch/x86/mm/gup.c 2015-11-16 12:35:43.693551073 -0800
@@ -63,6 +63,31 @@ retry:
#endif
}
+static inline int pte_allows_gup(pte_t pte, int write)
+{
+ /*
+ * 'entry_flags' can come from a pte, pmd or pud. Make
+ * sure to only check flags here that are valid *and* the
+ * same value on all 3 types. (PAT is currently the only
+ * one where that is true and is not checked here).
+ */
+ if (!(pte_flags(pte) & (_PAGE_PRESENT|_PAGE_USER)))
+ return 0;
+ if (write && !(pte_write(pte)))
+ return 0;
+ return 1;
+}
+
+static inline int pmd_allows_gup(pmd_t pmd, int write)
+{
+ return pte_allows_gup(*(pte_t *)&pmd, write);
+}
+
+static inline int pud_allows_gup(pud_t pud, int write)
+{
+ return pte_allows_gup(*(pte_t *)&pud, write);
+}
+
/*
* The performance critical leaf functions are made noinline otherwise gcc
* inlines everything into a single function which results in too much
@@ -71,13 +96,8 @@ retry:
static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
unsigned long end, int write, struct page **pages, int *nr)
{
- unsigned long mask;
pte_t *ptep;
- mask = _PAGE_PRESENT|_PAGE_USER;
- if (write)
- mask |= _PAGE_RW;
-
ptep = pte_offset_map(&pmd, addr);
do {
pte_t pte = gup_get_pte(ptep);
@@ -88,8 +108,8 @@ static noinline int gup_pte_range(pmd_t
pte_unmap(ptep);
return 0;
}
-
- if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {
+ if (!pte_allows_gup(pte, write) ||
+ pte_special(pte)) {
pte_unmap(ptep);
return 0;
}
@@ -117,14 +137,10 @@ static inline void get_head_page_multipl
static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
unsigned long end, int write, struct page **pages, int *nr)
{
- unsigned long mask;
struct page *head, *page;
int refs;
- mask = _PAGE_PRESENT|_PAGE_USER;
- if (write)
- mask |= _PAGE_RW;
- if ((pmd_flags(pmd) & mask) != mask)
+ if (!pmd_allows_gup(pmd, write))
return 0;
/* hugepages are never "special" */
VM_BUG_ON(pmd_flags(pmd) & _PAGE_SPECIAL);
@@ -193,14 +209,10 @@ static int gup_pmd_range(pud_t pud, unsi
static noinline int gup_huge_pud(pud_t pud, unsigned long addr,
unsigned long end, int write, struct page **pages, int *nr)
{
- unsigned long mask;
struct page *head, *page;
int refs;
- mask = _PAGE_PRESENT|_PAGE_USER;
- if (write)
- mask |= _PAGE_RW;
- if ((pud_flags(pud) & mask) != mask)
+ if (!pud_allows_gup(pud, write))
return 0;
/* hugepages are never "special" */
VM_BUG_ON(pud_flags(pud) & _PAGE_SPECIAL);
_
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2015-11-27 11:20 +0100 |
| Subject | Re: [PATCH 19/37] x86, mm: simplify get_user_pages() PTE bit handling |
| Message-ID | <qzoif-1vq-27@gated-at.bofh.it> |
| In reply to | #1270796 |
On Mon, 16 Nov 2015, Dave Hansen wrote:
> +static inline int pte_allows_gup(pte_t pte, int write)
> +{
> + /*
> + * 'entry_flags' can come from a pte, pmd or pud. Make
> + * sure to only check flags here that are valid *and* the
> + * same value on all 3 types. (PAT is currently the only
> + * one where that is true and is not checked here).
I have a hard time to understand that comment.
/*
* 'entry_flags' can come from a pte, pmd or pud. We only check
* _PAGE_PRESENT, _PAGE_USER and _PAGE_RW here, which are the
* same for all types.
*/
Is that what you wanted to say?
> + */
> + if (!(pte_flags(pte) & (_PAGE_PRESENT|_PAGE_USER)))
> + return 0;
> + if (write && !(pte_write(pte)))
> + return 0;
> + return 1;
> +}
> +
> +static inline int pmd_allows_gup(pmd_t pmd, int write)
> +{
> + return pte_allows_gup(*(pte_t *)&pmd, write);
> +}
> +
> +static inline int pud_allows_gup(pud_t pud, int write)
> +{
> + return pte_allows_gup(*(pte_t *)&pud, write);
> +}
> +
> static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
> unsigned long end, int write, struct page **pages, int *nr)
> {
> - unsigned long mask;
> struct page *head, *page;
> int refs;
>
> - mask = _PAGE_PRESENT|_PAGE_USER;
> - if (write)
> - mask |= _PAGE_RW;
> - if ((pmd_flags(pmd) & mask) != mask)
> + if (!pmd_allows_gup(pmd, write))
Why do you need that extra indirection here of rereading the pmd?
You have the pmd already.
Thanks,
tglx
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Dave Hansen <dave@sr71.net> |
|---|---|
| Date | 2015-11-30 17:30 +0100 |
| Message-ID | <qAzuX-5YC-35@gated-at.bofh.it> |
| In reply to | #1278703 |
On 11/27/2015 02:12 AM, Thomas Gleixner wrote:
> On Mon, 16 Nov 2015, Dave Hansen wrote:
>> +static inline int pte_allows_gup(pte_t pte, int write)
>> +{
>> + /*
>> + * 'entry_flags' can come from a pte, pmd or pud. Make
>> + * sure to only check flags here that are valid *and* the
>> + * same value on all 3 types. (PAT is currently the only
>> + * one where that is true and is not checked here).
>
> I have a hard time to understand that comment.
>
> /*
> * 'entry_flags' can come from a pte, pmd or pud. We only check
> * _PAGE_PRESENT, _PAGE_USER and _PAGE_RW here, which are the
> * same for all types.
> */
>
> Is that what you wanted to say?
Yeah, that's a much better way to say it. I'll fix it up.
>> + */
>> + if (!(pte_flags(pte) & (_PAGE_PRESENT|_PAGE_USER)))
>> + return 0;
>> + if (write && !(pte_write(pte)))
>> + return 0;
>> + return 1;
>> +}
>> +
>> +static inline int pmd_allows_gup(pmd_t pmd, int write)
>> +{
>> + return pte_allows_gup(*(pte_t *)&pmd, write);
>> +}
>> +
>> +static inline int pud_allows_gup(pud_t pud, int write)
>> +{
>> + return pte_allows_gup(*(pte_t *)&pud, write);
>> +}
>> +
>
>> static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr,
>> unsigned long end, int write, struct page **pages, int *nr)
>> {
>> - unsigned long mask;
>> struct page *head, *page;
>> int refs;
>>
>> - mask = _PAGE_PRESENT|_PAGE_USER;
>> - if (write)
>> - mask |= _PAGE_RW;
>> - if ((pmd_flags(pmd) & mask) != mask)
>> + if (!pmd_allows_gup(pmd, write))
>
> Why do you need that extra indirection here of rereading the pmd?
> You have the pmd already.
The intention there was not to re-read the PMD, but only to cast the
structure over to a pte_t. I expected the compiler to be able to figure
out what was going on and not actually re-read anything.
Is that a bad assumption?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web