On Fri, Jul 28, 2017 at 07:17:13PM -0300, Thiago Jung Bauermann wrote:
> 
> Ram Pai <linux...@us.ibm.com> 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

Reply via email to