hc
2024-02-19 1c055e55a242a33e574e48be530e06770a210dcd
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>
....@@ -662,7 +659,6 @@
662659 else
663660 iup = &intel_ucode_patch;
664661
665
-reget:
666662 if (!*iup) {
667663 patch = __load_ucode_intel(&uci);
668664 if (!patch)
....@@ -673,12 +669,7 @@
673669
674670 uci.mc = *iup;
675671
676
- if (apply_microcode_early(&uci, true)) {
677
- /* Mixed-silicon system? Try to refetch the proper patch: */
678
- *iup = NULL;
679
-
680
- goto reget;
681
- }
672
+ apply_microcode_early(&uci, true);
682673 }
683674
684675 static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
....@@ -751,6 +742,7 @@
751742 {
752743 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
753744 struct cpuinfo_x86 *c = &cpu_data(cpu);
745
+ bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
754746 struct microcode_intel *mc;
755747 enum ucode_state ret;
756748 static int prev_rev;
....@@ -796,7 +788,7 @@
796788 return UCODE_ERROR;
797789 }
798790
799
- if (rev != prev_rev) {
791
+ if (bsp && rev != prev_rev) {
800792 pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
801793 rev,
802794 mc->hdr.date & 0xffff,
....@@ -812,38 +804,39 @@
812804 c->microcode = rev;
813805
814806 /* Update boot_cpu_data's revision too, if we're on the BSP: */
815
- if (c->cpu_index == boot_cpu_data.cpu_index)
807
+ if (bsp)
816808 boot_cpu_data.microcode = rev;
817809
818810 return ret;
819811 }
820812
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))
813
+static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
823814 {
824815 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;
828816 unsigned int curr_mc_size = 0, new_mc_size = 0;
829
- unsigned int csig, cpf;
830817 enum ucode_state ret = UCODE_OK;
818
+ int new_rev = uci->cpu_sig.rev;
819
+ u8 *new_mc = NULL, *mc = NULL;
820
+ unsigned int csig, cpf;
831821
832
- while (leftover) {
822
+ while (iov_iter_count(iter)) {
833823 struct microcode_header_intel mc_header;
834
- unsigned int mc_size;
824
+ unsigned int mc_size, data_size;
825
+ u8 *data;
835826
836
- if (leftover < sizeof(mc_header)) {
837
- pr_err("error! Truncated header in microcode data file\n");
827
+ if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) {
828
+ pr_err("error! Truncated or inaccessible header in microcode data file\n");
838829 break;
839830 }
840831
841
- if (get_ucode_data(&mc_header, ucode_ptr, sizeof(mc_header)))
842
- break;
843
-
844832 mc_size = get_totalsize(&mc_header);
845
- if (!mc_size || mc_size > leftover) {
846
- pr_err("error! Bad data in microcode data file\n");
833
+ if (mc_size < sizeof(mc_header)) {
834
+ pr_err("error! Bad data in microcode data file (totalsize too small)\n");
835
+ break;
836
+ }
837
+ data_size = mc_size - sizeof(mc_header);
838
+ if (data_size > iov_iter_count(iter)) {
839
+ pr_err("error! Bad data in microcode data file (truncated file?)\n");
847840 break;
848841 }
849842
....@@ -856,7 +849,9 @@
856849 curr_mc_size = mc_size;
857850 }
858851
859
- if (get_ucode_data(mc, ucode_ptr, mc_size) ||
852
+ memcpy(mc, &mc_header, sizeof(mc_header));
853
+ data = mc + sizeof(mc_header);
854
+ if (!copy_from_iter_full(data, data_size, iter) ||
860855 microcode_sanity_check(mc, 1) < 0) {
861856 break;
862857 }
....@@ -871,14 +866,11 @@
871866 mc = NULL; /* trigger new vmalloc */
872867 ret = UCODE_NEW;
873868 }
874
-
875
- ucode_ptr += mc_size;
876
- leftover -= mc_size;
877869 }
878870
879871 vfree(mc);
880872
881
- if (leftover) {
873
+ if (iov_iter_count(iter)) {
882874 vfree(new_mc);
883875 return UCODE_ERROR;
884876 }
....@@ -900,12 +892,6 @@
900892 cpu, new_rev, uci->cpu_sig.rev);
901893
902894 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;
909895 }
910896
911897 static bool is_blacklisted(unsigned int cpu)
....@@ -934,10 +920,12 @@
934920 static enum ucode_state request_microcode_fw(int cpu, struct device *device,
935921 bool refresh_fw)
936922 {
937
- char name[30];
938923 struct cpuinfo_x86 *c = &cpu_data(cpu);
939924 const struct firmware *firmware;
925
+ struct iov_iter iter;
940926 enum ucode_state ret;
927
+ struct kvec kvec;
928
+ char name[30];
941929
942930 if (is_blacklisted(cpu))
943931 return UCODE_NFOUND;
....@@ -950,26 +938,30 @@
950938 return UCODE_NFOUND;
951939 }
952940
953
- ret = generic_load_microcode(cpu, (void *)firmware->data,
954
- firmware->size, &get_ucode_fw);
941
+ kvec.iov_base = (void *)firmware->data;
942
+ kvec.iov_len = firmware->size;
943
+ iov_iter_kvec(&iter, WRITE, &kvec, 1, firmware->size);
944
+ ret = generic_load_microcode(cpu, &iter);
955945
956946 release_firmware(firmware);
957947
958948 return ret;
959949 }
960950
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
-
966951 static enum ucode_state
967952 request_microcode_user(int cpu, const void __user *buf, size_t size)
968953 {
954
+ struct iov_iter iter;
955
+ struct iovec iov;
956
+
969957 if (is_blacklisted(cpu))
970958 return UCODE_NFOUND;
971959
972
- return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
960
+ iov.iov_base = (void __user *)buf;
961
+ iov.iov_len = size;
962
+ iov_iter_init(&iter, WRITE, &iov, 1, size);
963
+
964
+ return generic_load_microcode(cpu, &iter);
973965 }
974966
975967 static struct microcode_ops microcode_intel_ops = {