Commit b591ee3913b7eeef851451641c85e1e014d2103f
1 parent
cf29e3e303
Exists in
v2017.01-smarct4x
and in
37 other branches
x86: Correct problems in the microcode loading
There are several problems in the code. The device tree decode is incorrect in ways that are masked due to a matching bug. Both are fixed. Also microcode_read_rev() should be inline and called before the microcode is written. Note: microcode writing does not work correctly on ivybridge for me. Further work is needed to resolve this. But this patch tidies up the existing code so that will be easier. Signed-off-by: Simon Glass <sjg@chromium.org>
Showing 1 changed file with 15 additions and 10 deletions Side-by-side Diff
arch/x86/cpu/ivybridge/microcode_intel.c
... | ... | @@ -50,17 +50,17 @@ |
50 | 50 | update->date_code = fdtdec_get_int(blob, node, |
51 | 51 | "intel,date-code", 0); |
52 | 52 | update->processor_signature = fdtdec_get_int(blob, node, |
53 | - "intel.processor-signature", 0); | |
53 | + "intel,processor-signature", 0); | |
54 | 54 | update->checksum = fdtdec_get_int(blob, node, "intel,checksum", 0); |
55 | 55 | update->loader_revision = fdtdec_get_int(blob, node, |
56 | - "loader-revision", 0); | |
56 | + "intel,loader-revision", 0); | |
57 | 57 | update->processor_flags = fdtdec_get_int(blob, node, |
58 | - "processor-flags", 0); | |
58 | + "intel,processor-flags", 0); | |
59 | 59 | |
60 | 60 | return 0; |
61 | 61 | } |
62 | 62 | |
63 | -static uint32_t microcode_read_rev(void) | |
63 | +static inline uint32_t microcode_read_rev(void) | |
64 | 64 | { |
65 | 65 | /* |
66 | 66 | * Some Intel CPUs can be very finicky about the CPUID sequence used. |
... | ... | @@ -116,6 +116,7 @@ |
116 | 116 | { |
117 | 117 | struct microcode_update cpu, update; |
118 | 118 | const void *blob = gd->fdt_blob; |
119 | + int skipped; | |
119 | 120 | int count; |
120 | 121 | int node; |
121 | 122 | int ret; |
122 | 123 | |
... | ... | @@ -123,12 +124,13 @@ |
123 | 124 | microcode_read_cpu(&cpu); |
124 | 125 | node = 0; |
125 | 126 | count = 0; |
127 | + skipped = 0; | |
126 | 128 | do { |
127 | 129 | node = fdtdec_next_compatible(blob, node, |
128 | 130 | COMPAT_INTEL_MICROCODE); |
129 | 131 | if (node < 0) { |
130 | 132 | debug("%s: Found %d updates\n", __func__, count); |
131 | - return count ? 0 : -ENOENT; | |
133 | + return count ? 0 : skipped ? -EEXIST : -ENOENT; | |
132 | 134 | } |
133 | 135 | |
134 | 136 | ret = microcode_decode_node(blob, node, &update); |
135 | 137 | |
... | ... | @@ -137,12 +139,15 @@ |
137 | 139 | ret); |
138 | 140 | return ret; |
139 | 141 | } |
140 | - if (update.processor_signature == cpu.processor_signature && | |
141 | - (update.processor_flags & cpu.processor_flags)) { | |
142 | - debug("%s: Update already exists\n", __func__); | |
143 | - return -EEXIST; | |
142 | + if (!(update.processor_signature == cpu.processor_signature && | |
143 | + (update.processor_flags & cpu.processor_flags))) { | |
144 | + debug("%s: Skipping non-matching update, sig=%x, pf=%x\n", | |
145 | + __func__, update.processor_signature, | |
146 | + update.processor_flags); | |
147 | + skipped++; | |
148 | + continue; | |
144 | 149 | } |
145 | - | |
150 | + ret = microcode_read_rev(); | |
146 | 151 | wrmsr(0x79, (ulong)update.data, 0); |
147 | 152 | debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n", |
148 | 153 | microcode_read_rev(), update.date_code & 0xffff, |