lkml.org 
[lkml]   [2008]   [Feb]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] [1/5] CPA: Split static_protections into required_static_prot and advised_static_prot
    Date

    There is a big difference between NX and RO. NX absolutely has to be cleared
    or the kernel will fail while RO just can be set, but does not need to.
    And for a large page area not setting NX if there is a area below
    it that needs it is essential, while making it ro is optional again.

    This is needed for a followup patch who uses requred_static_prot() for large
    pages where it is inconvenient to check all pages.

    No behaviour change in this patch.

    [Lines > 80 characters are changed in followup patch]

    Signed-off-by: Andi Kleen <ak@suse.de>

    ---
    arch/x86/mm/pageattr.c | 24 +++++++++++++++---------
    1 file changed, 15 insertions(+), 9 deletions(-)

    Index: linux/arch/x86/mm/pageattr.c
    ===================================================================
    --- linux.orig/arch/x86/mm/pageattr.c
    +++ linux/arch/x86/mm/pageattr.c
    @@ -149,7 +149,7 @@ static unsigned long virt_to_highmap(voi
    * right (again, ioremap() on BIOS memory is not uncommon) so this function
    * checks and fixes these known static required protection bits.
    */
    -static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
    +static inline pgprot_t required_static_prot(pgprot_t prot, unsigned long address)
    {
    pgprot_t forbidden = __pgprot(0);

    @@ -173,21 +173,25 @@ static inline pgprot_t static_protection
    pgprot_val(forbidden) |= _PAGE_NX;


    + prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
    +
    + return prot;
    +}
    +
    +static inline pgprot_t advised_static_prot(pgprot_t prot, unsigned long address)
    +{
    #ifdef CONFIG_DEBUG_RODATA
    /* The .rodata section needs to be read-only */
    if (within(address, (unsigned long)__start_rodata,
    (unsigned long)__end_rodata))
    - pgprot_val(forbidden) |= _PAGE_RW;
    + pgprot_val(prot) &= ~_PAGE_RW;
    /*
    * Do the same for the x86-64 high kernel mapping
    */
    if (within(address, virt_to_highmap(__start_rodata),
    virt_to_highmap(__end_rodata)))
    - pgprot_val(forbidden) |= _PAGE_RW;
    + pgprot_val(prot) &= ~_PAGE_RW;
    #endif
    -
    - prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
    -
    return prot;
    }

    @@ -318,7 +322,8 @@ try_preserve_large_page(pte_t *kpte, uns

    pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
    pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
    - new_prot = static_protections(new_prot, address);
    + new_prot = required_static_prot(new_prot, address);
    + new_prot = advised_static_prot(new_prot, address);

    /*
    * If there are no changes, return. maxpages has been updated
    @@ -456,7 +461,8 @@ repeat:
    pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
    pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);

    - new_prot = static_protections(new_prot, address);
    + new_prot = required_static_prot(new_prot, address);
    + new_prot = advised_static_prot(new_prot, address);

    /*
    * We need to keep the pfn from the existing PTE,
    @@ -546,7 +552,7 @@ static int change_page_attr_addr(struct
    * for the non obvious details.
    *
    * Note that NX and other required permissions are
    - * checked in static_protections().
    + * checked in required_static_prot().
    */
    address = phys_addr + HIGH_MAP_START - phys_base;


    \
     
     \ /
      Last update: 2008-02-08 14:31    [W:0.025 / U:301.240 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site