1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2014 Google, Inc 4 * Copyright (C) 2000 Ronald G. Minnich 5 * 6 * Microcode update for Intel PIII and later CPUs 7 */ 8 9 #include <common.h> 10 #include <errno.h> 11 #include <fdtdec.h> 12 #include <linux/libfdt.h> 13 #include <asm/cpu.h> 14 #include <asm/microcode.h> 15 #include <asm/msr.h> 16 #include <asm/msr-index.h> 17 #include <asm/processor.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 /** 22 * struct microcode_update - standard microcode header from Intel 23 * 24 * We read this information out of the device tree and use it to determine 25 * whether the update is applicable or not. We also use the same structure 26 * to read information from the CPU. 27 */ 28 struct microcode_update { 29 uint header_version; 30 uint update_revision; 31 uint date_code; 32 uint processor_signature; 33 uint checksum; 34 uint loader_revision; 35 uint processor_flags; 36 const void *data; 37 int size; 38 }; 39 40 static int microcode_decode_node(const void *blob, int node, 41 struct microcode_update *update) 42 { 43 update->data = fdt_getprop(blob, node, "data", &update->size); 44 if (!update->data) 45 return -ENOENT; 46 update->data += UCODE_HEADER_LEN; 47 update->size -= UCODE_HEADER_LEN; 48 49 update->header_version = fdtdec_get_int(blob, node, 50 "intel,header-version", 0); 51 update->update_revision = fdtdec_get_int(blob, node, 52 "intel,update-revision", 0); 53 update->date_code = fdtdec_get_int(blob, node, 54 "intel,date-code", 0); 55 update->processor_signature = fdtdec_get_int(blob, node, 56 "intel,processor-signature", 0); 57 update->checksum = fdtdec_get_int(blob, node, "intel,checksum", 0); 58 update->loader_revision = fdtdec_get_int(blob, node, 59 "intel,loader-revision", 0); 60 update->processor_flags = fdtdec_get_int(blob, node, 61 "intel,processor-flags", 0); 62 63 return 0; 64 } 65 66 int microcode_read_rev(void) 67 { 68 /* Quark does not have microcode MSRs */ 69 #ifdef CONFIG_INTEL_QUARK 70 return 0; 71 #else 72 /* 73 * Some Intel CPUs can be very finicky about the CPUID sequence used. 74 * So this is implemented in assembly so that it works reliably. 75 */ 76 uint32_t low, high; 77 78 asm volatile ( 79 "xorl %%eax, %%eax\n" 80 "xorl %%edx, %%edx\n" 81 "movl %2, %%ecx\n" 82 "wrmsr\n" 83 "movl $0x01, %%eax\n" 84 "cpuid\n" 85 "movl %2, %%ecx\n" 86 "rdmsr\n" 87 : /* outputs */ 88 "=a" (low), "=d" (high) 89 : /* inputs */ 90 "i" (MSR_IA32_UCODE_REV) 91 : /* clobbers */ 92 "ebx", "ecx" 93 ); 94 95 return high; 96 #endif 97 } 98 99 static void microcode_read_cpu(struct microcode_update *cpu) 100 { 101 /* CPUID sets MSR 0x8B iff a microcode update has been loaded. */ 102 unsigned int x86_model, x86_family; 103 struct cpuid_result result; 104 uint32_t low, high; 105 106 wrmsr(MSR_IA32_UCODE_REV, 0, 0); 107 result = cpuid(1); 108 rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision); 109 x86_model = (result.eax >> 4) & 0x0f; 110 x86_family = (result.eax >> 8) & 0x0f; 111 cpu->processor_signature = result.eax; 112 113 cpu->processor_flags = 0; 114 if ((x86_model >= 5) || (x86_family > 6)) { 115 rdmsr(0x17, low, high); 116 cpu->processor_flags = 1 << ((high >> 18) & 7); 117 } 118 debug("microcode: sig=%#x pf=%#x revision=%#x\n", 119 cpu->processor_signature, cpu->processor_flags, 120 cpu->update_revision); 121 } 122 123 /* Get a microcode update from the device tree and apply it */ 124 int microcode_update_intel(void) 125 { 126 struct microcode_update cpu, update; 127 const void *blob = gd->fdt_blob; 128 int skipped; 129 int count; 130 int node; 131 int ret; 132 int rev; 133 134 microcode_read_cpu(&cpu); 135 node = 0; 136 count = 0; 137 skipped = 0; 138 do { 139 node = fdtdec_next_compatible(blob, node, 140 COMPAT_INTEL_MICROCODE); 141 if (node < 0) { 142 debug("%s: Found %d updates\n", __func__, count); 143 return count ? 0 : skipped ? -EEXIST : -ENOENT; 144 } 145 146 ret = microcode_decode_node(blob, node, &update); 147 if (ret == -ENOENT && ucode_base) { 148 /* 149 * The microcode has been removed from the device tree 150 * in the build system. In that case it will have 151 * already been updated in car_init(). 152 */ 153 debug("%s: Microcode data not available\n", __func__); 154 skipped++; 155 continue; 156 } 157 if (ret) { 158 debug("%s: Unable to decode update: %d\n", __func__, 159 ret); 160 return ret; 161 } 162 if (!(update.processor_signature == cpu.processor_signature && 163 (update.processor_flags & cpu.processor_flags))) { 164 debug("%s: Skipping non-matching update, sig=%x, pf=%x\n", 165 __func__, update.processor_signature, 166 update.processor_flags); 167 skipped++; 168 continue; 169 } 170 wrmsr(MSR_IA32_UCODE_WRITE, (ulong)update.data, 0); 171 rev = microcode_read_rev(); 172 debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n", 173 rev, update.date_code & 0xffff, 174 (update.date_code >> 24) & 0xff, 175 (update.date_code >> 16) & 0xff); 176 if (update.update_revision != rev) { 177 printf("Microcode update failed\n"); 178 return -EFAULT; 179 } 180 count++; 181 } while (1); 182 } 183