12449e17fSsherrym /* 22449e17fSsherrym * CDDL HEADER START 32449e17fSsherrym * 42449e17fSsherrym * The contents of this file are subject to the terms of the 52449e17fSsherrym * Common Development and Distribution License (the "License"). 62449e17fSsherrym * You may not use this file except in compliance with the License. 72449e17fSsherrym * 82449e17fSsherrym * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92449e17fSsherrym * or http://www.opensolaris.org/os/licensing. 102449e17fSsherrym * See the License for the specific language governing permissions 112449e17fSsherrym * and limitations under the License. 122449e17fSsherrym * 132449e17fSsherrym * When distributing Covered Code, include this CDDL HEADER in each 142449e17fSsherrym * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152449e17fSsherrym * If applicable, add the following below this CDDL HEADER, with the 162449e17fSsherrym * fields enclosed by brackets "[]" replaced with your own identifying 172449e17fSsherrym * information: Portions Copyright [yyyy] [name of copyright owner] 182449e17fSsherrym * 192449e17fSsherrym * CDDL HEADER END 202449e17fSsherrym */ 212449e17fSsherrym /* 220ba6f73dSMark Johnson * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 232449e17fSsherrym * Use is subject to license terms. 242449e17fSsherrym */ 252449e17fSsherrym 262449e17fSsherrym #ifndef _SYS_UCODE_H 272449e17fSsherrym #define _SYS_UCODE_H 282449e17fSsherrym 29adc586deSMark Johnson #ifdef _KERNEL 30adc586deSMark Johnson #include <sys/cpuvar.h> 31adc586deSMark Johnson #endif 322449e17fSsherrym #include <sys/types.h> 332449e17fSsherrym #include <sys/priv.h> 342449e17fSsherrym #include <sys/processor.h> 352449e17fSsherrym #ifndef _KERNEL 362449e17fSsherrym #include <limits.h> 372449e17fSsherrym #endif 382449e17fSsherrym #include <ucode/ucode_errno.h> 392449e17fSsherrym 402449e17fSsherrym #ifdef __cplusplus 412449e17fSsherrym extern "C" { 422449e17fSsherrym #endif 432449e17fSsherrym 442449e17fSsherrym /* 452449e17fSsherrym * /dev/ucode 462449e17fSsherrym */ 472449e17fSsherrym #define UCODE_DRIVER_NAME "ucode" 482449e17fSsherrym #define UCODE_NODE_NAME "ucode" 492449e17fSsherrym #define UCODE_MINOR ((minor_t)0x3fffful) 502449e17fSsherrym 512449e17fSsherrym /* 522449e17fSsherrym * Where to install the microcode 532449e17fSsherrym */ 542449e17fSsherrym #define UCODE_INSTALL_PATH "platform/i86pc/ucode" 552449e17fSsherrym #define UCODE_INSTALL_COMMON_PATH ".f" 562449e17fSsherrym 572449e17fSsherrym /* 582449e17fSsherrym * ioctl numbers 592449e17fSsherrym */ 602449e17fSsherrym #define UCODE_IOC (('u'<<24)|('c'<<16)|('o'<<8)) 612449e17fSsherrym 622449e17fSsherrym #define UCODE_GET_VERSION (UCODE_IOC|0) 632449e17fSsherrym #define UCODE_UPDATE (UCODE_IOC|1) 642449e17fSsherrym 652449e17fSsherrym struct ucode_get_rev_struct { 662449e17fSsherrym uint32_t *ugv_rev; /* microcode revision array */ 672449e17fSsherrym int ugv_size; /* size of the array */ 682449e17fSsherrym ucode_errno_t ugv_errno; /* EUC error code */ 692449e17fSsherrym }; 702449e17fSsherrym 712449e17fSsherrym struct ucode_write_struct { 722449e17fSsherrym uint32_t uw_size; /* size of the uw_code buffer */ 732449e17fSsherrym uint8_t *uw_ucode; /* pointer to the undigested microcode */ 742449e17fSsherrym ucode_errno_t uw_errno; /* EUC error code */ 752449e17fSsherrym }; 762449e17fSsherrym 772449e17fSsherrym #if defined(_SYSCALL32_IMPL) 782449e17fSsherrym 792449e17fSsherrym #include <sys/types32.h> 802449e17fSsherrym 812449e17fSsherrym struct ucode_get_rev_struct32 { 822449e17fSsherrym caddr32_t ugv_rev; /* microcode revision array */ 832449e17fSsherrym int ugv_size; /* size of the array */ 842449e17fSsherrym ucode_errno_t ugv_errno; /* EUC error code */ 852449e17fSsherrym }; 862449e17fSsherrym 872449e17fSsherrym struct ucode_write_struct32 { 882449e17fSsherrym uint32_t uw_size; /* size of the uw_code buffer */ 892449e17fSsherrym caddr32_t uw_ucode; /* pointer to the undigested microcode */ 902449e17fSsherrym ucode_errno_t uw_errno; /* EUC error code */ 912449e17fSsherrym }; 922449e17fSsherrym 932449e17fSsherrym #endif /* _SYSCALL32_IMPL */ 942449e17fSsherrym 952449e17fSsherrym /* 96adc586deSMark Johnson * AMD Microcode file information 972449e17fSsherrym */ 98adc586deSMark Johnson typedef struct ucode_header_amd { 99adc586deSMark Johnson uint32_t uh_date; 100adc586deSMark Johnson uint32_t uh_patch_id; 101adc586deSMark Johnson uint32_t uh_internal; /* patch data id & length, init flag */ 102adc586deSMark Johnson uint32_t uh_cksum; 103adc586deSMark Johnson uint32_t uh_nb_id; 104adc586deSMark Johnson uint32_t uh_sb_id; 105adc586deSMark Johnson uint16_t uh_cpu_rev; 106adc586deSMark Johnson uint8_t uh_nb_rev; 107adc586deSMark Johnson uint8_t uh_sb_rev; 108adc586deSMark Johnson uint32_t uh_bios_rev; 109adc586deSMark Johnson uint32_t uh_match[8]; 110adc586deSMark Johnson } ucode_header_amd_t; 111adc586deSMark Johnson 112adc586deSMark Johnson typedef struct ucode_file_amd { 1130ba6f73dSMark Johnson #ifndef __xpv 114adc586deSMark Johnson ucode_header_amd_t uf_header; 115adc586deSMark Johnson uint8_t uf_data[896]; 116adc586deSMark Johnson uint8_t uf_resv[896]; 117adc586deSMark Johnson uint8_t uf_code_present; 118adc586deSMark Johnson uint8_t uf_code[191]; 119*5e53ed34SHans Rosenfeld uint8_t uf_encr[2048]; 1200ba6f73dSMark Johnson #else 1210ba6f73dSMark Johnson uint8_t *ucodep; 1220ba6f73dSMark Johnson uint32_t usize; 1230ba6f73dSMark Johnson #endif 124adc586deSMark Johnson } ucode_file_amd_t; 125adc586deSMark Johnson 126adc586deSMark Johnson typedef struct ucode_eqtbl_amd { 127adc586deSMark Johnson uint32_t ue_inst_cpu; 128adc586deSMark Johnson uint32_t ue_fixed_mask; 129adc586deSMark Johnson uint32_t ue_fixed_comp; 1300ba6f73dSMark Johnson uint16_t ue_equiv_cpu; 1310ba6f73dSMark Johnson uint16_t ue_reserved; 132adc586deSMark Johnson } ucode_eqtbl_amd_t; 133adc586deSMark Johnson 134adc586deSMark Johnson /* 135adc586deSMark Johnson * Intel Microcode file information 136adc586deSMark Johnson */ 137adc586deSMark Johnson typedef struct ucode_header_intel { 1382449e17fSsherrym uint32_t uh_header_ver; 1392449e17fSsherrym uint32_t uh_rev; 1402449e17fSsherrym uint32_t uh_date; 1412449e17fSsherrym uint32_t uh_signature; 1422449e17fSsherrym uint32_t uh_checksum; 1432449e17fSsherrym uint32_t uh_loader_ver; 1442449e17fSsherrym uint32_t uh_proc_flags; 1452449e17fSsherrym uint32_t uh_body_size; 1462449e17fSsherrym uint32_t uh_total_size; 1472449e17fSsherrym uint32_t uh_reserved[3]; 148adc586deSMark Johnson } ucode_header_intel_t; 1492449e17fSsherrym 150adc586deSMark Johnson typedef struct ucode_ext_sig_intel { 1512449e17fSsherrym uint32_t ues_signature; 1522449e17fSsherrym uint32_t ues_proc_flags; 1532449e17fSsherrym uint32_t ues_checksum; 154adc586deSMark Johnson } ucode_ext_sig_intel_t; 1552449e17fSsherrym 156adc586deSMark Johnson typedef struct ucode_ext_table_intel { 1572449e17fSsherrym uint32_t uet_count; 1582449e17fSsherrym uint32_t uet_checksum; 1592449e17fSsherrym uint32_t uet_reserved[3]; 160adc586deSMark Johnson ucode_ext_sig_intel_t uet_ext_sig[1]; 161adc586deSMark Johnson } ucode_ext_table_intel_t; 1622449e17fSsherrym 163adc586deSMark Johnson typedef struct ucode_file_intel { 164adc586deSMark Johnson ucode_header_intel_t *uf_header; 1652449e17fSsherrym uint8_t *uf_body; 166adc586deSMark Johnson ucode_ext_table_intel_t *uf_ext_table; 167adc586deSMark Johnson } ucode_file_intel_t; 168adc586deSMark Johnson 169adc586deSMark Johnson /* 170adc586deSMark Johnson * common container 171adc586deSMark Johnson */ 172adc586deSMark Johnson typedef union ucode_file { 173adc586deSMark Johnson ucode_file_amd_t *amd; 174adc586deSMark Johnson ucode_file_intel_t intel; 1752449e17fSsherrym } ucode_file_t; 1762449e17fSsherrym 1772449e17fSsherrym 1782449e17fSsherrym #define UCODE_SHORT_NAME_LEN 12 /* "32-bit-sig"-"8-bit-platid"\0 */ 1792449e17fSsherrym /* 1802449e17fSsherrym * Length of UCODE_INSTALL_COMMON_PATH/short-name 1812449e17fSsherrym * strlen(UCODE_INSTALL_COMMON_PATH) + 1 + UCODE_SHORT_NAME_LEN 1822449e17fSsherrym * Use sizeof which will give us the additional byte for the '/' in between 1832449e17fSsherrym * the common path and the file name. 1842449e17fSsherrym */ 1852449e17fSsherrym #define UCODE_COMMON_NAME_LEN \ 1862449e17fSsherrym (sizeof (UCODE_INSTALL_COMMON_PATH) + (UCODE_SHORT_NAME_LEN)) 1872449e17fSsherrym #define UCODE_MAX_PATH_LEN (PATH_MAX - UCODE_COMMON_NAME_LEN) 1882449e17fSsherrym 1892449e17fSsherrym 190adc586deSMark Johnson #define UCODE_HEADER_SIZE_INTEL (sizeof (struct ucode_header_intel)) 191adc586deSMark Johnson #define UCODE_EXT_TABLE_SIZE_INTEL (20) /* 20-bytes */ 192adc586deSMark Johnson #define UCODE_EXT_SIG_SIZE_INTEL (sizeof (struct ucode_ext_sig_intel)) 1932449e17fSsherrym 1942449e17fSsherrym #define UCODE_KB(a) ((a) << 10) /* KB */ 1952449e17fSsherrym #define UCODE_MB(a) ((a) << 20) /* MB */ 1962449e17fSsherrym #define UCODE_DEFAULT_TOTAL_SIZE UCODE_KB(2) 197adc586deSMark Johnson #define UCODE_DEFAULT_BODY_SIZE (UCODE_KB(2) - UCODE_HEADER_SIZE_INTEL) 1982449e17fSsherrym 1992449e17fSsherrym /* 2002449e17fSsherrym * For a single microcode file, the minimum size is 1K, maximum size is 16K. 2012449e17fSsherrym * Such limitations, while somewhat artificial, are not only to provide better 2022449e17fSsherrym * sanity checks, but also avoid wasting precious memory at startup time as the 2032449e17fSsherrym * microcode buffer for the first processor has to be statically allocated. 2042449e17fSsherrym * 2052449e17fSsherrym * For the concatenation of all the microcode binary files, the maximum size 2062449e17fSsherrym * is 16M. 2072449e17fSsherrym */ 2082449e17fSsherrym #define UCODE_MIN_SIZE UCODE_KB(1) 2092449e17fSsherrym #define UCODE_MAX_SIZE UCODE_KB(16) 2102449e17fSsherrym #define UCODE_MAX_COMBINED_SIZE UCODE_MB(16) 2112449e17fSsherrym 2122449e17fSsherrym #define UCODE_SIZE_CONVERT(size, default_size) \ 2132449e17fSsherrym ((size) == 0 ? (default_size) : (size)) 2142449e17fSsherrym 215adc586deSMark Johnson #define UCODE_BODY_SIZE_INTEL(size) \ 2162449e17fSsherrym UCODE_SIZE_CONVERT((size), UCODE_DEFAULT_BODY_SIZE) 2172449e17fSsherrym 218adc586deSMark Johnson #define UCODE_TOTAL_SIZE_INTEL(size) \ 2192449e17fSsherrym UCODE_SIZE_CONVERT((size), UCODE_DEFAULT_TOTAL_SIZE) 2202449e17fSsherrym 221adc586deSMark Johnson #define UCODE_MATCH_INTEL(sig1, sig2, pf1, pf2) \ 2222449e17fSsherrym (((sig1) == (sig2)) && \ 2232449e17fSsherrym (((pf1) & (pf2)) || (((pf1) == 0) && ((pf2) == 0)))) 2242449e17fSsherrym 225adc586deSMark Johnson extern ucode_errno_t ucode_header_validate_intel(ucode_header_intel_t *); 226adc586deSMark Johnson extern uint32_t ucode_checksum_intel(uint32_t, uint32_t, uint8_t *); 227adc586deSMark Johnson 228adc586deSMark Johnson extern ucode_errno_t ucode_validate_amd(uint8_t *, int); 229adc586deSMark Johnson extern ucode_errno_t ucode_validate_intel(uint8_t *, int); 230adc586deSMark Johnson 231adc586deSMark Johnson #ifdef _KERNEL 2322449e17fSsherrym extern ucode_errno_t ucode_get_rev(uint32_t *); 2332449e17fSsherrym extern ucode_errno_t ucode_update(uint8_t *, int); 2342449e17fSsherrym 235adc586deSMark Johnson /* 236adc586deSMark Johnson * Microcode specific information per core 237adc586deSMark Johnson */ 238adc586deSMark Johnson typedef struct cpu_ucode_info { 239adc586deSMark Johnson uint32_t cui_platid; /* platform id */ 240adc586deSMark Johnson uint32_t cui_rev; /* microcode revision */ 241adc586deSMark Johnson } cpu_ucode_info_t; 242adc586deSMark Johnson 243adc586deSMark Johnson /* 244adc586deSMark Johnson * Data structure used for xcall 245adc586deSMark Johnson */ 246adc586deSMark Johnson typedef struct ucode_update { 247adc586deSMark Johnson uint32_t sig; /* signature */ 248adc586deSMark Johnson cpu_ucode_info_t info; /* ucode info */ 249adc586deSMark Johnson uint32_t expected_rev; 250adc586deSMark Johnson uint32_t new_rev; 251adc586deSMark Johnson uint8_t *ucodep; /* pointer to ucode */ 252adc586deSMark Johnson uint32_t usize; 253adc586deSMark Johnson } ucode_update_t; 254adc586deSMark Johnson 255adc586deSMark Johnson /* 256adc586deSMark Johnson * Microcode kernel operations 257adc586deSMark Johnson */ 258adc586deSMark Johnson struct ucode_ops { 259adc586deSMark Johnson uint32_t write_msr; 260adc586deSMark Johnson int (*capable)(cpu_t *); 261adc586deSMark Johnson void (*file_reset)(ucode_file_t *, processorid_t); 262adc586deSMark Johnson void (*read_rev)(cpu_ucode_info_t *); 263adc586deSMark Johnson uint32_t (*load)(ucode_file_t *, cpu_ucode_info_t *, cpu_t *); 264adc586deSMark Johnson ucode_errno_t (*validate)(uint8_t *, int); 265adc586deSMark Johnson ucode_errno_t (*extract)(ucode_update_t *, uint8_t *, int); 266adc586deSMark Johnson ucode_errno_t (*locate)(cpu_t *, cpu_ucode_info_t *, ucode_file_t *); 267adc586deSMark Johnson }; 268adc586deSMark Johnson #else 269adc586deSMark Johnson 2702449e17fSsherrym #define UCODE_MAX_VENDORS_NAME_LEN 20 2712449e17fSsherrym 2722449e17fSsherrym #define UCODE_VENDORS \ 2732449e17fSsherrym static struct { \ 2742449e17fSsherrym char *filestr; \ 275adc586deSMark Johnson char *extstr; \ 2762449e17fSsherrym char *vendorstr; \ 2772449e17fSsherrym int supported; \ 2782449e17fSsherrym } ucode_vendors[] = { \ 279adc586deSMark Johnson { "intel", "txt", "GenuineIntel", 1 }, \ 280adc586deSMark Johnson { "amd", "bin", "AuthenticAMD", 1 }, \ 281adc586deSMark Johnson { NULL, NULL, NULL, 0 } \ 2822449e17fSsherrym } 2832449e17fSsherrym 284adc586deSMark Johnson /* 285adc586deSMark Johnson * Microcode user operations 286adc586deSMark Johnson */ 287adc586deSMark Johnson struct ucode_ops { 288adc586deSMark Johnson int (*convert)(const char *, uint8_t *, size_t); 289adc586deSMark Johnson ucode_errno_t (*gen_files)(uint8_t *, int, char *); 290adc586deSMark Johnson ucode_errno_t (*validate)(uint8_t *, int); 291adc586deSMark Johnson }; 292adc586deSMark Johnson #endif 293adc586deSMark Johnson 294adc586deSMark Johnson extern const struct ucode_ops *ucode; 295adc586deSMark Johnson 2962449e17fSsherrym #ifdef __cplusplus 2972449e17fSsherrym } 2982449e17fSsherrym #endif 2992449e17fSsherrym 3002449e17fSsherrym #endif /* _SYS_UCODE_H */ 301