Re: [RFC v6 21/62] powerpc: introduce execute-only pkey

2017-08-17 Thread Ram Pai
On Thu, Aug 17, 2017 at 04:35:55PM -0700, Ram Pai wrote:
> On Wed, Aug 02, 2017 at 07:40:46PM +1000, Michael Ellerman wrote:
> > Thiago Jung Bauermann  writes:
> > 
> > > Michael Ellerman  writes:
> > >
> > >> Thiago Jung Bauermann  writes:
> > >>> Ram Pai  writes:
> > >> ...
> >  +
> >  +  /* We got one, store it and use it from here on out */
> >  +  if (need_to_set_mm_pkey)
> >  +  mm->context.execute_only_pkey = execute_only_pkey;
> >  +  return execute_only_pkey;
> >  +}
> > >>>
> > >>> If you follow the code flow in __execute_only_pkey, the AMR and UAMOR
> > >>> are read 3 times in total, and AMR is written twice. IAMR is read and
> > >>> written twice. Since they are SPRs and access to them is slow (or isn't
> > >>> it?),
> > >>
> > >> SPRs read/writes are slow, but they're not *that* slow in comparison to
> > >> a system call (which I think is where this code is being called?).
> > >
> > > Yes, this code runs on mprotect and mmap syscalls if the memory is
> > > requested to have execute but not read nor write permissions.
> > 
> > Yep. That's not in the fast path for key usage, ie. the fast path is
> > userspace changing the AMR itself, and the overhead of a syscall is
> > already hundreds of cycles.
> > 
> > >> So we should try to avoid too many SPR read/writes, but at the same time
> > >> we can accept more than the minimum if it makes the code much easier to
> > >> follow.
> > >
> > > Ok. Ram had asked me to suggest a way to optimize the SPR reads and
> > > writes and I came up with the patch below. Do you think it's worth it?
> > 
> > At a glance no I don't think it is. Sorry you spent that much time on it.
> > 
> > I think we can probably reduce the number of SPR accesses without
> > needing to go to that level of complexity.
> > 
> > But don't throw the patch away, I may eat my words once I have the full
> > series applied and am looking at it hard - at the moment I'm just
> > reviewing the patches piecemeal as I get time.
> 

Thiago's patch does save some cycles. I dont feel like throwing his
work. I agree, It should be considered after applying all the patches. 
 
RP

-- 
Ram Pai



Re: [RFC v6 21/62] powerpc: introduce execute-only pkey

2017-08-02 Thread Michael Ellerman
Thiago Jung Bauermann  writes:

> Michael Ellerman  writes:
>
>> Thiago Jung Bauermann  writes:
>>> Ram Pai  writes:
>> ...
 +
 +  /* We got one, store it and use it from here on out */
 +  if (need_to_set_mm_pkey)
 +  mm->context.execute_only_pkey = execute_only_pkey;
 +  return execute_only_pkey;
 +}
>>>
>>> If you follow the code flow in __execute_only_pkey, the AMR and UAMOR
>>> are read 3 times in total, and AMR is written twice. IAMR is read and
>>> written twice. Since they are SPRs and access to them is slow (or isn't
>>> it?),
>>
>> SPRs read/writes are slow, but they're not *that* slow in comparison to
>> a system call (which I think is where this code is being called?).
>
> Yes, this code runs on mprotect and mmap syscalls if the memory is
> requested to have execute but not read nor write permissions.

Yep. That's not in the fast path for key usage, ie. the fast path is
userspace changing the AMR itself, and the overhead of a syscall is
already hundreds of cycles.

>> So we should try to avoid too many SPR read/writes, but at the same time
>> we can accept more than the minimum if it makes the code much easier to
>> follow.
>
> Ok. Ram had asked me to suggest a way to optimize the SPR reads and
> writes and I came up with the patch below. Do you think it's worth it?

At a glance no I don't think it is. Sorry you spent that much time on it.

I think we can probably reduce the number of SPR accesses without
needing to go to that level of complexity.

But don't throw the patch away, I may eat my words once I have the full
series applied and am looking at it hard - at the moment I'm just
reviewing the patches piecemeal as I get time.

cheers


Re: [RFC v6 21/62] powerpc: introduce execute-only pkey

2017-08-01 Thread Thiago Jung Bauermann

Michael Ellerman  writes:

