From: Christophe Saout <christophe@saout.de>
To: Andrew Morton <akpm@osdl.org>
Cc: Jean-Luc Cooke <jlcooke@certainkey.com>,
jmorris@intercode.com.au, linux-kernel@vger.kernel.org
Subject: Re: cryptoapi highmem bug
Date: Wed, 25 Feb 2004 16:31:26 +0100 [thread overview]
Message-ID: <20040225153126.GA7395@leto.cs.pocnet.net> (raw)
In-Reply-To: <20040224220030.13160197.akpm@osdl.org>
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);
}
next prev parent reply other threads:[~2004-02-25 15:31 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-02-24 20:49 Christophe Saout
2004-02-24 22:34 ` Jean-Luc Cooke
2004-02-24 23:01 ` Christophe Saout
2004-02-25 4:32 ` Jean-Luc Cooke
2004-02-25 6:00 ` Andrew Morton
2004-02-25 13:27 ` James Morris
2004-02-25 15:17 ` Jean-Luc Cooke
2004-02-25 19:50 ` Andrew Morton
2004-02-25 21:27 ` Christophe Saout
2004-02-25 21:41 ` Jean-Luc Cooke
2004-02-25 22:55 ` [PATCH 1/2] move scatterwalk functions to own file Christophe Saout
2004-02-25 22:55 ` [PATCH 2/2] fix in-place de/encryption bug with highmem Christophe Saout
2004-02-26 4:13 ` James Morris
2004-02-26 11:03 ` Christophe Saout
2004-02-25 15:31 ` Christophe Saout [this message]
2004-02-25 15:51 ` cryptoapi highmem bug Christophe Saout
2004-02-25 15:44 ` Jean-Luc Cooke
2004-02-25 16:13 ` Christophe Saout
2004-02-25 16:09 ` Jean-Luc Cooke
2004-02-25 18:11 ` cryptoapi OMAC (was: cryptoapi highmem bug) Christophe Saout
2004-02-25 20:59 ` Jean-Luc Cooke
2004-02-25 21:44 ` Christophe Saout
2004-02-25 18:15 ` cryptoapi highmem bug Christophe Saout
2004-02-25 20:12 ` Jean-Luc Cooke
2004-02-25 20:39 ` Christophe Saout
2004-02-25 20:46 ` Jean-Luc Cooke
2004-02-25 21:36 ` Christophe Saout
2004-02-25 21:52 ` Jean-Luc Cooke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040225153126.GA7395@leto.cs.pocnet.net \
--to=christophe@saout.de \
--cc=akpm@osdl.org \
--cc=jlcooke@certainkey.com \
--cc=jmorris@intercode.com.au \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®