1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _SYS_UCODE_H 27 #define _SYS_UCODE_H 28 29 #ifdef _KERNEL 30 #include <sys/cpuvar.h> 31 #endif 32 #include <sys/types.h> 33 #include <sys/priv.h> 34 #include <sys/processor.h> 35 #ifndef _KERNEL 36 #include <limits.h> 37 #endif 38 #include <ucode/ucode_errno.h> 39 40 #ifdef __cplusplus 41 extern "C" { 42 #endif 43 44 /* 45 * /dev/ucode 46 */ 47 #define UCODE_DRIVER_NAME "ucode" 48 #define UCODE_NODE_NAME "ucode" 49 #define UCODE_MINOR ((minor_t)0x3fffful) 50 51 /* 52 * Where to install the microcode 53 */ 54 #define UCODE_INSTALL_PATH "platform/i86pc/ucode" 55 #define UCODE_INSTALL_COMMON_PATH ".f" 56 57 /* 58 * ioctl numbers 59 */ 60 #define UCODE_IOC (('u'<<24)|('c'<<16)|('o'<<8)) 61 62 #define UCODE_GET_VERSION (UCODE_IOC|0) 63 #define UCODE_UPDATE (UCODE_IOC|1) 64 65 struct ucode_get_rev_struct { 66 uint32_t *ugv_rev; /* microcode revision array */ 67 int ugv_size; /* size of the array */ 68 ucode_errno_t ugv_errno; /* EUC error code */ 69 }; 70 71 struct ucode_write_struct { 72 uint32_t uw_size; /* size of the uw_code buffer */ 73 uint8_t *uw_ucode; /* pointer to the undigested microcode */ 74 ucode_errno_t uw_errno; /* EUC error code */ 75 }; 76 77 #if defined(_SYSCALL32_IMPL) 78 79 #include <sys/types32.h> 80 81 struct ucode_get_rev_struct32 { 82 caddr32_t ugv_rev; /* microcode revision array */ 83 int ugv_size; /* size of the array */ 84 ucode_errno_t ugv_errno; /* EUC error code */ 85 }; 86 87 struct ucode_write_struct32 { 88 uint32_t uw_size; /* size of the uw_code buffer */ 89 caddr32_t uw_ucode; /* pointer to the undigested microcode */ 90 ucode_errno_t uw_errno; /* EUC error code */ 91 }; 92 93 #endif /* _SYSCALL32_IMPL */ 94 95 /* 96 * AMD Microcode file information 97 */ 98 typedef struct ucode_header_amd { 99 uint32_t uh_date; 100 uint32_t uh_patch_id; 101 uint32_t uh_internal; /* patch data id & length, init flag */ 102 uint32_t uh_cksum; 103 uint32_t uh_nb_id; 104 uint32_t uh_sb_id; 105 uint16_t uh_cpu_rev; 106 uint8_t uh_nb_rev; 107 uint8_t uh_sb_rev; 108 uint32_t uh_bios_rev; 109 uint32_t uh_match[8]; 110 } ucode_header_amd_t; 111 112 typedef struct ucode_file_amd { 113 #ifndef __xpv 114 ucode_header_amd_t uf_header; 115 uint8_t uf_data[896]; 116 uint8_t uf_resv[896]; 117 uint8_t uf_code_present; 118 uint8_t uf_code[191]; 119 uint8_t uf_encr[2048]; 120 #else 121 uint8_t *ucodep; 122 uint32_t usize; 123 #endif 124 } ucode_file_amd_t; 125 126 typedef struct ucode_eqtbl_amd { 127 uint32_t ue_inst_cpu; 128 uint32_t ue_fixed_mask; 129 uint32_t ue_fixed_comp; 130 uint16_t ue_equiv_cpu; 131 uint16_t ue_reserved; 132 } ucode_eqtbl_amd_t; 133 134 /* 135 * Intel Microcode file information 136 */ 137 typedef struct ucode_header_intel { 138 uint32_t uh_header_ver; 139 uint32_t uh_rev; 140 uint32_t uh_date; 141 uint32_t uh_signature; 142 uint32_t uh_checksum; 143 uint32_t uh_loader_ver; 144 uint32_t uh_proc_flags; 145 uint32_t uh_body_size; 146 uint32_t uh_total_size; 147 uint32_t uh_reserved[3]; 148 } ucode_header_intel_t; 149 150 typedef struct ucode_ext_sig_intel { 151 uint32_t ues_signature; 152 uint32_t ues_proc_flags; 153 uint32_t ues_checksum; 154 } ucode_ext_sig_intel_t; 155 156 typedef struct ucode_ext_table_intel { 157 uint32_t uet_count; 158 uint32_t uet_checksum; 159 uint32_t uet_reserved[3]; 160 ucode_ext_sig_intel_t uet_ext_sig[1]; 161 } ucode_ext_table_intel_t; 162 163 typedef struct ucode_file_intel { 164 ucode_header_intel_t *uf_header; 165 uint8_t *uf_body; 166 ucode_ext_table_intel_t *uf_ext_table; 167 } ucode_file_intel_t; 168 169 /* 170 * common container 171 */ 172 typedef union ucode_file { 173 ucode_file_amd_t *amd; 174 ucode_file_intel_t intel; 175 } ucode_file_t; 176 177 178 #define UCODE_SHORT_NAME_LEN 12 /* "32-bit-sig"-"8-bit-platid"\0 */ 179 /* 180 * Length of UCODE_INSTALL_COMMON_PATH/short-name 181 * strlen(UCODE_INSTALL_COMMON_PATH) + 1 + UCODE_SHORT_NAME_LEN 182 * Use sizeof which will give us the additional byte for the '/' in between 183 * the common path and the file name. 184 */ 185 #define UCODE_COMMON_NAME_LEN \ 186 (sizeof (UCODE_INSTALL_COMMON_PATH) + (UCODE_SHORT_NAME_LEN)) 187 #define UCODE_MAX_PATH_LEN (PATH_MAX - UCODE_COMMON_NAME_LEN) 188 189 190 #define UCODE_HEADER_SIZE_INTEL (sizeof (struct ucode_header_intel)) 191 #define UCODE_EXT_TABLE_SIZE_INTEL (20) /* 20-bytes */ 192 #define UCODE_EXT_SIG_SIZE_INTEL (sizeof (struct ucode_ext_sig_intel)) 193 194 #define UCODE_KB(a) ((a) << 10) /* KB */ 195 #define UCODE_MB(a) ((a) << 20) /* MB */ 196 #define UCODE_DEFAULT_TOTAL_SIZE UCODE_KB(2) 197 #define UCODE_DEFAULT_BODY_SIZE (UCODE_KB(2) - UCODE_HEADER_SIZE_INTEL) 198 199 /* 200 * For a single microcode file, the minimum size is 1K, maximum size is 16K. 201 * Such limitations, while somewhat artificial, are not only to provide better 202 * sanity checks, but also avoid wasting precious memory at startup time as the 203 * microcode buffer for the first processor has to be statically allocated. 204 * 205 * For the concatenation of all the microcode binary files, the maximum size 206 * is 16M. 207 */ 208 #define UCODE_MIN_SIZE UCODE_KB(1) 209 #define UCODE_MAX_SIZE UCODE_KB(16) 210 #define UCODE_MAX_COMBINED_SIZE UCODE_MB(16) 211 212 #define UCODE_SIZE_CONVERT(size, default_size) \ 213 ((size) == 0 ? (default_size) : (size)) 214 215 #define UCODE_BODY_SIZE_INTEL(size) \ 216 UCODE_SIZE_CONVERT((size), UCODE_DEFAULT_BODY_SIZE) 217 218 #define UCODE_TOTAL_SIZE_INTEL(size) \ 219 UCODE_SIZE_CONVERT((size), UCODE_DEFAULT_TOTAL_SIZE) 220 221 #define UCODE_MATCH_INTEL(sig1, sig2, pf1, pf2) \ 222 (((sig1) == (sig2)) && \ 223 (((pf1) & (pf2)) || (((pf1) == 0) && ((pf2) == 0)))) 224 225 extern ucode_errno_t ucode_header_validate_intel(ucode_header_intel_t *); 226 extern uint32_t ucode_checksum_intel(uint32_t, uint32_t, uint8_t *); 227 228 extern ucode_errno_t ucode_validate_amd(uint8_t *, int); 229 extern ucode_errno_t ucode_validate_intel(uint8_t *, int); 230 231 #ifdef _KERNEL 232 extern ucode_errno_t ucode_get_rev(uint32_t *); 233 extern ucode_errno_t ucode_update(uint8_t *, int); 234 235 /* 236 * Microcode specific information per core 237 */ 238 typedef struct cpu_ucode_info { 239 uint32_t cui_platid; /* platform id */ 240 uint32_t cui_rev; /* microcode revision */ 241 } cpu_ucode_info_t; 242 243 /* 244 * Data structure used for xcall 245 */ 246 typedef struct ucode_update { 247 uint32_t sig; /* signature */ 248 cpu_ucode_info_t info; /* ucode info */ 249 uint32_t expected_rev; 250 uint32_t new_rev; 251 uint8_t *ucodep; /* pointer to ucode */ 252 uint32_t usize; 253 } ucode_update_t; 254 255 /* 256 * Microcode kernel operations 257 */ 258 struct ucode_ops { 259 uint32_t write_msr; 260 int (*capable)(cpu_t *); 261 void (*file_reset)(ucode_file_t *, processorid_t); 262 void (*read_rev)(cpu_ucode_info_t *); 263 uint32_t (*load)(ucode_file_t *, cpu_ucode_info_t *, cpu_t *); 264 ucode_errno_t (*validate)(uint8_t *, int); 265 ucode_errno_t (*extract)(ucode_update_t *, uint8_t *, int); 266 ucode_errno_t (*locate)(cpu_t *, cpu_ucode_info_t *, ucode_file_t *); 267 }; 268 #else 269 270 #define UCODE_MAX_VENDORS_NAME_LEN 20 271 272 #define UCODE_VENDORS \ 273 static struct { \ 274 char *filestr; \ 275 char *extstr; \ 276 char *vendorstr; \ 277 int supported; \ 278 } ucode_vendors[] = { \ 279 { "intel", "txt", "GenuineIntel", 1 }, \ 280 { "amd", "bin", "AuthenticAMD", 1 }, \ 281 { NULL, NULL, NULL, 0 } \ 282 } 283 284 /* 285 * Microcode user operations 286 */ 287 struct ucode_ops { 288 int (*convert)(const char *, uint8_t *, size_t); 289 ucode_errno_t (*gen_files)(uint8_t *, int, char *); 290 ucode_errno_t (*validate)(uint8_t *, int); 291 }; 292 #endif 293 294 extern const struct ucode_ops *ucode; 295 296 #ifdef __cplusplus 297 } 298 #endif 299 300 #endif /* _SYS_UCODE_H */ 301