crypto: padlock-aes - work around Nano CPU errata in ECB mode

The VIA Nano processor has a bug that makes it prefetch extra data
during encryption operations, causing spurious page faults. Extend
existing workarounds for ECB mode to copy the data to an temporary
buffer to avoid the problem.

Signed-off-by: Chuck Ebbert <cebbert@redhat.com>
Acked-by: Harald Welte <HaraldWelte@viatech.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by Chuck Ebbert and committed by Herbert Xu a76c1c23 1d89b30c

+46 -35
+46 -35
drivers/crypto/padlock-aes.c
··· 18 #include <linux/percpu.h> 19 #include <linux/smp.h> 20 #include <asm/byteorder.h> 21 #include <asm/i387.h> 22 #include "padlock.h" 23 24 /* Control word. */ 25 struct cword { ··· 181 */ 182 183 static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key, 184 - struct cword *control_word) 185 { 186 asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ 187 : "+S"(input), "+D"(output) 188 - : "d"(control_word), "b"(key), "c"(1)); 189 } 190 191 - static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, struct cword *cword) 192 { 193 - u8 buf[AES_BLOCK_SIZE * 2 + PADLOCK_ALIGNMENT - 1]; 194 u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); 195 196 - memcpy(tmp, in, AES_BLOCK_SIZE); 197 - padlock_xcrypt(tmp, out, key, cword); 198 } 199 200 static inline void aes_crypt(const u8 *in, u8 *out, u32 *key, 201 - struct cword *cword) 202 { 203 - /* padlock_xcrypt requires at least two blocks of data. */ 204 - if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) & 205 - (PAGE_SIZE - 1)))) { 206 - aes_crypt_copy(in, out, key, cword); 207 return; 208 } 209 210 - padlock_xcrypt(in, out, key, cword); 211 } 212 213 static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, 214 void *control_word, u32 count) 215 { 216 - if (count == 1) { 217 - aes_crypt(input, output, key, control_word); 218 return; 219 } 220 221 - asm volatile ("test $1, %%cl;" 222 - "je 1f;" 223 - #ifndef CONFIG_X86_64 224 - "lea -1(%%ecx), %%eax;" 225 - "mov $1, %%ecx;" 226 - #else 227 - "lea -1(%%rcx), %%rax;" 228 - "mov $1, %%rcx;" 229 - #endif 230 - ".byte 0xf3,0x0f,0xa7,0xc8;" /* rep xcryptecb */ 231 - #ifndef CONFIG_X86_64 232 - "mov %%eax, %%ecx;" 233 - #else 234 - "mov %%rax, %%rcx;" 235 - #endif 236 - "1:" 237 - ".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ 238 : "+S"(input), "+D"(output) 239 - : "d"(control_word), "b"(key), "c"(count) 240 - : "ax"); 241 } 242 243 static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, ··· 253 254 padlock_reset_key(&ctx->cword.encrypt); 255 ts_state = irq_ts_save(); 256 - aes_crypt(in, out, ctx->E, &ctx->cword.encrypt); 257 irq_ts_restore(ts_state); 258 padlock_store_cword(&ctx->cword.encrypt); 259 } ··· 265 266 padlock_reset_key(&ctx->cword.encrypt); 267 ts_state = irq_ts_save(); 268 - aes_crypt(in, out, ctx->D, &ctx->cword.decrypt); 269 irq_ts_restore(ts_state); 270 padlock_store_cword(&ctx->cword.encrypt); 271 } ··· 458 static int __init padlock_init(void) 459 { 460 int ret; 461 462 if (!cpu_has_xcrypt) { 463 printk(KERN_NOTICE PFX "VIA PadLock not detected.\n"); ··· 480 goto cbc_aes_err; 481 482 printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n"); 483 484 out: 485 return ret;
··· 18 #include <linux/percpu.h> 19 #include <linux/smp.h> 20 #include <asm/byteorder.h> 21 + #include <asm/processor.h> 22 #include <asm/i387.h> 23 #include "padlock.h" 24 + 25 + /* number of data blocks actually fetched for each xcrypt insn */ 26 + static unsigned int ecb_fetch_blocks = 2; 27 + static unsigned int cbc_fetch_blocks = 1; 28 + 29 + #define ecb_fetch_bytes (ecb_fetch_blocks * AES_BLOCK_SIZE) 30 + #define cbc_fetch_bytes (cbc_fetch_blocks * AES_BLOCK_SIZE) 31 32 /* Control word. */ 33 struct cword { ··· 173 */ 174 175 static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key, 176 + struct cword *control_word, int count) 177 { 178 asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ 179 : "+S"(input), "+D"(output) 180 + : "d"(control_word), "b"(key), "c"(count)); 181 } 182 183 + static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, 184 + struct cword *cword, int count) 185 { 186 + /* 187 + * Padlock prefetches extra data so we must provide mapped input buffers. 188 + * Assume there are at least 16 bytes of stack already in use. 189 + */ 190 + u8 buf[AES_BLOCK_SIZE * 7 + PADLOCK_ALIGNMENT - 1]; 191 u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); 192 193 + memcpy(tmp, in, count * AES_BLOCK_SIZE); 194 + padlock_xcrypt(tmp, out, key, cword, count); 195 } 196 197 static inline void aes_crypt(const u8 *in, u8 *out, u32 *key, 198 + struct cword *cword, int count) 199 { 200 + /* Padlock in ECB mode fetches at least ecb_fetch_bytes of data. 201 + * We could avoid some copying here but it's probably not worth it. 202 + */ 203 + if (unlikely(((unsigned long)in & PAGE_SIZE) + ecb_fetch_bytes > PAGE_SIZE)) { 204 + aes_crypt_copy(in, out, key, cword, count); 205 return; 206 } 207 208 + padlock_xcrypt(in, out, key, cword, count); 209 } 210 211 static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, 212 void *control_word, u32 count) 213 { 214 + u32 initial = count & (ecb_fetch_blocks - 1); 215 + 216 + if (count < ecb_fetch_blocks) { 217 + aes_crypt(input, output, key, control_word, count); 218 return; 219 } 220 221 + if (initial) 222 + asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ 223 + : "+S"(input), "+D"(output) 224 + : "d"(control_word), "b"(key), "c"(initial)); 225 + 226 + asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ 227 : "+S"(input), "+D"(output) 228 + : "d"(control_word), "b"(key), "c"(count - initial)); 229 } 230 231 static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, ··· 249 250 padlock_reset_key(&ctx->cword.encrypt); 251 ts_state = irq_ts_save(); 252 + aes_crypt(in, out, ctx->E, &ctx->cword.encrypt, 1); 253 irq_ts_restore(ts_state); 254 padlock_store_cword(&ctx->cword.encrypt); 255 } ··· 261 262 padlock_reset_key(&ctx->cword.encrypt); 263 ts_state = irq_ts_save(); 264 + aes_crypt(in, out, ctx->D, &ctx->cword.decrypt, 1); 265 irq_ts_restore(ts_state); 266 padlock_store_cword(&ctx->cword.encrypt); 267 } ··· 454 static int __init padlock_init(void) 455 { 456 int ret; 457 + struct cpuinfo_x86 *c = &cpu_data(0); 458 459 if (!cpu_has_xcrypt) { 460 printk(KERN_NOTICE PFX "VIA PadLock not detected.\n"); ··· 475 goto cbc_aes_err; 476 477 printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n"); 478 + 479 + if (c->x86 == 6 && c->x86_model == 15 && c->x86_mask == 2) { 480 + ecb_fetch_blocks = 8; 481 + cbc_fetch_blocks = 4; /* NOTE: notused */ 482 + printk(KERN_NOTICE PFX "VIA Nano stepping 2 detected: enabling workaround.\n"); 483 + } 484 485 out: 486 return ret;