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 47 update->header_version = fdtdec_get_int(blob, node, 48 "intel,header-version", 0); 49 update->update_revision = fdtdec_get_int(blob, node, 50 "intel,update-revision", 0); 51 update->date_code = fdtdec_get_int(blob, node, 52 "intel,date-code", 0); 53 update->processor_signature = fdtdec_get_int(blob, node, 54 "intel,processor-signature", 0); 55 update->checksum = fdtdec_get_int(blob, node, "intel,checksum", 0); 56 update->loader_revision = fdtdec_get_int(blob, node, 57 "intel,loader-revision", 0); 58 update->processor_flags = fdtdec_get_int(blob, node, 59 "intel,processor-flags", 0); 60 61 return 0; 62 } 63 64 int microcode_read_rev(void) 65 { 66 /* Quark does not have microcode MSRs */ 67 #ifdef CONFIG_INTEL_QUARK 68 return 0; 69 #else 70 /* 71 * Some Intel CPUs can be very finicky about the CPUID sequence used. 72 * So this is implemented in assembly so that it works reliably. 73 */ 74 uint32_t low, high; 75 76 asm volatile ( 77 "xorl %%eax, %%eax\n" 78 "xorl %%edx, %%edx\n" 79 "movl %2, %%ecx\n" 80 "wrmsr\n" 81 "movl $0x01, %%eax\n" 82 "cpuid\n" 83 "movl %2, %%ecx\n" 84 "rdmsr\n" 85 : /* outputs */ 86 "=a" (low), "=d" (high) 87 : /* inputs */ 88 "i" (MSR_IA32_UCODE_REV) 89 : /* clobbers */ 90 "ebx", "ecx" 91 ); 92 93 return high; 94 #endif 95 } 96 97 static void microcode_read_cpu(struct microcode_update *cpu) 98 { 99 /* CPUID sets MSR 0x8B iff a microcode update has been loaded. */ 100 unsigned int x86_model, x86_family; 101 struct cpuid_result result; 102 uint32_t low, high; 103 104 wrmsr(MSR_IA32_UCODE_REV, 0, 0); 105 result = cpuid(1); 106 rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision); 107 x86_model = (result.eax >> 4) & 0x0f; 108 x86_family = (result.eax >> 8) & 0x0f; 109 cpu->processor_signature = result.eax; 110 111 cpu->processor_flags = 0; 112 if ((x86_model >= 5) || (x86_family > 6)) { 113 rdmsr(0x17, low, high); 114 cpu->processor_flags = 1 << ((high >> 18) & 7); 115 } 116 debug("microcode: sig=%#x pf=%#x revision=%#x\n", 117 cpu->processor_signature, cpu->processor_flags, 118 cpu->update_revision); 119 } 120 121 /* Get a microcode update from the device tree and apply it */ 122 int microcode_update_intel(void) 123 { 124 struct microcode_update cpu, update; 125 ulong address; 126 const void *blob = gd->fdt_blob; 127 int skipped; 128 int count; 129 int node; 130 int ret; 131 int rev; 132 133 microcode_read_cpu(&cpu); 134 node = 0; 135 count = 0; 136 skipped = 0; 137 do { 138 node = fdtdec_next_compatible(blob, node, 139 COMPAT_INTEL_MICROCODE); 140 if (node < 0) { 141 debug("%s: Found %d updates\n", __func__, count); 142 return count ? 0 : skipped ? -EEXIST : -ENOENT; 143 } 144 145 ret = microcode_decode_node(blob, node, &update); 146 if (ret == -ENOENT && ucode_base) { 147 /* 148 * The microcode has been removed from the device tree 149 * in the build system. In that case it will have 150 * already been updated in car_init(). 151 */ 152 debug("%s: Microcode data not available\n", __func__); 153 skipped++; 154 continue; 155 } 156 if (ret) { 157 debug("%s: Unable to decode update: %d\n", __func__, 158 ret); 159 return ret; 160 } 161 if (!(update.processor_signature == cpu.processor_signature && 162 (update.processor_flags & cpu.processor_flags))) { 163 debug("%s: Skipping non-matching update, sig=%x, pf=%x\n", 164 __func__, update.processor_signature, 165 update.processor_flags); 166 skipped++; 167 continue; 168 } 169 address = (ulong)update.data + UCODE_HEADER_LEN; 170 wrmsr(MSR_IA32_UCODE_WRITE, address, 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 if (!ucode_base) { 182 ucode_base = (ulong)update.data; 183 ucode_size = update.size; 184 } 185 } while (1); 186 } 187