14581Ssherrym /* 24581Ssherrym * CDDL HEADER START 34581Ssherrym * 44581Ssherrym * The contents of this file are subject to the terms of the 54581Ssherrym * Common Development and Distribution License (the "License"). 64581Ssherrym * You may not use this file except in compliance with the License. 74581Ssherrym * 84581Ssherrym * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94581Ssherrym * or http://www.opensolaris.org/os/licensing. 104581Ssherrym * See the License for the specific language governing permissions 114581Ssherrym * and limitations under the License. 124581Ssherrym * 134581Ssherrym * When distributing Covered Code, include this CDDL HEADER in each 144581Ssherrym * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154581Ssherrym * If applicable, add the following below this CDDL HEADER, with the 164581Ssherrym * fields enclosed by brackets "[]" replaced with your own identifying 174581Ssherrym * information: Portions Copyright [yyyy] [name of copyright owner] 184581Ssherrym * 194581Ssherrym * CDDL HEADER END 204581Ssherrym */ 214581Ssherrym /* 22*7605SMark.Johnson@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 234581Ssherrym * Use is subject to license terms. 244581Ssherrym */ 254581Ssherrym 264581Ssherrym #ifndef _SYS_UCODE_H 274581Ssherrym #define _SYS_UCODE_H 284581Ssherrym 29*7605SMark.Johnson@Sun.COM #ifdef _KERNEL 30*7605SMark.Johnson@Sun.COM #include <sys/cpuvar.h> 31*7605SMark.Johnson@Sun.COM #endif 324581Ssherrym #include <sys/types.h> 334581Ssherrym #include <sys/priv.h> 344581Ssherrym #include <sys/processor.h> 354581Ssherrym #ifndef _KERNEL 364581Ssherrym #include <limits.h> 374581Ssherrym #endif 384581Ssherrym #include <ucode/ucode_errno.h> 394581Ssherrym 404581Ssherrym #ifdef __cplusplus 414581Ssherrym extern "C" { 424581Ssherrym #endif 434581Ssherrym 444581Ssherrym /* 454581Ssherrym * /dev/ucode 464581Ssherrym */ 474581Ssherrym #define UCODE_DRIVER_NAME "ucode" 484581Ssherrym #define UCODE_NODE_NAME "ucode" 494581Ssherrym #define UCODE_MINOR ((minor_t)0x3fffful) 504581Ssherrym 514581Ssherrym /* 524581Ssherrym * Where to install the microcode 534581Ssherrym */ 544581Ssherrym #define UCODE_INSTALL_PATH "platform/i86pc/ucode" 554581Ssherrym #define UCODE_INSTALL_COMMON_PATH ".f" 564581Ssherrym 574581Ssherrym /* 584581Ssherrym * ioctl numbers 594581Ssherrym */ 604581Ssherrym #define UCODE_IOC (('u'<<24)|('c'<<16)|('o'<<8)) 614581Ssherrym 624581Ssherrym #define UCODE_GET_VERSION (UCODE_IOC|0) 634581Ssherrym #define UCODE_UPDATE (UCODE_IOC|1) 644581Ssherrym 654581Ssherrym struct ucode_get_rev_struct { 664581Ssherrym uint32_t *ugv_rev; /* microcode revision array */ 674581Ssherrym int ugv_size; /* size of the array */ 684581Ssherrym ucode_errno_t ugv_errno; /* EUC error code */ 694581Ssherrym }; 704581Ssherrym 714581Ssherrym struct ucode_write_struct { 724581Ssherrym uint32_t uw_size; /* size of the uw_code buffer */ 734581Ssherrym uint8_t *uw_ucode; /* pointer to the undigested microcode */ 744581Ssherrym ucode_errno_t uw_errno; /* EUC error code */ 754581Ssherrym }; 764581Ssherrym 774581Ssherrym #if defined(_SYSCALL32_IMPL) 784581Ssherrym 794581Ssherrym #include <sys/types32.h> 804581Ssherrym 814581Ssherrym struct ucode_get_rev_struct32 { 824581Ssherrym caddr32_t ugv_rev; /* microcode revision array */ 834581Ssherrym int ugv_size; /* size of the array */ 844581Ssherrym ucode_errno_t ugv_errno; /* EUC error code */ 854581Ssherrym }; 864581Ssherrym 874581Ssherrym struct ucode_write_struct32 { 884581Ssherrym uint32_t uw_size; /* size of the uw_code buffer */ 894581Ssherrym caddr32_t uw_ucode; /* pointer to the undigested microcode */ 904581Ssherrym ucode_errno_t uw_errno; /* EUC error code */ 914581Ssherrym }; 924581Ssherrym 934581Ssherrym #endif /* _SYSCALL32_IMPL */ 944581Ssherrym 954581Ssherrym /* 96*7605SMark.Johnson@Sun.COM * AMD Microcode file information 974581Ssherrym */ 98*7605SMark.Johnson@Sun.COM typedef struct ucode_header_amd { 99*7605SMark.Johnson@Sun.COM uint32_t uh_date; 100*7605SMark.Johnson@Sun.COM uint32_t uh_patch_id; 101*7605SMark.Johnson@Sun.COM uint32_t uh_internal; /* patch data id & length, init flag */ 102*7605SMark.Johnson@Sun.COM uint32_t uh_cksum; 103*7605SMark.Johnson@Sun.COM uint32_t uh_nb_id; 104*7605SMark.Johnson@Sun.COM uint32_t uh_sb_id; 105*7605SMark.Johnson@Sun.COM uint16_t uh_cpu_rev; 106*7605SMark.Johnson@Sun.COM uint8_t uh_nb_rev; 107*7605SMark.Johnson@Sun.COM uint8_t uh_sb_rev; 108*7605SMark.Johnson@Sun.COM uint32_t uh_bios_rev; 109*7605SMark.Johnson@Sun.COM uint32_t uh_match[8]; 110*7605SMark.Johnson@Sun.COM } ucode_header_amd_t; 111*7605SMark.Johnson@Sun.COM 112*7605SMark.Johnson@Sun.COM typedef struct ucode_file_amd { 113*7605SMark.Johnson@Sun.COM ucode_header_amd_t uf_header; 114*7605SMark.Johnson@Sun.COM uint8_t uf_data[896]; 115*7605SMark.Johnson@Sun.COM uint8_t uf_resv[896]; 116*7605SMark.Johnson@Sun.COM uint8_t uf_code_present; 117*7605SMark.Johnson@Sun.COM uint8_t uf_code[191]; 118*7605SMark.Johnson@Sun.COM } ucode_file_amd_t; 119*7605SMark.Johnson@Sun.COM 120*7605SMark.Johnson@Sun.COM typedef struct ucode_eqtbl_amd { 121*7605SMark.Johnson@Sun.COM uint32_t ue_inst_cpu; 122*7605SMark.Johnson@Sun.COM uint32_t ue_fixed_mask; 123*7605SMark.Johnson@Sun.COM uint32_t ue_fixed_comp; 124*7605SMark.Johnson@Sun.COM uint32_t ue_equiv_cpu; 125*7605SMark.Johnson@Sun.COM } ucode_eqtbl_amd_t; 126*7605SMark.Johnson@Sun.COM 127*7605SMark.Johnson@Sun.COM /* 128*7605SMark.Johnson@Sun.COM * Intel Microcode file information 129*7605SMark.Johnson@Sun.COM */ 130*7605SMark.Johnson@Sun.COM typedef struct ucode_header_intel { 1314581Ssherrym uint32_t uh_header_ver; 1324581Ssherrym uint32_t uh_rev; 1334581Ssherrym uint32_t uh_date; 1344581Ssherrym uint32_t uh_signature; 1354581Ssherrym uint32_t uh_checksum; 1364581Ssherrym uint32_t uh_loader_ver; 1374581Ssherrym uint32_t uh_proc_flags; 1384581Ssherrym uint32_t uh_body_size; 1394581Ssherrym uint32_t uh_total_size; 1404581Ssherrym uint32_t uh_reserved[3]; 141*7605SMark.Johnson@Sun.COM } ucode_header_intel_t; 1424581Ssherrym 143*7605SMark.Johnson@Sun.COM typedef struct ucode_ext_sig_intel { 1444581Ssherrym uint32_t ues_signature; 1454581Ssherrym uint32_t ues_proc_flags; 1464581Ssherrym uint32_t ues_checksum; 147*7605SMark.Johnson@Sun.COM } ucode_ext_sig_intel_t; 1484581Ssherrym 149*7605SMark.Johnson@Sun.COM typedef struct ucode_ext_table_intel { 1504581Ssherrym uint32_t uet_count; 1514581Ssherrym uint32_t uet_checksum; 1524581Ssherrym uint32_t uet_reserved[3]; 153*7605SMark.Johnson@Sun.COM ucode_ext_sig_intel_t uet_ext_sig[1]; 154*7605SMark.Johnson@Sun.COM } ucode_ext_table_intel_t; 1554581Ssherrym 156*7605SMark.Johnson@Sun.COM typedef struct ucode_file_intel { 157*7605SMark.Johnson@Sun.COM ucode_header_intel_t *uf_header; 1584581Ssherrym uint8_t *uf_body; 159*7605SMark.Johnson@Sun.COM ucode_ext_table_intel_t *uf_ext_table; 160*7605SMark.Johnson@Sun.COM } ucode_file_intel_t; 161*7605SMark.Johnson@Sun.COM 162*7605SMark.Johnson@Sun.COM /* 163*7605SMark.Johnson@Sun.COM * common container 164*7605SMark.Johnson@Sun.COM */ 165*7605SMark.Johnson@Sun.COM typedef union ucode_file { 166*7605SMark.Johnson@Sun.COM ucode_file_amd_t *amd; 167*7605SMark.Johnson@Sun.COM ucode_file_intel_t intel; 1684581Ssherrym } ucode_file_t; 1694581Ssherrym 1704581Ssherrym 1714581Ssherrym #define UCODE_SHORT_NAME_LEN 12 /* "32-bit-sig"-"8-bit-platid"\0 */ 1724581Ssherrym /* 1734581Ssherrym * Length of UCODE_INSTALL_COMMON_PATH/short-name 1744581Ssherrym * strlen(UCODE_INSTALL_COMMON_PATH) + 1 + UCODE_SHORT_NAME_LEN 1754581Ssherrym * Use sizeof which will give us the additional byte for the '/' in between 1764581Ssherrym * the common path and the file name. 1774581Ssherrym */ 1784581Ssherrym #define UCODE_COMMON_NAME_LEN \ 1794581Ssherrym (sizeof (UCODE_INSTALL_COMMON_PATH) + (UCODE_SHORT_NAME_LEN)) 1804581Ssherrym #define UCODE_MAX_PATH_LEN (PATH_MAX - UCODE_COMMON_NAME_LEN) 1814581Ssherrym 1824581Ssherrym 183*7605SMark.Johnson@Sun.COM #define UCODE_HEADER_SIZE_INTEL (sizeof (struct ucode_header_intel)) 184*7605SMark.Johnson@Sun.COM #define UCODE_EXT_TABLE_SIZE_INTEL (20) /* 20-bytes */ 185*7605SMark.Johnson@Sun.COM #define UCODE_EXT_SIG_SIZE_INTEL (sizeof (struct ucode_ext_sig_intel)) 1864581Ssherrym 1874581Ssherrym #define UCODE_KB(a) ((a) << 10) /* KB */ 1884581Ssherrym #define UCODE_MB(a) ((a) << 20) /* MB */ 1894581Ssherrym #define UCODE_DEFAULT_TOTAL_SIZE UCODE_KB(2) 190*7605SMark.Johnson@Sun.COM #define UCODE_DEFAULT_BODY_SIZE (UCODE_KB(2) - UCODE_HEADER_SIZE_INTEL) 1914581Ssherrym 1924581Ssherrym /* 1934581Ssherrym * For a single microcode file, the minimum size is 1K, maximum size is 16K. 1944581Ssherrym * Such limitations, while somewhat artificial, are not only to provide better 1954581Ssherrym * sanity checks, but also avoid wasting precious memory at startup time as the 1964581Ssherrym * microcode buffer for the first processor has to be statically allocated. 1974581Ssherrym * 1984581Ssherrym * For the concatenation of all the microcode binary files, the maximum size 1994581Ssherrym * is 16M. 2004581Ssherrym */ 2014581Ssherrym #define UCODE_MIN_SIZE UCODE_KB(1) 2024581Ssherrym #define UCODE_MAX_SIZE UCODE_KB(16) 2034581Ssherrym #define UCODE_MAX_COMBINED_SIZE UCODE_MB(16) 2044581Ssherrym 2054581Ssherrym #define UCODE_SIZE_CONVERT(size, default_size) \ 2064581Ssherrym ((size) == 0 ? (default_size) : (size)) 2074581Ssherrym 208*7605SMark.Johnson@Sun.COM #define UCODE_BODY_SIZE_INTEL(size) \ 2094581Ssherrym UCODE_SIZE_CONVERT((size), UCODE_DEFAULT_BODY_SIZE) 2104581Ssherrym 211*7605SMark.Johnson@Sun.COM #define UCODE_TOTAL_SIZE_INTEL(size) \ 2124581Ssherrym UCODE_SIZE_CONVERT((size), UCODE_DEFAULT_TOTAL_SIZE) 2134581Ssherrym 214*7605SMark.Johnson@Sun.COM #define UCODE_MATCH_INTEL(sig1, sig2, pf1, pf2) \ 2154581Ssherrym (((sig1) == (sig2)) && \ 2164581Ssherrym (((pf1) & (pf2)) || (((pf1) == 0) && ((pf2) == 0)))) 2174581Ssherrym 218*7605SMark.Johnson@Sun.COM extern ucode_errno_t ucode_header_validate_intel(ucode_header_intel_t *); 219*7605SMark.Johnson@Sun.COM extern uint32_t ucode_checksum_intel(uint32_t, uint32_t, uint8_t *); 220*7605SMark.Johnson@Sun.COM 221*7605SMark.Johnson@Sun.COM extern ucode_errno_t ucode_validate_amd(uint8_t *, int); 222*7605SMark.Johnson@Sun.COM extern ucode_errno_t ucode_validate_intel(uint8_t *, int); 223*7605SMark.Johnson@Sun.COM 224*7605SMark.Johnson@Sun.COM #ifdef _KERNEL 2254581Ssherrym extern ucode_errno_t ucode_get_rev(uint32_t *); 2264581Ssherrym extern ucode_errno_t ucode_update(uint8_t *, int); 2274581Ssherrym 228*7605SMark.Johnson@Sun.COM /* 229*7605SMark.Johnson@Sun.COM * Microcode specific information per core 230*7605SMark.Johnson@Sun.COM */ 231*7605SMark.Johnson@Sun.COM typedef struct cpu_ucode_info { 232*7605SMark.Johnson@Sun.COM uint32_t cui_platid; /* platform id */ 233*7605SMark.Johnson@Sun.COM uint32_t cui_rev; /* microcode revision */ 234*7605SMark.Johnson@Sun.COM } cpu_ucode_info_t; 235*7605SMark.Johnson@Sun.COM 236*7605SMark.Johnson@Sun.COM /* 237*7605SMark.Johnson@Sun.COM * Data structure used for xcall 238*7605SMark.Johnson@Sun.COM */ 239*7605SMark.Johnson@Sun.COM typedef struct ucode_update { 240*7605SMark.Johnson@Sun.COM uint32_t sig; /* signature */ 241*7605SMark.Johnson@Sun.COM cpu_ucode_info_t info; /* ucode info */ 242*7605SMark.Johnson@Sun.COM uint32_t expected_rev; 243*7605SMark.Johnson@Sun.COM uint32_t new_rev; 244*7605SMark.Johnson@Sun.COM uint8_t *ucodep; /* pointer to ucode */ 245*7605SMark.Johnson@Sun.COM uint32_t usize; 246*7605SMark.Johnson@Sun.COM } ucode_update_t; 247*7605SMark.Johnson@Sun.COM 248*7605SMark.Johnson@Sun.COM /* 249*7605SMark.Johnson@Sun.COM * Microcode kernel operations 250*7605SMark.Johnson@Sun.COM */ 251*7605SMark.Johnson@Sun.COM struct ucode_ops { 252*7605SMark.Johnson@Sun.COM uint32_t write_msr; 253*7605SMark.Johnson@Sun.COM int (*capable)(cpu_t *); 254*7605SMark.Johnson@Sun.COM void (*file_reset)(ucode_file_t *, processorid_t); 255*7605SMark.Johnson@Sun.COM void (*read_rev)(cpu_ucode_info_t *); 256*7605SMark.Johnson@Sun.COM uint32_t (*load)(ucode_file_t *, cpu_ucode_info_t *, cpu_t *); 257*7605SMark.Johnson@Sun.COM ucode_errno_t (*validate)(uint8_t *, int); 258*7605SMark.Johnson@Sun.COM ucode_errno_t (*extract)(ucode_update_t *, uint8_t *, int); 259*7605SMark.Johnson@Sun.COM ucode_errno_t (*locate)(cpu_t *, cpu_ucode_info_t *, ucode_file_t *); 260*7605SMark.Johnson@Sun.COM }; 261*7605SMark.Johnson@Sun.COM #else 262*7605SMark.Johnson@Sun.COM 2634581Ssherrym #define UCODE_MAX_VENDORS_NAME_LEN 20 2644581Ssherrym 2654581Ssherrym #define UCODE_VENDORS \ 2664581Ssherrym static struct { \ 2674581Ssherrym char *filestr; \ 268*7605SMark.Johnson@Sun.COM char *extstr; \ 2694581Ssherrym char *vendorstr; \ 2704581Ssherrym int supported; \ 2714581Ssherrym } ucode_vendors[] = { \ 272*7605SMark.Johnson@Sun.COM { "intel", "txt", "GenuineIntel", 1 }, \ 273*7605SMark.Johnson@Sun.COM { "amd", "bin", "AuthenticAMD", 1 }, \ 274*7605SMark.Johnson@Sun.COM { NULL, NULL, NULL, 0 } \ 2754581Ssherrym } 2764581Ssherrym 277*7605SMark.Johnson@Sun.COM /* 278*7605SMark.Johnson@Sun.COM * Microcode user operations 279*7605SMark.Johnson@Sun.COM */ 280*7605SMark.Johnson@Sun.COM struct ucode_ops { 281*7605SMark.Johnson@Sun.COM int (*convert)(const char *, uint8_t *, size_t); 282*7605SMark.Johnson@Sun.COM ucode_errno_t (*gen_files)(uint8_t *, int, char *); 283*7605SMark.Johnson@Sun.COM ucode_errno_t (*validate)(uint8_t *, int); 284*7605SMark.Johnson@Sun.COM }; 285*7605SMark.Johnson@Sun.COM #endif 286*7605SMark.Johnson@Sun.COM 287*7605SMark.Johnson@Sun.COM extern const struct ucode_ops *ucode; 288*7605SMark.Johnson@Sun.COM 2894581Ssherrym #ifdef __cplusplus 2904581Ssherrym } 2914581Ssherrym #endif 2924581Ssherrym 2934581Ssherrym #endif /* _SYS_UCODE_H */ 294