> Thiago Jung Bauermann  writes:
>> Ram Pai  writes:
> ...
>>> +
>>> +   /* We got one, store it and use it from here on out */
>>> +   if (need_to_set_mm_pkey)
>>> +   mm->context.execute_only_pkey = execute_only_pkey;
>>> +   return execute_only_pkey;
>>> +}
>>
>> If you follow the code flow in __execute_only_pkey, the AMR and UAMOR
>> are read 3 times in total, and AMR is written twice. IAMR is read and
>> written twice. Since they are SPRs and access to them is slow (or isn't
>> it?),
>
> SPRs read/writes are slow, but they're not *that* slow in comparison to
> a system call (which I think is where this code is being called?).

Yes, this code runs on mprotect and mmap syscalls if the memory is
requested to have execute but not read nor write permissions.

> So we should try to avoid too many SPR read/writes, but at the same time
> we can accept more than the minimum if it makes the code much easier to
> follow.

Ok. Ram had asked me to suggest a way to optimize the SPR reads and
writes and I came up with the patch below. Do you think it's worth it?

The patch applies on top of this series, but if Ram includes it I think
he would break it up and merge it into the other patches.

-- 
Thiago Jung Bauermann
IBM Linux Technology Center


>From f6e73e67d325c4a1952c375072ca35156a9f2042 Mon Sep 17 00:00:00 2001
From: Thiago Jung Bauermann 
Date: Mon, 31 Jul 2017 20:22:59 -0300
Subject: [PATCH] powerpc: Cache protection key registers in
 __execute_only_pkey

Pass around a struct with the contents of AMR, IAMR and AMOR, as well as
flags indicating whether those fields hold valid values and whether they
should be committed back to the registers.

Signed-off-by: Thiago Jung Bauermann 
---
 arch/powerpc/include/asm/pkeys.h |  18 --
 arch/powerpc/mm/pkeys.c  | 120 +--
 2 files changed, 104 insertions(+), 34 deletions(-)

diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
index e61ed6c332db..66f15dbc5855 100644
--- a/arch/powerpc/include/asm/pkeys.h
+++ b/arch/powerpc/include/asm/pkeys.h
@@ -129,12 +129,15 @@ static inline bool mm_pkey_is_allocated(struct mm_struct 
*mm, int pkey)
mm_set_pkey_is_allocated(mm, pkey));
 }
 
-extern void __arch_activate_pkey(int pkey);
+struct pkey_regs_cache;
+
+extern void __arch_activate_pkey(int pkey, struct pkey_regs_cache *regs);
 extern void __arch_deactivate_pkey(int pkey);
 /*
  * Returns a positive, 5-bit key on success, or -1 on failure.
  */
-static inline int mm_pkey_alloc(struct mm_struct *mm)
+static inline int __mm_pkey_alloc(struct mm_struct *mm,
+ struct pkey_regs_cache *regs)
 {
/*
 * Note: this is the one and only place we make sure
@@ -162,10 +165,15 @@ static inline int mm_pkey_alloc(struct mm_struct *mm)
 * enable the key in the hardware
 */
if (ret > 0)
-   __arch_activate_pkey(ret);
+   __arch_activate_pkey(ret, regs);
return ret;
 }
 
+static inline int mm_pkey_alloc(struct mm_struct *mm)
+{
+   return __mm_pkey_alloc(mm, NULL);
+}
+
 static inline int mm_pkey_free(struct mm_struct *mm, int pkey)
 {
if (!pkey_inited)
@@ -206,13 +214,13 @@ static inline int arch_override_mprotect_pkey(struct 
vm_area_struct *vma,
 }
 
 extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
-   unsigned long init_val);
+   unsigned long init_val, struct pkey_regs_cache *regs);
 static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
unsigned long init_val)
 {
if (!pkey_inited)
return -EINVAL;
-   return __arch_set_user_pkey_access(tsk, pkey, init_val);
+   return __arch_set_user_pkey_access(tsk, pkey, init_val, NULL);
 }
 
 static inline bool arch_pkeys_enabled(void)
diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
index 1424c79f45f6..718ea23f8184 100644
--- a/arch/powerpc/mm/pkeys.c
+++ b/arch/powerpc/mm/pkeys.c
@@ -22,52 +22,92 @@ u32  initial_allocation_mask;   /* bits set for 
reserved keys */
 #define PKEY_REG_BITS (sizeof(u64)*8)
 #define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY))
 
