[PATCH] kmemcheck: use set_memory_4k() instead of disabling PSE - Kernel

This is a discussion on [PATCH] kmemcheck: use set_memory_4k() instead of disabling PSE - Kernel ; Hi, With this, we reduce the overall impact of kmemcheck by reverting some earlier, now unnecessary, changes: Documentation/kmemcheck.txt | 101 +++++ MAINTAINERS | 8 + arch/x86/Kconfig.debug | 87 ++++ arch/x86/kernel/Makefile | 2 + - arch/x86/kernel/cpu/common.c | 7 + arch/x86/kernel/entry_32.S | ...

+ Reply to Thread
Results 1 to 2 of 2

Thread: [PATCH] kmemcheck: use set_memory_4k() instead of disabling PSE

  1. [PATCH] kmemcheck: use set_memory_4k() instead of disabling PSE

    Hi,

    With this, we reduce the overall impact of kmemcheck by reverting some
    earlier, now unnecessary, changes:

    Documentation/kmemcheck.txt | 101 +++++
    MAINTAINERS | 8 +
    arch/x86/Kconfig.debug | 87 ++++
    arch/x86/kernel/Makefile | 2 +
    - arch/x86/kernel/cpu/common.c | 7 +
    arch/x86/kernel/entry_32.S | 8 +-
    arch/x86/kernel/entry_64.S | 4 +-
    - arch/x86/kernel/head_32.S | 2 +-
    - arch/x86/kernel/kmemcheck.c | 964 ++++++++++++++++++++++++++++++++++++++++++
    + arch/x86/kernel/kmemcheck.c | 963 ++++++++++++++++++++++++++++++++++++++++++
    arch/x86/kernel/process.c | 2 +-
    arch/x86/kernel/process_32.c | 4 +-
    arch/x86/kernel/process_64.c | 12 +-
    arch/x86/kernel/traps_32.c | 18 +-
    arch/x86/kernel/traps_64.c | 16 +-
    - arch/x86/mm/fault.c | 25 +-
    - arch/x86/mm/init_32.c | 2 +-
    + arch/x86/mm/fault.c | 35 ++
    include/asm-x86/kdebug.h | 3 +-
    include/asm-x86/kmemcheck.h | 30 ++
    include/asm-x86/pgtable.h | 4 +-
    include/asm-x86/pgtable_32.h | 6 +
    include/asm-x86/pgtable_64.h | 6 +
    include/asm-x86/string_32.h | 8 +
    include/asm-x86/string_64.h | 1 +
    include/linux/gfp.h | 3 +-
    include/linux/kmemcheck.h | 61 +++
    include/linux/mm_types.h | 4 +
    include/linux/slab.h | 7 +
    include/linux/slab_def.h | 81 ++++
    init/main.c | 2 +
    kernel/fork.c | 16 +-
    kernel/sysctl.c | 12 +
    mm/Makefile | 2 +-
    mm/kmemcheck.c | 97 +++++
    mm/slab.c | 101 +----
    mm/slub.c | 17 +-
    - 35 files changed, 1601 insertions(+), 122 deletions(-)
    + 32 files changed, 1605 insertions(+), 116 deletions(-)

    which is probably a good thing if it is ever merged into mainline :-)

    See patch description for more info.

    Vegard


    From 648611a899fd61df8f44b6f78c2700a460913d67 Mon Sep 17 00:00:00 2001
    From: Vegard Nossum
    Date: Sat, 10 May 2008 17:19:33 +0200
    Subject: [PATCH] kmemcheck: use set_memory_4k() instead of disabling PSE

    Thanks a bunch to Andi Kleen for this brilliant solution. Now all pages
    that kmemcheck handle will be 4k in size, and we need no special-case code
    to handle larger pages.

    This will also greatly help the upcoming 64-bit support.

    Signed-off-by: Vegard Nossum
    ---
    arch/x86/kernel/cpu/common.c | 7 ------
    arch/x86/kernel/head_32.S | 2 +-
    arch/x86/kernel/kmemcheck.c | 9 +++----
    arch/x86/mm/fault.c | 44 +++++++++++++++++++++++++++++------------
    arch/x86/mm/init_32.c | 2 +-
    5 files changed, 37 insertions(+), 27 deletions(-)

    diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
    index 39933f6..35b4f6a 100644
    --- a/arch/x86/kernel/cpu/common.c
    +++ b/arch/x86/kernel/cpu/common.c
    @@ -651,13 +651,6 @@ void __init early_cpu_init(void)
    cpu_devs[cvdev->vendor] = cvdev->cpu_dev;

    early_cpu_detect();
    -
    -#ifdef CONFIG_KMEMCHECK
    - /*
    - * We need 4K granular PTEs for kmemcheck:
    - */
    - setup_clear_cpu_cap(X86_FEATURE_PSE);
    -#endif
    }

    /* Make sure %fs is initialized properly in idle threads */
    diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
    index c41ca7d..b2cc737 100644
    --- a/arch/x86/kernel/head_32.S
    +++ b/arch/x86/kernel/head_32.S
    @@ -60,7 +60,7 @@ LOW_PAGES = 1<<(32-PAGE_SHIFT_asm)
    * pagetables from above the 16MB DMA limit, so we'll have to set
    * up pagetables 16MB more (worst-case):
    */
    -#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
    +#ifdef CONFIG_DEBUG_PAGEALLOC
    LOW_PAGES = LOW_PAGES + 0x1000000
    #endif

    diff --git a/arch/x86/kernel/kmemcheck.c b/arch/x86/kernel/kmemcheck.c
    index 7412a80..752a2d1 100644
    --- a/arch/x86/kernel/kmemcheck.c
    +++ b/arch/x86/kernel/kmemcheck.c
    @@ -488,9 +488,7 @@ kmemcheck_show_pages(struct page *p, unsigned int n)
    address = (unsigned long) page_address(&p[i]);
    pte = lookup_address(address, &level);
    BUG_ON(!pte);
    -
    - if (level != PG_LEVEL_4K)
    - continue;
    + BUG_ON(level != PG_LEVEL_4K);

    set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT));
    set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_HIDDEN));
    @@ -510,6 +508,8 @@ kmemcheck_hide_pages(struct page *p, unsigned int n)
    {
    unsigned int i;

    + set_memory_4k((unsigned long) page_address(p), n);
    +
    for (i = 0; i < n; ++i) {
    unsigned long address;
    pte_t *pte;
    @@ -518,8 +518,7 @@ kmemcheck_hide_pages(struct page *p, unsigned int n)
    address = (unsigned long) page_address(&p[i]);
    pte = lookup_address(address, &level);
    BUG_ON(!pte);
    - if (level != PG_LEVEL_4K)
    - continue;
    + BUG_ON(level != PG_LEVEL_4K);

    set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT));
    set_pte(pte, __pte(pte_val(*pte) | _PAGE_HIDDEN));
    diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
    index 694a0b0..bde2361 100644
    --- a/arch/x86/mm/fault.c
    +++ b/arch/x86/mm/fault.c
    @@ -492,8 +492,7 @@ static int spurious_fault(unsigned long address,
    *
    * This assumes no large pages in there.
    */
    -static int vmalloc_fault(struct pt_regs *regs, unsigned long address,
    - unsigned long error_code)
    +static int vmalloc_fault(unsigned long address)
    {
    #ifdef CONFIG_X86_32
    unsigned long pgd_paddr;
    @@ -510,17 +509,10 @@ static int vmalloc_fault(struct pt_regs *regs, unsigned long address,
    pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
    if (!pmd_k)
    return -1;
    +
    pte_k = pte_offset_kernel(pmd_k, address);
    - if (!pte_present(*pte_k)) {
    - if (!pte_hidden(*pte_k))
    - return -1;
    -
    - if (error_code & 2)
    - kmemcheck_access(regs, address, KMEMCHECK_WRITE);
    - else
    - kmemcheck_access(regs, address, KMEMCHECK_READ);
    - kmemcheck_show(regs);
    - }
    + if (!pte_present(*pte_k))
    + return -1;
    return 0;
    #else
    pgd_t *pgd, *pgd_ref;
    @@ -573,6 +565,29 @@ static int vmalloc_fault(struct pt_regs *regs, unsigned long address,
    #endif
    }

    +static bool kmemcheck_fault(struct pt_regs *regs, unsigned long address,
    + unsigned long error_code)
    +{
    + pte_t *pte;
    + unsigned int level;
    +
    + pte = lookup_address(address, &level);
    + if (!pte)
    + return false;
    + if (level != PG_LEVEL_4K)
    + return false;
    + if (!pte_hidden(*pte))
    + return false;
    +
    + if (error_code & 2)
    + kmemcheck_access(regs, address, KMEMCHECK_WRITE);
    + else
    + kmemcheck_access(regs, address, KMEMCHECK_READ);
    +
    + kmemcheck_show(regs);
    + return true;
    +}
    +
    int show_unhandled_signals = 1;

    /*
    @@ -638,7 +653,10 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
    if (unlikely(address >= TASK_SIZE64)) {
    #endif
    if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
    - vmalloc_fault(regs, address, error_code) >= 0)
    + vmalloc_fault(address) >= 0)
    + return;
    +
    + if (kmemcheck_fault(regs, address, error_code))
    return;

    /* Can handle a stale RO->RW TLB */
    diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
    index 806c6aa..de236e4 100644
    --- a/arch/x86/mm/init_32.c
    +++ b/arch/x86/mm/init_32.c
    @@ -92,7 +92,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
    if (!(pmd_val(*pmd) & _PAGE_PRESENT)) {
    pte_t *page_table = NULL;

    -#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
    +#ifdef CONFIG_DEBUG_PAGEALLOC
    page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
    #endif
    if (!page_table) {
    --
    1.5.4.1

    --
    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/

  2. Re: [PATCH] kmemcheck: use set_memory_4k() instead of disabling PSE


    * Vegard Nossum wrote:

    > Hi,
    >
    > With this, we reduce the overall impact of kmemcheck by reverting some
    > earlier, now unnecessary, changes:


    > Thanks a bunch to Andi Kleen for this brilliant solution. Now all
    > pages that kmemcheck handle will be 4k in size, and we need no
    > special-case code to handle larger pages.


    applied, thanks guys.

    Ingo
    --
    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/

+ Reply to Thread