hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/arch/x86/kernel/cpu/microcode/intel.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Intel CPU Microcode Update Driver for Linux
34 *
....@@ -8,11 +9,6 @@
89 *
910 * Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
1011 * H Peter Anvin" <hpa@zytor.com>
11
- *
12
- * This program is free software; you can redistribute it and/or
13
- * modify it under the terms of the GNU General Public License
14
- * as published by the Free Software Foundation; either version
15
- * 2 of the License, or (at your option) any later version.
1612 */
1713
1814 /*
....@@ -31,6 +27,7 @@
3127 #include <linux/kernel.h>
3228 #include <linux/slab.h>
3329 #include <linux/cpu.h>
30
+#include <linux/uio.h>
3431 #include <linux/mm.h>
3532
3633 #include <asm/microcode_intel.h>
....@@ -751,6 +748,7 @@
751748 {
752749 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
753750 struct cpuinfo_x86 *c = &cpu_data(cpu);
751
+ bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
754752 struct microcode_intel *mc;
755753 enum ucode_state ret;
756754 static int prev_rev;
....@@ -796,7 +794,7 @@
796794 return UCODE_ERROR;
797795 }
798796
799
- if (rev != prev_rev) {
797
+ if (bsp && rev != prev_rev) {
800798 pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
801799 rev,
802800 mc->hdr.date & 0xffff,
....@@ -812,38 +810,39 @@
812810 c->microcode = rev;
813811
814812 /* Update boot_cpu_data's revision too, if we're on the BSP: */
815
- if (c->cpu_index == boot_cpu_data.cpu_index)
813
+ if (bsp)
816814 boot_cpu_data.microcode = rev;
817815
818816 return ret;
819817 }
820818
821
-static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
822
- int (*get_ucode_data)(void *, const void *, size_t))
819
+static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
823820 {
824821 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
825
- u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
826
- int new_rev = uci->cpu_sig.rev;
827
- unsigned int leftover = size;
828822 unsigned int curr_mc_size = 0, new_mc_size = 0;
829
- unsigned int csig, cpf;
830823 enum ucode_state ret = UCODE_OK;
824
+ int new_rev = uci->cpu_sig.rev;
825
+ u8 *new_mc = NULL, *mc = NULL;
826
+ unsigned int csig, cpf;
831827
832
- while (leftover) {
828
+ while (iov_iter_count(iter)) {
833829 struct microcode_header_intel mc_header;
834
- unsigned int mc_size;
830
+ unsigned int mc_size, data_size;
831
+ u8 *data;
835832
836
- if (leftover < sizeof(mc_header)) {
837
- pr_err("error! Truncated header in microcode data file\n");
833
+ if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) {
834
+ pr_err("error! Truncated or inaccessible header in microcode data file\n");
838835 break;
839836 }
840837
841
- if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header)))
842
- break;
843
-
844838 mc_size = get_totalsize(&mc_header);
845
- if (!mc_size || mc_size > leftover) {
846
- pr_err("error! Bad data in microcode data file\n");
839
+ if (mc_size < sizeof(mc_header)) {
840
+ pr_err("error! Bad data in microcode data file (totalsize too small)\n");
841
+ break;
842
+ }
843
+ data_size = mc_size - sizeof(mc_header);
844
+ if (data_size > iov_iter_count(iter)) {
845
+ pr_err("error! Bad data in microcode data file (truncated file?)\n");
847846 break;
848847 }
849848
....@@ -856,7 +855,9 @@
856855 curr_mc_size = mc_size;
857856 }
858857
859
- if (get_ucode_data(mc, ucode_ptr, mc_size) ||
858
+ memcpy(mc, &mc_header, sizeof(mc_header));
859
+ data = mc + sizeof(mc_header);
860
+ if (!copy_from_iter_full(data, data_size, iter) ||
860861 microcode_sanity_check(mc, 1) < 0) {
861862 break;
862863 }
....@@ -871,14 +872,11 @@
871872 mc = NULL; /* trigger new vmalloc */
872873 ret = UCODE_NEW;
873874 }
874
-
875
- ucode_ptr += mc_size;
876
- leftover -= mc_size;
877875 }
878876
879877 vfree(mc);
880878
881
- if (leftover) {
879
+ if (iov_iter_count(iter)) {
882880 vfree(new_mc);
883881 return UCODE_ERROR;
884882 }
....@@ -900,12 +898,6 @@
900898 cpu, new_rev, uci->cpu_sig.rev);
901899
902900 return ret;
903
-}
904
-
905
-static int get_ucode_fw(void *to, const void *from, size_t n)
906
-{
907
- memcpy(to, from, n);
908
- return 0;
909901 }
910902
911903 static bool is_blacklisted(unsigned int cpu)
....@@ -934,10 +926,12 @@
934926 static enum ucode_state request_microcode_fw(int cpu, struct device *device,
935927 bool refresh_fw)
936928 {
937
- char name[30];
938929 struct cpuinfo_x86 *c = &cpu_data(cpu);
939930 const struct firmware *firmware;
931
+ struct iov_iter iter;
940932 enum ucode_state ret;
933
+ struct kvec kvec;
934
+ char name[30];
941935
942936 if (is_blacklisted(cpu))
943937 return UCODE_NFOUND;
....@@ -950,26 +944,30 @@
950944 return UCODE_NFOUND;
951945 }
952946
953
- ret = generic_load_microcode(cpu, (void *)firmware->data,
954
- firmware->size, &get_ucode_fw);
947
+ kvec.iov_base = (void *)firmware->data;
948
+ kvec.iov_len = firmware->size;
949
+ iov_iter_kvec(&iter, WRITE, &kvec, 1, firmware->size);
950
+ ret = generic_load_microcode(cpu, &iter);
955951
956952 release_firmware(firmware);
957953
958954 return ret;
959955 }
960956
961
-static int get_ucode_user(void *to, const void *from, size_t n)
962
-{
963
- return copy_from_user(to, from, n);
964
-}
965
-
966957 static enum ucode_state
967958 request_microcode_user(int cpu, const void __user *buf, size_t size)
968959 {
960
+ struct iov_iter iter;
961
+ struct iovec iov;
962
+
969963 if (is_blacklisted(cpu))
970964 return UCODE_NFOUND;
971965
972
- return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
966
+ iov.iov_base = (void __user *)buf;
967
+ iov.iov_len = size;
968
+ iov_iter_init(&iter, WRITE, &iov, 1, size);
969
+
970
+ return generic_load_microcode(cpu, &iter);
973971 }
974972
975973 static struct microcode_ops microcode_intel_ops = {