Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

crypto: scatterwalk - use kmap_local() not kmap_atomic()

kmap_atomic() is used to create short-lived mappings of pages that may
not be accessible via the kernel direct map. This is only needed on
32-bit architectures that implement CONFIG_HIGHMEM, but it can be used
on 64-bit other architectures too, where the returned mapping is simply
the kernel direct address of the page.

However, kmap_atomic() does not support migration on CONFIG_HIGHMEM
configurations, due to the use of per-CPU kmap slots, and so it disables
preemption on all architectures, not just the 32-bit ones. This implies
that all scatterwalk based crypto routines essentially execute with
preemption disabled all the time, which is less than ideal.

So let's switch scatterwalk_map/_unmap and the shash/ahash routines to
kmap_local() instead, which serves a similar purpose, but without the
resulting impact on preemption on architectures that have no need for
CONFIG_HIGHMEM.

Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "Elliott, Robert (Servers)" <elliott@hpe.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Ard Biesheuvel and committed by
Herbert Xu
aa969515 b517b0fb

+6 -6
+2 -2
crypto/ahash.c
··· 45 45 unsigned int nbytes = min(walk->entrylen, 46 46 ((unsigned int)(PAGE_SIZE)) - offset); 47 47 48 - walk->data = kmap_atomic(walk->pg); 48 + walk->data = kmap_local_page(walk->pg); 49 49 walk->data += offset; 50 50 51 51 if (offset & alignmask) { ··· 95 95 } 96 96 } 97 97 98 - kunmap_atomic(walk->data); 98 + kunmap_local(walk->data); 99 99 crypto_yield(walk->flags); 100 100 101 101 if (err)
+2 -2
crypto/shash.c
··· 320 320 nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) { 321 321 void *data; 322 322 323 - data = kmap_atomic(sg_page(sg)); 323 + data = kmap_local_page(sg_page(sg)); 324 324 err = crypto_shash_digest(desc, data + offset, nbytes, 325 325 req->result); 326 - kunmap_atomic(data); 326 + kunmap_local(data); 327 327 } else 328 328 err = crypto_shash_init(desc) ?: 329 329 shash_ahash_finup(req, desc);
+2 -2
include/crypto/scatterwalk.h
··· 53 53 54 54 static inline void scatterwalk_unmap(void *vaddr) 55 55 { 56 - kunmap_atomic(vaddr); 56 + kunmap_local(vaddr); 57 57 } 58 58 59 59 static inline void scatterwalk_start(struct scatter_walk *walk, ··· 65 65 66 66 static inline void *scatterwalk_map(struct scatter_walk *walk) 67 67 { 68 - return kmap_atomic(scatterwalk_page(walk)) + 68 + return kmap_local_page(scatterwalk_page(walk)) + 69 69 offset_in_page(walk->offset); 70 70 } 71 71