lkml.org 
[lkml]   [2004]   [Feb]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: cryptoapi highmem bug
    On Tue, Feb 24, 2004 at 10:00:30PM -0800, Andrew Morton wrote:

    > I don't think there is a practical way of doing this. It would involve
    > comparing the virtual address with the kmap and atomic kmap regions,
    > performing a pagetable walk, extracting the pageframe. If the page is not
    > in a kmap area generate the pageframe directly. Make that work on all
    > architectures. Very yuk.

    We could also "simply" avoid to map the same page twice. My first idea
    turned out slightly more complicated than I expected but works.

    It's just a proof of concept though, it would be less complicated if we
    would just pass the other walk struct to the functions that take one
    and let them do the checking (no need to disable preemption and use
    per cpu variables). Hmm.


    --- linux-2.6.3/crypto/cipher.c 2004-02-25 13:49:53.000000000 +0100
    +++ linux-2.6.3.test/crypto/cipher.c 2004-02-25 16:23:53.094207712 +0100
    @@ -15,6 +15,7 @@
    #include <linux/kernel.h>
    #include <linux/crypto.h>
    #include <linux/errno.h>
    +#include <linux/percpu.h>
    #include <linux/mm.h>
    #include <linux/slab.h>
    #include <linux/pagemap.h>
    @@ -42,6 +43,14 @@
    KM_SOFTIRQ1,
    };

    +struct kmapped_page {
    + struct page *page;
    + void *vaddr;
    + int out;
    +};
    +
    +static DEFINE_PER_CPU(struct kmapped_page[4], kmapped_pages);
    +
    static inline void xor_64(u8 *a, const u8 *b)
    {
    ((u32 *)a)[0] ^= ((u32 *)b)[0];
    @@ -64,7 +73,7 @@
    return sg + 1;
    }

    -void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
    +static void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
    {
    if (nbytes <= walk->len_this_page &&
    (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
    @@ -98,7 +107,38 @@

    static void scatterwalk_map(struct scatter_walk *walk, int out)
    {
    - walk->data = crypto_kmap(walk->page, out) + walk->offset;
    + struct kmapped_page *kmaps;
    + int idx = (in_softirq() ? 2 : 0) + out;
    + void *vaddr;
    +
    + preempt_disable();
    + kmaps = __get_cpu_var(kmapped_pages);
    +
    + if (kmaps[idx ^ 1].page == walk->page) {
    + vaddr = kmaps[idx ^ 1].vaddr;
    + out = kmaps[idx ^ 1].out;
    + } else
    + vaddr = crypto_kmap(walk->page, out);
    +
    + kmaps[idx].page = walk->page;
    + kmaps[idx].vaddr = vaddr;
    + kmaps[idx].out = out;
    +
    + walk->data = vaddr + walk->offset;
    +}
    +
    +static void scatterwalk_unmap(void *vaddr, int out)
    +{
    + struct kmapped_page *kmaps = __get_cpu_var(kmapped_pages);
    + int idx = (in_softirq() ? 2 : 0) + out;
    +
    + if (kmaps[idx ^ 1].page != kmaps[idx].page)
    + crypto_kunmap(vaddr, kmaps[idx].out);
    +
    + kmaps[idx].page = NULL;
    + kmaps[idx].vaddr = NULL;
    +
    + preempt_enable();
    }

    static void scatter_page_done(struct scatter_walk *walk, int out,
    @@ -127,7 +167,7 @@

    static void scatter_done(struct scatter_walk *walk, int out, int more)
    {
    - crypto_kunmap(walk->data, out);
    + scatterwalk_unmap(walk->data, out);
    if (walk->len_this_page == 0 || !more)
    scatter_page_done(walk, out, more);
    }
    @@ -145,7 +185,7 @@
    buf += walk->len_this_page;
    nbytes -= walk->len_this_page;

    - crypto_kunmap(walk->data, out);
    + scatterwalk_unmap(walk->data, out);
    scatter_page_done(walk, out, 1);
    scatterwalk_map(walk, out);
    }
    -
    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/
    \
     
     \ /
      Last update: 2005-03-22 14:01    [W:4.702 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site