diff options
| -rw-r--r-- | arch/x86/kernel/microcode_core.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/microcode_intel.c | 22 |
2 files changed, 18 insertions, 8 deletions
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index cceb5bc3c3c2..2cd8c544e41a 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c | |||
| @@ -201,9 +201,9 @@ static int do_microcode_update(const void __user *buf, size_t size) | |||
| 201 | return error; | 201 | return error; |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | static int microcode_open(struct inode *unused1, struct file *unused2) | 204 | static int microcode_open(struct inode *inode, struct file *file) |
| 205 | { | 205 | { |
| 206 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; | 206 | return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM; |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | static ssize_t microcode_write(struct file *file, const char __user *buf, | 209 | static ssize_t microcode_write(struct file *file, const char __user *buf, |
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 85a343e28937..356170262a93 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
| @@ -343,10 +343,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | |||
| 343 | int (*get_ucode_data)(void *, const void *, size_t)) | 343 | int (*get_ucode_data)(void *, const void *, size_t)) |
| 344 | { | 344 | { |
| 345 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 345 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
| 346 | u8 *ucode_ptr = data, *new_mc = NULL, *mc; | 346 | u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL; |
| 347 | int new_rev = uci->cpu_sig.rev; | 347 | int new_rev = uci->cpu_sig.rev; |
| 348 | unsigned int leftover = size; | 348 | unsigned int leftover = size; |
| 349 | enum ucode_state state = UCODE_OK; | 349 | enum ucode_state state = UCODE_OK; |
| 350 | unsigned int curr_mc_size = 0; | ||
| 350 | 351 | ||
| 351 | while (leftover) { | 352 | while (leftover) { |
| 352 | struct microcode_header_intel mc_header; | 353 | struct microcode_header_intel mc_header; |
| @@ -361,9 +362,15 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | |||
| 361 | break; | 362 | break; |
| 362 | } | 363 | } |
| 363 | 364 | ||
| 364 | mc = vmalloc(mc_size); | 365 | /* For performance reasons, reuse mc area when possible */ |
| 365 | if (!mc) | 366 | if (!mc || mc_size > curr_mc_size) { |
| 366 | break; | 367 | if (mc) |
| 368 | vfree(mc); | ||
| 369 | mc = vmalloc(mc_size); | ||
| 370 | if (!mc) | ||
| 371 | break; | ||
| 372 | curr_mc_size = mc_size; | ||
| 373 | } | ||
| 367 | 374 | ||
| 368 | if (get_ucode_data(mc, ucode_ptr, mc_size) || | 375 | if (get_ucode_data(mc, ucode_ptr, mc_size) || |
| 369 | microcode_sanity_check(mc) < 0) { | 376 | microcode_sanity_check(mc) < 0) { |
| @@ -376,13 +383,16 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | |||
| 376 | vfree(new_mc); | 383 | vfree(new_mc); |
| 377 | new_rev = mc_header.rev; | 384 | new_rev = mc_header.rev; |
| 378 | new_mc = mc; | 385 | new_mc = mc; |
| 379 | } else | 386 | mc = NULL; /* trigger new vmalloc */ |
| 380 | vfree(mc); | 387 | } |
| 381 | 388 | ||
| 382 | ucode_ptr += mc_size; | 389 | ucode_ptr += mc_size; |
| 383 | leftover -= mc_size; | 390 | leftover -= mc_size; |
| 384 | } | 391 | } |
| 385 | 392 | ||
| 393 | if (mc) | ||
| 394 | vfree(mc); | ||
| 395 | |||
| 386 | if (leftover) { | 396 | if (leftover) { |
| 387 | if (new_mc) | 397 | if (new_mc) |
| 388 | vfree(new_mc); | 398 | vfree(new_mc); |