-static bool is_pkey_enabled(int pkey)
+/*
+ * The registers controlling memory protection keys are expensive to access, so
+ * we want to cache their values in code paths that might need to use them more
+ * than once.
+ */
+struct pkey_regs_cache {
+   u64 amr;
+   u64 iamr;
+   u64 uamor;
+
+   bool amr_valid;
+   bool iamr_valid;
+   bool uamor_valid;
+
+   bool write_amr;
+   bool write_iamr;
+   bool write_uamor;
+};
+
+static bool is_pkey_enabled(int pkey, struct pkey_regs_cache *regs)
 {
-   return !!(read_uamor() & (0x3ul << 

Re: [RFC v6 21/62] powerpc: introduce execute-only pkey

2017-08-01 Thread Michael Ellerman
Thiago Jung Bauermann  writes:
> Ram Pai  writes:
...
>> +
>> +/* We got one, store it and use it from here on out */
>> +if (need_to_set_mm_pkey)
>> +mm->context.execute_only_pkey = execute_only_pkey;
>> +return execute_only_pkey;
>> +}
>
> If you follow the code flow in __execute_only_pkey, the AMR and UAMOR
> are read 3 times in total, and AMR is written twice. IAMR is read and
> written twice. Since they are SPRs and access to them is slow (or isn't
> it?),

SPRs read/writes are slow, but they're not *that* slow in comparison to
a system call (which I think is where this code is being called?).

So we should try to avoid too many SPR read/writes, but at the same time
we can accept more than the minimum if it makes the code much easier to
follow.

cheers


Re: [RFC v6 21/62] powerpc: introduce execute-only pkey

2017-07-31 Thread Thiago Jung Bauermann

Ram Pai  writes:

> On Fri, Jul 28, 2017 at 07:17:13PM -0300, Thiago Jung Bauermann wrote:
>> 
>> Ram Pai  writes:
>> > --- a/arch/powerpc/mm/pkeys.c
>> > +++ b/arch/powerpc/mm/pkeys.c
>> > @@ -97,3 +97,60 @@ int __arch_set_user_pkey_access(struct task_struct 
>> > *tsk, int pkey,
>> >init_iamr(pkey, new_iamr_bits);
>> >return 0;
>> >  }
>> > +
>> > +static inline bool pkey_allows_readwrite(int pkey)
>> > +{
>> > +  int pkey_shift = pkeyshift(pkey);
>> > +
>> > +  if (!(read_uamor() & (0x3UL << pkey_shift)))
>> > +  return true;
>> > +
>> > +  return !(read_amr() & ((AMR_RD_BIT|AMR_WR_BIT) << pkey_shift));
>> > +}
>> > +
>> > +int __execute_only_pkey(struct mm_struct *mm)
>> > +{
>> > +  bool need_to_set_mm_pkey = false;
>> > +  int execute_only_pkey = mm->context.execute_only_pkey;
>> > +  int ret;
>> > +
>> > +  /* Do we need to assign a pkey for mm's execute-only maps? */
>> > +  if (execute_only_pkey == -1) {
>> > +  /* Go allocate one to use, which might fail */
>> > +  execute_only_pkey = mm_pkey_alloc(mm);
>> > +  if (execute_only_pkey < 0)
>> > +  return -1;
>> > +  need_to_set_mm_pkey = true;
>> > +  }
>> > +
>> > +  /*
>> > +   * We do not want to go through the relatively costly
>> > +   * dance to set AMR if we do not need to.  Check it
>> > +   * first and assume that if the execute-only pkey is
>> > +   * readwrite-disabled than we do not have to set it
>> > +   * ourselves.
>> > +   */
>> > +  if (!need_to_set_mm_pkey &&
>> > +  !pkey_allows_readwrite(execute_only_pkey))
>   ^
>   Here uamor and amr is read once each.

You are right. What confused me was that the call to mm_pkey_alloc above
also reads uamor and amr (and also iamr, and writes to all of those) but
if that function is called, then need_to_set_mm_pkey is true and
pkey_allows_readwrite won't be called.

>> > +  return execute_only_pkey;
>> > +
>> > +  /*
>> > +   * Set up AMR so that it denies access for everything
>> > +   * other than execution.
>> > +   */
>> > +  ret = __arch_set_user_pkey_access(current, execute_only_pkey,
>> > +  (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
>   ^^^
>   here amr and iamr are written once each if the
>   the function returns successfully.

__arch_set_user_pkey_access also reads uamor for the second time in its
call to is_pkey_enabled, and reads amr for the second time as well in
its calls to init_amr. The first reads are in either
pkey_allows_readwrite or pkey_status_change (called from
__arch_activate_pkey).

If need_to_set_mm_pkey is true, then the iamr read in init_iamr is the
2nd one during __execute_only_pkey's execution. In this case the writes
to amr and iamr will be the 2nd ones as well. The first reads and writes
are in pkey_status_change.

>> > +  /*
>> > +   * If the AMR-set operation failed somehow, just return
>> > +   * 0 and effectively disable execute-only support.
>> > +   */
>> > +  if (ret) {
>> > +  mm_set_pkey_free(mm, execute_only_pkey);
>   ^^^
>   here only if __arch_set_user_pkey_access() fails
>   amr and iamr and uamor will be written once each.

I assume the error case isn't perfomance sensitive and didn't account
for mm_set_pkey_free in my analysis.

>> > +  return -1;
>> > +  }
>> > +
>> > +  /* We got one, store it and use it from here on out */
>> > +  if (need_to_set_mm_pkey)
>> > +  mm->context.execute_only_pkey = execute_only_pkey;
>> > +  return execute_only_pkey;
>> > +}
>> 
>> If you follow the code flow in __execute_only_pkey, the AMR and UAMOR
>> are read 3 times in total, and AMR is written twice. IAMR is read and
>> written twice. Since they are SPRs and access to them is slow (or isn't
>> it?), is it worth it to read them once in __execute_only_pkey and pass
>> down their values to the callees, and then write them once at the end of
>> the function?
>
> If my calculations are right: 
>   uamor may be read once and may be written once.
>   amr may be read once and is written once.
>   iamr is written once.
> So not that bad, i think.

If I'm following the code correctly:
if need_to_set_mm_pkey = true:
uamor is read twice and written once.
amr is read twice and written twice.
iamr is read twice and written twice.
if need_to_set_mm_pkey = false:
uamor is read twice.
amr is read once or twice (depending on the value of uamor) and written 
once.
iamr is read once and written once.

-- 
Thiago Jung Bauermann
IBM Linux Technology Center



Re: [RFC v6 21/62] powerpc: introduce execute-only pkey

2017-07-29 Thread Ram Pai
On Fri, Jul 28, 2017 at 07:17:13PM -0300, Thiago Jung Bauermann wrote:
> 
> Ram Pai  writes:
> > --- a/arch/powerpc/mm/pkeys.c
> > +++ b/arch/powerpc/mm/pkeys.c
> > @@ -97,3 +97,60 @@ int __arch_set_user_pkey_access(struct task_struct *tsk, 
> > int pkey,
> > init_iamr(pkey, new_iamr_bits);
> > return 0;
> >  }
> > +
> > +static inline bool pkey_allows_readwrite(int pkey)
> > +{
> > +   int pkey_shift = pkeyshift(pkey);
> > +
> > +   if (!(read_uamor() & (0x3UL << pkey_shift)))
> > +   return true;
> > +
> > +   return !(read_amr() & ((AMR_RD_BIT|AMR_WR_BIT) << pkey_shift));
> > +}
> > +
> > +int __execute_only_pkey(struct mm_struct *mm)
> > +{
> > +   bool need_to_set_mm_pkey = false;
> > +   int execute_only_pkey = mm->context.execute_only_pkey;
> > +   int ret;
> > +
> > +   /* Do we need to assign a pkey for mm's execute-only maps? */
> > +   if (execute_only_pkey == -1) {
> > +   /* Go allocate one to use, which might fail */
> > +   execute_only_pkey = mm_pkey_alloc(mm);
> > +   if (execute_only_pkey < 0)
> > +   return -1;
> > +   need_to_set_mm_pkey = true;
> > +   }
> > +
> > +   /*
> > +* We do not want to go through the relatively costly
> > +* dance to set AMR if we do not need to.  Check it
> > +* first and assume that if the execute-only pkey is
> > +* readwrite-disabled than we do not have to set it
> > +* ourselves.
> > +*/
> > +   if (!need_to_set_mm_pkey &&
> > +   !pkey_allows_readwrite(execute_only_pkey))
^
Here uamor and amr is read once each.

> > +   return execute_only_pkey;
> > +
> > +   /*
> > +* Set up AMR so that it denies access for everything
> > +* other than execution.
> > +*/
> > +   ret = __arch_set_user_pkey_access(current, execute_only_pkey,
> > +   (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
^^^
here amr and iamr are written once each if the
the function returns successfully.
> > +   /*
> > +* If the AMR-set operation failed somehow, just return
> > +* 0 and effectively disable execute-only support.
> > +*/
> > +   if (ret) {
> > +   mm_set_pkey_free(mm, execute_only_pkey);
^^^
here only if __arch_set_user_pkey_access() fails
amr and iamr and uamor will be written once each.

> > +   return -1;
> > +   }
> > +
> > +   /* We got one, store it and use it from here on out */
> > +   if (need_to_set_mm_pkey)
> > +   mm->context.execute_only_pkey = execute_only_pkey;
> > +   return execute_only_pkey;
> > +}
> 
> If you follow the code flow in __execute_only_pkey, the AMR and UAMOR
> are read 3 times in total, and AMR is written twice. IAMR is read and
> written twice. Since they are SPRs and access to them is slow (or isn't
> it?), is it worth it to read them once in __execute_only_pkey and pass
> down their values to the callees, and then write them once at the end of
> the function?

If my calculations are right: 
uamor may be read once and may be written once.
amr may be read once and is written once.
iamr is written once.
So not that bad, i think.

RP



Re: [RFC v6 21/62] powerpc: introduce execute-only pkey

2017-07-28 Thread Thiago Jung Bauermann

Ram Pai  writes:
> --- a/arch/powerpc/mm/pkeys.c
> +++ b/arch/powerpc/mm/pkeys.c
> @@ -97,3 +97,60 @@ int __arch_set_user_pkey_access(struct task_struct *tsk, 
> int pkey,
>   init_iamr(pkey, new_iamr_bits);
>   return 0;
>  }
> +
> +static inline bool pkey_allows_readwrite(int pkey)
> +{
> + int pkey_shift = pkeyshift(pkey);
> +
> + if (!(read_uamor() & (0x3UL << pkey_shift)))
> + return true;
> +
> + return !(read_amr() & ((AMR_RD_BIT|AMR_WR_BIT) << pkey_shift));
> +}
> +
> +int __execute_only_pkey(struct mm_struct *mm)
> +{
> + bool need_to_set_mm_pkey = false;
> + int execute_only_pkey = mm->context.execute_only_pkey;
> + int ret;
> +
> + /* Do we need to assign a pkey for mm's execute-only maps? */
> + if (execute_only_pkey == -1) {
> + /* Go allocate one to use, which might fail */
> + execute_only_pkey = mm_pkey_alloc(mm);
> + if (execute_only_pkey < 0)
> + return -1;
> + need_to_set_mm_pkey = true;
> + }
> +
> + /*
> +  * We do not want to go through the relatively costly
> +  * dance to set AMR if we do not need to.  Check it
> +  * first and assume that if the execute-only pkey is
> +  * readwrite-disabled than we do not have to set it
> +  * ourselves.
> +  */
> + if (!need_to_set_mm_pkey &&
> + !pkey_allows_readwrite(execute_only_pkey))
> + return execute_only_pkey;
> +
> + /*
> +  * Set up AMR so that it denies access for everything
> +  * other than execution.
> +  */
> + ret = __arch_set_user_pkey_access(current, execute_only_pkey,
> + (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
> + /*
> +  * If the AMR-set operation failed somehow, just return
> +  * 0 and effectively disable execute-only support.
> +  */
> + if (ret) {
> + mm_set_pkey_free(mm, execute_only_pkey);
> + return -1;
> + }
> +
> + /* We got one, store it and use it from here on out */
> + if (need_to_set_mm_pkey)
> + mm->context.execute_only_pkey = execute_only_pkey;
> + return execute_only_pkey;
> +}

If you follow the code flow in __execute_only_pkey, the AMR and UAMOR
are read 3 times in total, and AMR is written twice. IAMR is read and
written twice. Since they are SPRs and access to them is slow (or isn't
it?), is it worth it to read them once in __execute_only_pkey and pass
down their values to the callees, and then write them once at the end of
the function?

This function is used both by the mmap syscall and the mprotect syscall
(but not by pkey_mprotect) if the requested protection is execute-only.

-- 
Thiago Jung Bauermann
IBM Linux Technology Center



[RFC v6 21/62] powerpc: introduce execute-only pkey

2017-07-15 Thread Ram Pai
This patch provides the implementation of execute-only pkey.
The architecture-independent  expects the ability to create
and manage a special key which has execute-only permission.

Signed-off-by: Ram Pai 
---
 arch/powerpc/include/asm/book3s/64/mmu.h |1 +
 arch/powerpc/include/asm/pkeys.h |8 -
 arch/powerpc/mm/pkeys.c  |   57 ++
 3 files changed, 65 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h 
b/arch/powerpc/include/asm/book3s/64/mmu.h
index 104ad72..0c0a2a8 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -116,6 +116,7 @@ struct patb_entry {
 * bit unset -> key available for allocation
 */
u32 pkey_allocation_map;
+   s16 execute_only_pkey; /* key holding execute-only protection */
 #endif
 } mm_context_t;
 
diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h
index 0e744f1..1864148 100644
--- a/arch/powerpc/include/asm/pkeys.h
+++ b/arch/powerpc/include/asm/pkeys.h
@@ -118,11 +118,15 @@ static inline int mm_pkey_free(struct mm_struct *mm, int 
pkey)
  * Try to dedicate one of the protection keys to be used as an
  * execute-only protection key.
  */
+extern int __execute_only_pkey(struct mm_struct *mm);
 static inline int execute_only_pkey(struct mm_struct *mm)
 {
-   return 0;
+   if (!pkey_inited)
+   return -1;
+   return __execute_only_pkey(mm);
 }
 
+
 static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
int prot, int pkey)
 {
@@ -144,6 +148,8 @@ static inline void pkey_mm_init(struct mm_struct *mm)
if (!pkey_inited)
return;
mm_pkey_allocation_map(mm) = PKEY_INITIAL_ALLOCAION;
+   /* -1 means unallocated or invalid */
+   mm->context.execute_only_pkey = -1;
 }
 
 static inline void pkey_initialize(void)
diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
index b9ad98d..34e8557 100644
--- a/arch/powerpc/mm/pkeys.c
+++ b/arch/powerpc/mm/pkeys.c
@@ -97,3 +97,60 @@ int __arch_set_user_pkey_access(struct task_struct *tsk, int 
pkey,
init_iamr(pkey, new_iamr_bits);
return 0;
 }
+
+static inline bool pkey_allows_readwrite(int pkey)
+{
+   int pkey_shift = pkeyshift(pkey);
+
+   if (!(read_uamor() & (0x3UL << pkey_shift)))
+   return true;
+
+   return !(read_amr() & ((AMR_RD_BIT|AMR_WR_BIT) << pkey_shift));
+}
+
+int __execute_only_pkey(struct mm_struct *mm)
+{
+   bool need_to_set_mm_pkey = false;
+   int execute_only_pkey = mm->context.execute_only_pkey;
+   int ret;
+
+   /* Do we need to assign a pkey for mm's execute-only maps? */
+   if (execute_only_pkey == -1) {
+   /* Go allocate one to use, which might fail */
+   execute_only_pkey = mm_pkey_alloc(mm);
+   if (execute_only_pkey < 0)
+   return -1;
+   need_to_set_mm_pkey = true;
+   }
+
+   /*
+* We do not want to go through the relatively costly
+* dance to set AMR if we do not need to.  Check it
+* first and assume that if the execute-only pkey is
+* readwrite-disabled than we do not have to set it
+* ourselves.
+*/
+   if (!need_to_set_mm_pkey &&
+   !pkey_allows_readwrite(execute_only_pkey))
+   return execute_only_pkey;
+
+   /*
+* Set up AMR so that it denies access for everything
+* other than execution.
+*/
+   ret = __arch_set_user_pkey_access(current, execute_only_pkey,
+   (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
+   /*
+* If the AMR-set operation failed somehow, just return
+* 0 and effectively disable execute-only support.
+*/
+   if (ret) {
+   mm_set_pkey_free(mm, execute_only_pkey);
+   return -1;
+   }
+
+   /* We got one, store it and use it from here on out */
+   if (need_to_set_mm_pkey)
+   mm->context.execute_only_pkey = execute_only_pkey;
+   return execute_only_pkey;
+}
-- 
1.7.1