lkml.org 
[lkml]   [2021]   [Feb]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v19 10/25] x86/mm: Update pte_modify for _PAGE_COW
    Date
    The read-only and Dirty PTE has been used to indicate copy-on-write pages.
    However, newer x86 processors also regard a read-only and Dirty PTE as a
    shadow stack page. In order to separate the two, the software-defined
    _PAGE_COW is created to replace _PAGE_DIRTY for the copy-on-write case, and
    pte_*() are updated.

    Pte_modify() changes a PTE to 'newprot', but it doesn't use the pte_*().
    Introduce fixup_dirty_pte(), which sets a dirty PTE, based on _PAGE_RW,
    to either _PAGE_DIRTY or _PAGE_COW.

    Apply the same changes to pmd_modify().

    Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
    ---
    arch/x86/include/asm/pgtable.h | 33 +++++++++++++++++++++++++++++++++
    1 file changed, 33 insertions(+)

    diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
    index 4b0ec61510dc..4a7fd3e5b7df 100644
    --- a/arch/x86/include/asm/pgtable.h
    +++ b/arch/x86/include/asm/pgtable.h
    @@ -726,6 +726,21 @@ static inline pmd_t pmd_mkinvalid(pmd_t pmd)

    static inline u64 flip_protnone_guard(u64 oldval, u64 val, u64 mask);

    +static inline pteval_t fixup_dirty_pte(pteval_t pteval)
    +{
    + pte_t pte = __pte(pteval);
    +
    + if (cpu_feature_enabled(X86_FEATURE_SHSTK) && pte_dirty(pte)) {
    + pte = pte_mkclean(pte);
    +
    + if (pte_flags(pte) & _PAGE_RW)
    + pte = pte_set_flags(pte, _PAGE_DIRTY);
    + else
    + pte = pte_set_flags(pte, _PAGE_COW);
    + }
    + return pte_val(pte);
    +}
    +
    static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
    {
    pteval_t val = pte_val(pte), oldval = val;
    @@ -736,16 +751,34 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
    */
    val &= _PAGE_CHG_MASK;
    val |= check_pgprot(newprot) & ~_PAGE_CHG_MASK;
    + val = fixup_dirty_pte(val);
    val = flip_protnone_guard(oldval, val, PTE_PFN_MASK);
    return __pte(val);
    }

    +static inline int pmd_write(pmd_t pmd);
    +static inline pmdval_t fixup_dirty_pmd(pmdval_t pmdval)
    +{
    + pmd_t pmd = __pmd(pmdval);
    +
    + if (cpu_feature_enabled(X86_FEATURE_SHSTK) && pmd_dirty(pmd)) {
    + pmd = pmd_mkclean(pmd);
    +
    + if (pmd_flags(pmd) & _PAGE_RW)
    + pmd = pmd_set_flags(pmd, _PAGE_DIRTY);
    + else
    + pmd = pmd_set_flags(pmd, _PAGE_COW);
    + }
    + return pmd_val(pmd);
    +}
    +
    static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
    {
    pmdval_t val = pmd_val(pmd), oldval = val;

    val &= _HPAGE_CHG_MASK;
    val |= check_pgprot(newprot) & ~_HPAGE_CHG_MASK;
    + val = fixup_dirty_pmd(val);
    val = flip_protnone_guard(oldval, val, PHYSICAL_PMD_PAGE_MASK);
    return __pmd(val);
    }
    --
    2.21.0
    \
     
     \ /
      Last update: 2021-02-04 00:01    [W:4.027 / U:0.396 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site