Bug Summary

File:arch/amd64/amd64/ucode.c
Warning:line 210, column 3
Value stored to 'level' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ucode.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/arch/amd64/amd64/ucode.c
1/* $OpenBSD: ucode.c,v 1.8 2023/09/10 09:32:31 jsg Exp $ */
2/*
3 * Copyright (c) 2018 Stefan Fritsch <fritsch@genua.de>
4 * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/systm.h>
21#include <sys/mutex.h>
22#include <sys/malloc.h>
23
24#include <uvm/uvm_extern.h>
25
26#include <machine/cpu.h>
27#include <machine/cpufunc.h>
28#include <machine/specialreg.h>
29#include <machine/biosvar.h>
30
31/* #define UCODE_DEBUG */
32#ifdef UCODE_DEBUG
33#define DPRINTF(x)do { ; } while (0) do { if (cpu_ucode_debug > 0) printf x; } while (0)
34#define DPRINTFN(n, x)do { ; } while (0) do { if (cpu_ucode_debug >= (n)) printf x; } while (0)
35int cpu_ucode_debug = 1;
36#else
37#define DPRINTF(x)do { ; } while (0) do { ; } while (0)
38#define DPRINTFN(n, x)do { ; } while (0) do { ; } while (0)
39#endif
40
41struct intel_ucode_header {
42 uint32_t header_version;
43 uint32_t update_revision;
44 uint32_t date;
45 uint32_t processor_sig;
46 uint32_t checksum;
47 uint32_t loader_rev;
48 uint32_t processor_flags;
49 uint32_t data_size;
50 uint32_t total_size;
51 uint32_t reserved[3];
52};
53
54struct intel_ucode_ext_sig_header {
55 uint32_t ext_sig_count;
56 uint32_t checksum;
57 uint32_t reserved[3];
58};
59
60struct intel_ucode_ext_sig {
61 uint32_t processor_sig;
62 uint32_t processor_flags;
63 uint32_t checksum;
64};
65
66#define INTEL_UCODE_DEFAULT_DATA_SIZE2000 2000
67
68/* Generic */
69char * cpu_ucode_data;
70size_t cpu_ucode_size;
71
72void cpu_ucode_setup(void);
73void cpu_ucode_apply(struct cpu_info *);
74
75struct mutex cpu_ucode_mtx = MUTEX_INITIALIZER(IPL_HIGH){ ((void *)0), ((((0xd)) > 0x0 && ((0xd)) < 0x9
) ? 0x9 : ((0xd))), 0x0 }
;
76
77/* Intel */
78void cpu_ucode_intel_apply(struct cpu_info *);
79struct intel_ucode_header *
80 cpu_ucode_intel_find(char *, size_t, uint32_t);
81int cpu_ucode_intel_verify(struct intel_ucode_header *);
82int cpu_ucode_intel_match(struct intel_ucode_header *, uint32_t, uint32_t,
83 uint32_t);
84uint32_t cpu_ucode_intel_rev(void);
85
86struct intel_ucode_header *cpu_ucode_intel_applied;
87
88void cpu_ucode_amd_apply(struct cpu_info *);
89
90void
91cpu_ucode_setup(void)
92{
93 if (bios_ucode == NULL((void *)0))
94 return;
95
96 if (!bios_ucode->uc_addr || !bios_ucode->uc_size)
97 return;
98
99 cpu_ucode_size = bios_ucode->uc_size;
100 cpu_ucode_data = malloc(cpu_ucode_size, M_DEVBUF2, M_WAITOK0x0001);
101 memcpy(cpu_ucode_data, (void *)PMAP_DIRECT_MAP(bios_ucode->uc_addr),__builtin_memcpy((cpu_ucode_data), ((void *)((vaddr_t)(((((511
- 4) * (1ULL << 39))) | 0xffff000000000000)) + (bios_ucode
->uc_addr))), (cpu_ucode_size))
102 cpu_ucode_size)__builtin_memcpy((cpu_ucode_data), ((void *)((vaddr_t)(((((511
- 4) * (1ULL << 39))) | 0xffff000000000000)) + (bios_ucode
->uc_addr))), (cpu_ucode_size))
;
103}
104
105/*
106 * Called per-CPU.
107 */
108void
109cpu_ucode_apply(struct cpu_info *ci)
110{
111 if (strcmp(cpu_vendor, "GenuineIntel") == 0)
112 cpu_ucode_intel_apply(ci);
113 else if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
114 cpu_ucode_amd_apply(ci);
115}
116
117#define AMD_MAGIC0x00414d44 0x00414d44
118
119struct amd_equiv {
120 uint32_t id;
121 uint32_t a;
122 uint32_t b;
123 uint16_t eid;
124 uint16_t c;
125} __packed__attribute__((__packed__));
126
127struct amd_patch {
128 uint32_t type;
129 uint32_t len;
130 uint32_t a;
131 uint32_t level;
132 uint8_t c[16];
133 uint16_t eid;
134} __packed__attribute__((__packed__));
135
136void
137cpu_ucode_amd_apply(struct cpu_info *ci)
138{
139 uint64_t level;
140 uint32_t magic, tlen, i;
141 uint16_t eid = 0;
142 uint32_t sig, ebx, ecx, edx;
143 uint64_t start = 0;
144 uint32_t patch_len = 0;
145
146 if (cpu_ucode_data == NULL((void *)0) || cpu_ucode_size == 0) {
147 DPRINTF(("%s: no microcode provided\n", __func__))do { ; } while (0);
148 return;
149 }
150
151 /*
152 * Grab a mutex, because we are not allowed to run updates
153 * simultaneously on HT siblings.
154 */
155 mtx_enter(&cpu_ucode_mtx);
156
157 CPUID(1, sig, ebx, ecx, edx)__asm volatile("cpuid" : "=a" (sig), "=b" (ebx), "=c" (ecx), "=d"
(edx) : "a" (1))
;
158
159 level = rdmsr(MSR_PATCH_LEVEL0x0000008b);
160 DPRINTF(("%s: cur patch level 0x%llx\n", __func__, level))do { ; } while (0);
161
162 memcpy(&magic, cpu_ucode_data, 4)__builtin_memcpy((&magic), (cpu_ucode_data), (4));
163 if (magic != AMD_MAGIC0x00414d44) {
164 DPRINTF(("%s: bad magic %x\n", __func__, magic))do { ; } while (0);
165 goto out;
166 }
167
168 memcpy(&tlen, &cpu_ucode_data[8], 4)__builtin_memcpy((&tlen), (&cpu_ucode_data[8]), (4));
169
170 /* find equivalence id matching our cpu signature */
171 for (i = 12; i < 12 + tlen;) {
172 struct amd_equiv ae;
173 if (i + sizeof(ae) > cpu_ucode_size) {
174 DPRINTF(("%s: truncated etable\n", __func__))do { ; } while (0);
175 goto out;
176 }
177 memcpy(&ae, &cpu_ucode_data[i], sizeof(ae))__builtin_memcpy((&ae), (&cpu_ucode_data[i]), (sizeof
(ae)))
;
178 i += sizeof(ae);
179 if (ae.id == sig)
180 eid = ae.eid;
181 }
182
183 /* look for newer patch with the equivalence id */
184 while (i < cpu_ucode_size) {
185 struct amd_patch ap;
186 if (i + sizeof(ap) > cpu_ucode_size) {
187 DPRINTF(("%s: truncated ptable\n", __func__))do { ; } while (0);
188 goto out;
189 }
190 memcpy(&ap, &cpu_ucode_data[i], sizeof(ap))__builtin_memcpy((&ap), (&cpu_ucode_data[i]), (sizeof
(ap)))
;
191 if (ap.type == 1 && ap.eid == eid && ap.level > level) {
192 start = (uint64_t)&cpu_ucode_data[i + 8];
193 patch_len = ap.len;
194 }
195 if (i + ap.len + 8 > cpu_ucode_size) {
196 DPRINTF(("%s: truncated patch\n", __func__))do { ; } while (0);
197 goto out;
198 }
199 i += ap.len + 8;
200 }
201
202 if (start != 0) {
203 /* alignment required on fam 15h */
204 uint8_t *p = malloc(patch_len, M_TEMP127, M_NOWAIT0x0002);
205 if (p == NULL((void *)0))
206 goto out;
207 memcpy(p, (uint8_t *)start, patch_len)__builtin_memcpy((p), ((uint8_t *)start), (patch_len));
208 start = (uint64_t)p;
209 wrmsr(MSR_PATCH_LOADER0xc0010020, start);
210 level = rdmsr(MSR_PATCH_LEVEL0x0000008b);
Value stored to 'level' is never read
211 DPRINTF(("%s: new patch level 0x%llx\n", __func__, level))do { ; } while (0);
212 free(p, M_TEMP127, patch_len);
213 }
214out:
215 mtx_leave(&cpu_ucode_mtx);
216}
217
218void
219cpu_ucode_intel_apply(struct cpu_info *ci)
220{
221 struct intel_ucode_header *update;
222 uint32_t old_rev, new_rev;
223 paddr_t data;
224
225 if (cpu_ucode_data == NULL((void *)0) || cpu_ucode_size == 0) {
226 DPRINTF(("%s: no microcode provided\n", __func__))do { ; } while (0);
227 return;
228 }
229
230 /*
231 * Grab a mutex, because we are not allowed to run updates
232 * simultaneously on HT siblings.
233 */
234 mtx_enter(&cpu_ucode_mtx);
235
236 old_rev = cpu_ucode_intel_rev();
237 update = cpu_ucode_intel_applied;
238 if (update == NULL((void *)0))
239 update = cpu_ucode_intel_find(cpu_ucode_data,
240 cpu_ucode_size, old_rev);
241 if (update == NULL((void *)0)) {
242 DPRINTF(("%s: no microcode update found\n", __func__))do { ; } while (0);
243 goto out;
244 }
245 if (update->update_revision == old_rev) {
246 DPRINTF(("%s: microcode already up-to-date\n", __func__))do { ; } while (0);
247 goto out;
248 }
249
250 /* Apply microcode. */
251 data = (paddr_t)update;
252 data += sizeof(struct intel_ucode_header);
253 wbinvd();
254 wrmsr(MSR_BIOS_UPDT_TRIG0x079, data);
255
256 new_rev = cpu_ucode_intel_rev();
257 if (new_rev != old_rev) {
258 DPRINTF(("%s: microcode updated cpu %d rev %#x->%#x (%x)\n",do { ; } while (0)
259 __func__, ci->ci_cpuid, old_rev, new_rev, update->date))do { ; } while (0);
260 if (cpu_ucode_intel_applied == NULL((void *)0))
261 cpu_ucode_intel_applied = update;
262 } else {
263 DPRINTF(("%s: microcode update failed cpu %d rev %#x->%#x != %#x\n",do { ; } while (0)
264 __func__, ci->ci_cpuid, old_rev, update->update_revision, new_rev))do { ; } while (0);
265 }
266
267out:
268 mtx_leave(&cpu_ucode_mtx);
269}
270
271struct intel_ucode_header *
272cpu_ucode_intel_find(char *data, size_t left, uint32_t current)
273{
274 uint64_t platform_id = (rdmsr(MSR_PLATFORM_ID0x017) >> 50) & 7;
275 uint32_t sig, dummy1, dummy2, dummy3;
276 uint32_t mask = 1UL << platform_id;
277 struct intel_ucode_header *hdr;
278 uint32_t total_size;
279 int n = 0;
280
281 CPUID(1, sig, dummy1, dummy2, dummy3)__asm volatile("cpuid" : "=a" (sig), "=b" (dummy1), "=c" (dummy2
), "=d" (dummy3) : "a" (1))
;
282
283 while (left > 0) {
284 hdr = (struct intel_ucode_header *)data;
285 if (left < sizeof(struct intel_ucode_header)) {
286 DPRINTF(("%s:%d: not enough data for header (%zd)\n",do { ; } while (0)
287 __func__, n, left))do { ; } while (0);
288 break;
289 }
290 /*
291 * Older microcode has an empty length. In that case we
292 * have to use the default length of 2000.
293 */
294 if (hdr->data_size)
295 total_size = hdr->total_size;
296 else
297 total_size = INTEL_UCODE_DEFAULT_DATA_SIZE2000 +
298 sizeof(struct intel_ucode_header);
299 if (total_size > left) {
300 DPRINTF(("%s:%d: size %u out of range (%zd)\n",do { ; } while (0)
301 __func__, n, total_size, left))do { ; } while (0);
302 break;
303 }
304 if (cpu_ucode_intel_verify(hdr)) {
305 DPRINTF(("%s:%d: broken data\n", __func__, n))do { ; } while (0);
306 break;
307 }
308 if (cpu_ucode_intel_match(hdr, sig, mask, current))
309 return hdr;
310 n++;
311 left -= total_size;
312 data += total_size;
313 }
314 DPRINTF(("%s: no update found\n", __func__))do { ; } while (0);
315 return NULL((void *)0);
316}
317
318int
319cpu_ucode_intel_verify(struct intel_ucode_header *hdr)
320{
321 uint32_t *data = (uint32_t *)hdr;
322 size_t total_size;
323 uint32_t sum;
324 int i;
325
326 CTASSERT(sizeof(struct intel_ucode_header) == 48)extern char _ctassert[(sizeof(struct intel_ucode_header) == 48
) ? 1 : -1 ] __attribute__((__unused__))
;
327
328 if ((paddr_t)data % 16 != 0) {
329 DPRINTF(("%s: misaligned microcode update\n", __func__))do { ; } while (0);
330 return 1;
331 }
332 if (hdr->loader_rev != 1) {
333 DPRINTF(("%s: unsupported loader rev\n", __func__))do { ; } while (0);
334 return 1;
335 }
336
337 if (hdr->data_size)
338 total_size = hdr->total_size;
339 else
340 total_size = INTEL_UCODE_DEFAULT_DATA_SIZE2000 +
341 sizeof(struct intel_ucode_header);
342 if (total_size % 4 != 0) {
343 DPRINTF(("%s: inconsistent size\n", __func__))do { ; } while (0);
344 return 1;
345 }
346
347 sum = 0;
348 for (i = 0; i < total_size / 4; i++)
349 sum += data[i];
350 if (sum != 0) {
351 DPRINTF(("%s: wrong checksum (%#x)\n", __func__, sum))do { ; } while (0);
352 return 1;
353 }
354
355 return 0;
356}
357
358int
359cpu_ucode_intel_match(struct intel_ucode_header *hdr,
360 uint32_t processor_sig, uint32_t processor_mask,
361 uint32_t ucode_revision)
362{
363 struct intel_ucode_ext_sig_header *ehdr;
364 struct intel_ucode_ext_sig *esig;
365 uint32_t data_size, total_size;
366 unsigned i;
367
368 data_size = hdr->data_size;
369 total_size = hdr->total_size;
370
371 /*
372 * Older microcode has an empty length. In that case we
373 * have to use the default length of 2000.
374 */
375 if (!data_size) {
376 data_size = INTEL_UCODE_DEFAULT_DATA_SIZE2000;
377 total_size = INTEL_UCODE_DEFAULT_DATA_SIZE2000 +
378 sizeof(struct intel_ucode_header);
379 }
380
381 if (ucode_revision > hdr->update_revision)
382 return 0;
383 if (hdr->processor_sig == processor_sig &&
384 (hdr->processor_flags & processor_mask))
385 return 1;
386 if (total_size <= sizeof(struct intel_ucode_header) +
387 data_size + sizeof(struct intel_ucode_ext_sig_header))
388 return 0;
389
390 ehdr = (void *)((char *)hdr + sizeof(struct intel_ucode_header) +
391 data_size);
392 esig = (void *)&ehdr[1];
393 for (i = 0; i < ehdr->ext_sig_count; i++) {
394 if (esig[i].processor_sig == processor_sig &&
395 (esig[i].processor_flags & processor_mask))
396 return 1;
397 }
398
399 return 0;
400}
401
402uint32_t
403cpu_ucode_intel_rev(void)
404{
405 uint32_t eax, ebx, ecx, edx;
406 uint64_t rev;
407
408 wrmsr(MSR_BIOS_SIGN0x08b, 0);
409 CPUID(1, eax, ebx, ecx, edx)__asm volatile("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d"
(edx) : "a" (1))
;
410 rev = rdmsr(MSR_BIOS_SIGN0x08b);
411 return rev >> 32;
412}