From patchwork Thu Feb 21 23:05:58 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 222436 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id B88EA2C0501 for ; Fri, 22 Feb 2013 10:07:06 +1100 (EST) Received: from mail-vc0-f202.google.com (mail-vc0-f202.google.com [209.85.220.202]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 0C43A2C007A for ; Fri, 22 Feb 2013 10:06:02 +1100 (EST) Received: by mail-vc0-f202.google.com with SMTP id m8so9350vcd.5 for ; Thu, 21 Feb 2013 15:05:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:subject:to:cc:from:date:mime-version:content-type :content-transfer-encoding:message-id:x-gm-message-state; bh=8I9mT7XVQBDpNCWCfUM2a68POme4sSjn4XkFXoHhvkE=; b=bZHwO7nfBKzzgAI1s77Yr6gyYqUVfbGa1pd3iKbQCjsPOfd4Yj5FHu1WDPq/x3EYOq OsvfpZ3JpZXMLJhkFMAcflCihG1MbpYeU4dF5EMFwoIRzfI8NxOtJfRuSojRJsj4xrIQ mX/+9RSJfB/gPv3WokmO2DNyufz5xy1drfnPH8VOl7SO4DS5/LWDbf1yYKvOxG2wOTjF 2dxLKgYU+flymg2IljQQkoBwSV67uwczFbLBQRhx/4cZQm8+LC95Tu+0e/Tu/Hzboblm CXulOl7sYobGwwepdrjYbZHHUxhIVq38iBSmQV1DpZ3B+NOl1DdMd76CGYjEkVuCjXwr tLwg== X-Received: by 10.236.81.80 with SMTP id l56mr13184063yhe.16.1361487959367; Thu, 21 Feb 2013 15:05:59 -0800 (PST) Received: from corp2gmr1-1.hot.corp.google.com (corp2gmr1-1.hot.corp.google.com [172.24.189.92]) by gmr-mx.google.com with ESMTPS id h26si34592yhf.3.2013.02.21.15.05.59 (version=TLSv1.1 cipher=AES128-SHA bits=128/128); Thu, 21 Feb 2013 15:05:59 -0800 (PST) Received: from localhost.localdomain (akpm.mtv.corp.google.com [172.17.130.154]) by corp2gmr1-1.hot.corp.google.com (Postfix) with ESMTP id C201931C1B7; Thu, 21 Feb 2013 15:05:58 -0800 (PST) Subject: [patch 2/2] mm: use vm_unmapped_area() on powerpc architecture To: benh@kernel.crashing.org From: akpm@linux-foundation.org Date: Thu, 21 Feb 2013 15:05:58 -0800 MIME-Version: 1.0 Message-Id: <20130221230558.C201931C1B7@corp2gmr1-1.hot.corp.google.com> X-Gm-Message-State: ALoCoQmkrKVHgrn8IK0qWTwaSZB00K650HE1stsmBXEnONePLccCNmn9WylesDYRAoT2DgqYzvY8 Cc: paulus@samba.org, akpm@linux-foundation.org, walken@google.com, linuxppc-dev@lists.ozlabs.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" From: Michel Lespinasse Subject: mm: use vm_unmapped_area() on powerpc architecture Update the powerpc slice_get_unmapped_area function to make use of vm_unmapped_area() instead of implementing a brute force search. Signed-off-by: Michel Lespinasse Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Signed-off-by: Andrew Morton Acked-by: David Gibson --- arch/powerpc/mm/slice.c | 123 ++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 45 deletions(-) diff -puN arch/powerpc/mm/slice.c~mm-use-vm_unmapped_area-on-powerpc-architecture arch/powerpc/mm/slice.c --- a/arch/powerpc/mm/slice.c~mm-use-vm_unmapped_area-on-powerpc-architecture +++ a/arch/powerpc/mm/slice.c @@ -237,36 +237,69 @@ static void slice_convert(struct mm_stru #endif } +/* + * Compute which slice addr is part of; + * set *boundary_addr to the start or end boundary of that slice + * (depending on 'end' parameter); + * return boolean indicating if the slice is marked as available in the + * 'available' slice_mark. + */ +static bool slice_scan_available(unsigned long addr, + struct slice_mask available, + int end, + unsigned long *boundary_addr) +{ + unsigned long slice; + if (addr < SLICE_LOW_TOP) { + slice = GET_LOW_SLICE_INDEX(addr); + *boundary_addr = (slice + end) << SLICE_LOW_SHIFT; + return !!(available.low_slices & (1u << slice)); + } else { + slice = GET_HIGH_SLICE_INDEX(addr); + *boundary_addr = (slice + end) ? + ((slice + end) << SLICE_HIGH_SHIFT) : SLICE_LOW_TOP; + return !!(available.high_slices & (1u << slice)); + } +} + static unsigned long slice_find_area_bottomup(struct mm_struct *mm, unsigned long len, struct slice_mask available, int psize) { - struct vm_area_struct *vma; - unsigned long addr; - struct slice_mask mask; int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); + unsigned long addr, found, next_end; + struct vm_unmapped_area_info info; - addr = TASK_UNMAPPED_BASE; - - for (;;) { - addr = _ALIGN_UP(addr, 1ul << pshift); - if ((TASK_SIZE - len) < addr) - break; - vma = find_vma(mm, addr); - BUG_ON(vma && (addr >= vma->vm_end)); + info.flags = 0; + info.length = len; + info.align_mask = PAGE_MASK & ((1ul << pshift) - 1); + info.align_offset = 0; - mask = slice_range_to_mask(addr, len); - if (!slice_check_fit(mask, available)) { - if (addr < SLICE_LOW_TOP) - addr = _ALIGN_UP(addr + 1, 1ul << SLICE_LOW_SHIFT); - else - addr = _ALIGN_UP(addr + 1, 1ul << SLICE_HIGH_SHIFT); + addr = TASK_UNMAPPED_BASE; + while (addr < TASK_SIZE) { + info.low_limit = addr; + if (!slice_scan_available(addr, available, 1, &addr)) continue; + + next_slice: + /* + * At this point [info.low_limit; addr) covers + * available slices only and ends at a slice boundary. + * Check if we need to reduce the range, or if we can + * extend it to cover the next available slice. + */ + if (addr >= TASK_SIZE) + addr = TASK_SIZE; + else if (slice_scan_available(addr, available, 1, &next_end)) { + addr = next_end; + goto next_slice; } - if (!vma || addr + len <= vma->vm_start) - return addr; - addr = vma->vm_end; + info.high_limit = addr; + + found = vm_unmapped_area(&info); + if (!(found & ~PAGE_MASK)) + return found; } return -ENOMEM; @@ -277,39 +310,39 @@ static unsigned long slice_find_area_top struct slice_mask available, int psize) { - struct vm_area_struct *vma; - unsigned long addr; - struct slice_mask mask; int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); + unsigned long addr, found, prev; + struct vm_unmapped_area_info info; - addr = mm->mmap_base; - while (addr > len) { - /* Go down by chunk size */ - addr = _ALIGN_DOWN(addr - len, 1ul << pshift); + info.flags = VM_UNMAPPED_AREA_TOPDOWN; + info.length = len; + info.align_mask = PAGE_MASK & ((1ul << pshift) - 1); + info.align_offset = 0; - /* Check for hit with different page size */ - mask = slice_range_to_mask(addr, len); - if (!slice_check_fit(mask, available)) { - if (addr < SLICE_LOW_TOP) - addr = _ALIGN_DOWN(addr, 1ul << SLICE_LOW_SHIFT); - else if (addr < (1ul << SLICE_HIGH_SHIFT)) - addr = SLICE_LOW_TOP; - else - addr = _ALIGN_DOWN(addr, 1ul << SLICE_HIGH_SHIFT); + addr = mm->mmap_base; + while (addr > PAGE_SIZE) { + info.high_limit = addr; + if (!slice_scan_available(addr - 1, available, 0, &addr)) continue; - } + prev_slice: /* - * Lookup failure means no vma is above this address, - * else if new region fits below vma->vm_start, - * return with success: + * At this point [addr; info.high_limit) covers + * available slices only and starts at a slice boundary. + * Check if we need to reduce the range, or if we can + * extend it to cover the previous available slice. */ - vma = find_vma(mm, addr); - if (!vma || (addr + len) <= vma->vm_start) - return addr; + if (addr < PAGE_SIZE) + addr = PAGE_SIZE; + else if (slice_scan_available(addr - 1, available, 0, &prev)) { + addr = prev; + goto prev_slice; + } + info.low_limit = addr; - /* try just below the current vma->vm_start */ - addr = vma->vm_start; + found = vm_unmapped_area(&info); + if (!(found & ~PAGE_MASK)) + return found; } /*