lkml.org 
[lkml]   [2009]   [Sep]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH 1/2]: mm: Make vmalloc_user() align base kernel virtual address to SHMLBA.

    ( Andrew, this patch has mm/* effects - any objections? Would still like
    to get this into v2.6.32. )

    * David Miller <davem@davemloft.net> wrote:

    > When a vmalloc'd area is mmap'd into userspace, some kind of
    > co-ordination is necessary for this to work on platforms with cpu
    > D-caches which can have aliases.
    >
    > Otherwise kernel side writes won't be seen properly in userspace and
    > vice versa.
    >
    > If the kernel side mapping and the user side one have the same
    > alignment, modulo SHMLBA, this can work as long as VM_SHARED is
    > shared of VMA and for all current users this is true. VM_SHARED
    > will force SHMLBA alignment of the user side mmap on platforms
    > with D-cache aliasing matters.
    >
    > The bulk of this patch is just making it so that a specific alignment
    > can be passed down into __get_vm_area_node(). All existing callers
    > pass in '1' which preserves existing behavior. vmalloc_user() gives
    > SHMLBA for the alignment.
    >
    > As a side effect this should get the video media drivers and other
    > vmalloc_user() users into more working shape on such systems.
    >
    > Signed-off-by: David S. Miller <davem@davemloft.net>
    > ---
    > mm/vmalloc.c | 48 ++++++++++++++++++++++++++----------------------
    > 1 files changed, 26 insertions(+), 22 deletions(-)
    >
    > diff --git a/mm/vmalloc.c b/mm/vmalloc.c
    > index f8189a4..be15e03 100644
    > --- a/mm/vmalloc.c
    > +++ b/mm/vmalloc.c
    > @@ -29,6 +29,7 @@
    > #include <asm/atomic.h>
    > #include <asm/uaccess.h>
    > #include <asm/tlbflush.h>
    > +#include <asm/shmparam.h>
    >
    >
    > /*** Page table manipulation functions ***/
    > @@ -1123,13 +1124,12 @@ DEFINE_RWLOCK(vmlist_lock);
    > struct vm_struct *vmlist;
    >
    > static struct vm_struct *__get_vm_area_node(unsigned long size,
    > - unsigned long flags, unsigned long start, unsigned long end,
    > - int node, gfp_t gfp_mask, void *caller)
    > + unsigned long align, unsigned long flags, unsigned long start,
    > + unsigned long end, int node, gfp_t gfp_mask, void *caller)
    > {
    > static struct vmap_area *va;
    > struct vm_struct *area;
    > struct vm_struct *tmp, **p;
    > - unsigned long align = 1;
    >
    > BUG_ON(in_interrupt());
    > if (flags & VM_IOREMAP) {
    > @@ -1187,7 +1187,7 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
    > struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
    > unsigned long start, unsigned long end)
    > {
    > - return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL,
    > + return __get_vm_area_node(size, 1, flags, start, end, -1, GFP_KERNEL,
    > __builtin_return_address(0));
    > }
    > EXPORT_SYMBOL_GPL(__get_vm_area);
    > @@ -1196,7 +1196,7 @@ struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
    > unsigned long start, unsigned long end,
    > void *caller)
    > {
    > - return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL,
    > + return __get_vm_area_node(size, 1, flags, start, end, -1, GFP_KERNEL,
    > caller);
    > }
    >
    > @@ -1211,22 +1211,22 @@ struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
    > */
    > struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
    > {
    > - return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END,
    > + return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
    > -1, GFP_KERNEL, __builtin_return_address(0));
    > }
    >
    > struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
    > void *caller)
    > {
    > - return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END,
    > + return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
    > -1, GFP_KERNEL, caller);
    > }
    >
    > struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags,
    > int node, gfp_t gfp_mask)
    > {
    > - return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, node,
    > - gfp_mask, __builtin_return_address(0));
    > + return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
    > + node, gfp_mask, __builtin_return_address(0));
    > }
    >
    > static struct vm_struct *find_vm_area(const void *addr)
    > @@ -1385,7 +1385,8 @@ void *vmap(struct page **pages, unsigned int count,
    > }
    > EXPORT_SYMBOL(vmap);
    >
    > -static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
    > +static void *__vmalloc_node(unsigned long size, unsigned long align,
    > + gfp_t gfp_mask, pgprot_t prot,
    > int node, void *caller);
    > static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
    > pgprot_t prot, int node, void *caller)
    > @@ -1399,7 +1400,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
    > area->nr_pages = nr_pages;
    > /* Please note that the recursion is strictly bounded. */
    > if (array_size > PAGE_SIZE) {
    > - pages = __vmalloc_node(array_size, gfp_mask | __GFP_ZERO,
    > + pages = __vmalloc_node(array_size, 1, gfp_mask | __GFP_ZERO,
    > PAGE_KERNEL, node, caller);
    > area->flags |= VM_VPAGES;
    > } else {
    > @@ -1458,6 +1459,7 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
    > /**
    > * __vmalloc_node - allocate virtually contiguous memory
    > * @size: allocation size
    > + * @align: desired alignment
    > * @gfp_mask: flags for the page level allocator
    > * @prot: protection mask for the allocated pages
    > * @node: node to use for allocation or -1
    > @@ -1467,8 +1469,9 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
    > * allocator with @gfp_mask flags. Map them into contiguous
    > * kernel virtual space, using a pagetable protection of @prot.
    > */
    > -static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
    > - int node, void *caller)
    > +static void *__vmalloc_node(unsigned long size, unsigned long align,
    > + gfp_t gfp_mask, pgprot_t prot,
    > + int node, void *caller)
    > {
    > struct vm_struct *area;
    > void *addr;
    > @@ -1478,8 +1481,8 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
    > if (!size || (size >> PAGE_SHIFT) > num_physpages)
    > return NULL;
    >
    > - area = __get_vm_area_node(size, VM_ALLOC, VMALLOC_START, VMALLOC_END,
    > - node, gfp_mask, caller);
    > + area = __get_vm_area_node(size, align, VM_ALLOC, VMALLOC_START,
    > + VMALLOC_END, node, gfp_mask, caller);
    >
    > if (!area)
    > return NULL;
    > @@ -1498,7 +1501,7 @@ static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
    >
    > void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
    > {
    > - return __vmalloc_node(size, gfp_mask, prot, -1,
    > + return __vmalloc_node(size, 1, gfp_mask, prot, -1,
    > __builtin_return_address(0));
    > }
    > EXPORT_SYMBOL(__vmalloc);
    > @@ -1514,7 +1517,7 @@ EXPORT_SYMBOL(__vmalloc);
    > */
    > void *vmalloc(unsigned long size)
    > {
    > - return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
    > + return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
    > -1, __builtin_return_address(0));
    > }
    > EXPORT_SYMBOL(vmalloc);
    > @@ -1531,7 +1534,8 @@ void *vmalloc_user(unsigned long size)
    > struct vm_struct *area;
    > void *ret;
    >
    > - ret = __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
    > + ret = __vmalloc_node(size, SHMLBA,
    > + GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
    > PAGE_KERNEL, -1, __builtin_return_address(0));
    > if (ret) {
    > area = find_vm_area(ret);
    > @@ -1554,7 +1558,7 @@ EXPORT_SYMBOL(vmalloc_user);
    > */
    > void *vmalloc_node(unsigned long size, int node)
    > {
    > - return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
    > + return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
    > node, __builtin_return_address(0));
    > }
    > EXPORT_SYMBOL(vmalloc_node);
    > @@ -1577,7 +1581,7 @@ EXPORT_SYMBOL(vmalloc_node);
    >
    > void *vmalloc_exec(unsigned long size)
    > {
    > - return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
    > + return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
    > -1, __builtin_return_address(0));
    > }
    >
    > @@ -1598,7 +1602,7 @@ void *vmalloc_exec(unsigned long size)
    > */
    > void *vmalloc_32(unsigned long size)
    > {
    > - return __vmalloc_node(size, GFP_VMALLOC32, PAGE_KERNEL,
    > + return __vmalloc_node(size, 1, GFP_VMALLOC32, PAGE_KERNEL,
    > -1, __builtin_return_address(0));
    > }
    > EXPORT_SYMBOL(vmalloc_32);
    > @@ -1615,7 +1619,7 @@ void *vmalloc_32_user(unsigned long size)
    > struct vm_struct *area;
    > void *ret;
    >
    > - ret = __vmalloc_node(size, GFP_VMALLOC32 | __GFP_ZERO, PAGE_KERNEL,
    > + ret = __vmalloc_node(size, 1, GFP_VMALLOC32 | __GFP_ZERO, PAGE_KERNEL,
    > -1, __builtin_return_address(0));
    > if (ret) {
    > area = find_vm_area(ret);
    > --
    > 1.6.4.2


    \
     
     \ /
      Last update: 2009-09-18 14:19    [W:0.044 / U:59.512 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site