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*8647SMark.Johnson@Sun.COM * Copyright 2009 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 297605SMark.Johnson@Sun.COM #ifdef _KERNEL 307605SMark.Johnson@Sun.COM #include <sys/cpuvar.h> 317605SMark.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 /* 967605SMark.Johnson@Sun.COM * AMD Microcode file information 974581Ssherrym */ 987605SMark.Johnson@Sun.COM typedef struct ucode_header_amd { 997605SMark.Johnson@Sun.COM uint32_t uh_date; 1007605SMark.Johnson@Sun.COM uint32_t uh_patch_id; 1017605SMark.Johnson@Sun.COM uint32_t uh_internal; /* patch data id & length, init flag */ 1027605SMark.Johnson@Sun.COM uint32_t uh_cksum; 1037605SMark.Johnson@Sun.COM uint32_t uh_nb_id; 1047605SMark.Johnson@Sun.COM uint32_t uh_sb_id; 1057605SMark.Johnson@Sun.COM uint16_t uh_cpu_rev; 1067605SMark.Johnson@Sun.COM uint8_t uh_nb_rev; 1077605SMark.Johnson@Sun.COM uint8_t uh_sb_rev; 1087605SMark.Johnson@Sun.COM uint32_t uh_bios_rev; 1097605SMark.Johnson@Sun.COM uint32_t uh_match[8]; 1107605SMark.Johnson@Sun.COM } ucode_header_amd_t; 1117605SMark.Johnson@Sun.COM 1127605SMark.Johnson@Sun.COM typedef struct ucode_file_amd { 113*8647SMark.Johnson@Sun.COM #ifndef __xpv 1147605SMark.Johnson@Sun.COM ucode_header_amd_t uf_header; 1157605SMark.Johnson@Sun.COM uint8_t uf_data[896]; 1167605SMark.Johnson@Sun.COM uint8_t uf_resv[896]; 1177605SMark.Johnson@Sun.COM uint8_t uf_code_present; 1187605SMark.Johnson@Sun.COM uint8_t uf_code[191]; 119*8647SMark.Johnson@Sun.COM #else 120*8647SMark.Johnson@Sun.COM uint8_t *ucodep; 121*8647SMark.Johnson@Sun.COM uint32_t usize; 122*8647SMark.Johnson@Sun.COM #endif 1237605SMark.Johnson@Sun.COM } ucode_file_amd_t; 1247605SMark.Johnson@Sun.COM 1257605SMark.Johnson@Sun.COM typedef struct ucode_eqtbl_amd { 1267605SMark.Johnson@Sun.COM uint32_t ue_inst_cpu; 1277605SMark.Johnson@Sun.COM uint32_t ue_fixed_mask; 1287605SMark.Johnson@Sun.COM uint32_t ue_fixed_comp; 129*8647SMark.Johnson@Sun.COM uint16_t ue_equiv_cpu; 130*8647SMark.Johnson@Sun.COM uint16_t ue_reserved; 1317605SMark.Johnson@Sun.COM } ucode_eqtbl_amd_t; 1327605SMark.Johnson@Sun.COM 1337605SMark.Johnson@Sun.COM /* 1347605SMark.Johnson@Sun.COM * Intel Microcode file information 1357605SMark.Johnson@Sun.COM */ 1367605SMark.Johnson@Sun.COM typedef struct ucode_header_intel { 1374581Ssherrym uint32_t uh_header_ver; 1384581Ssherrym uint32_t uh_rev; 1394581Ssherrym uint32_t uh_date; 1404581Ssherrym uint32_t uh_signature; 1414581Ssherrym uint32_t uh_checksum; 1424581Ssherrym uint32_t uh_loader_ver; 1434581Ssherrym uint32_t uh_proc_flags; 1444581Ssherrym uint32_t uh_body_size; 1454581Ssherrym uint32_t uh_total_size; 1464581Ssherrym uint32_t uh_reserved[3]; 1477605SMark.Johnson@Sun.COM } ucode_header_intel_t; 1484581Ssherrym 1497605SMark.Johnson@Sun.COM typedef struct ucode_ext_sig_intel { 1504581Ssherrym uint32_t ues_signature; 1514581Ssherrym uint32_t ues_proc_flags; 1524581Ssherrym uint32_t ues_checksum; 1537605SMark.Johnson@Sun.COM } ucode_ext_sig_intel_t; 1544581Ssherrym 1557605SMark.Johnson@Sun.COM typedef struct ucode_ext_table_intel { 1564581Ssherrym uint32_t uet_count; 1574581Ssherrym uint32_t uet_checksum; 1584581Ssherrym uint32_t uet_reserved[3]; 1597605SMark.Johnson@Sun.COM ucode_ext_sig_intel_t uet_ext_sig[1]; 1607605SMark.Johnson@Sun.COM } ucode_ext_table_intel_t; 1614581Ssherrym 1627605SMark.Johnson@Sun.COM typedef struct ucode_file_intel { 1637605SMark.Johnson@Sun.COM ucode_header_intel_t *uf_header; 1644581Ssherrym uint8_t *uf_body; 1657605SMark.Johnson@Sun.COM ucode_ext_table_intel_t *uf_ext_table; 1667605SMark.Johnson@Sun.COM } ucode_file_intel_t; 1677605SMark.Johnson@Sun.COM 1687605SMark.Johnson@Sun.COM /* 1697605SMark.Johnson@Sun.COM * common container 1707605SMark.Johnson@Sun.COM */ 1717605SMark.Johnson@Sun.COM typedef union ucode_file { 1727605SMark.Johnson@Sun.COM ucode_file_amd_t *amd; 1737605SMark.Johnson@Sun.COM ucode_file_intel_t intel; 1744581Ssherrym } ucode_file_t; 1754581Ssherrym 1764581Ssherrym 1774581Ssherrym #define UCODE_SHORT_NAME_LEN 12 /* "32-bit-sig"-"8-bit-platid"\0 */ 1784581Ssherrym /* 1794581Ssherrym * Length of UCODE_INSTALL_COMMON_PATH/short-name 1804581Ssherrym * strlen(UCODE_INSTALL_COMMON_PATH) + 1 + UCODE_SHORT_NAME_LEN 1814581Ssherrym * Use sizeof which will give us the additional byte for the '/' in between 1824581Ssherrym * the common path and the file name. 1834581Ssherrym */ 1844581Ssherrym #define UCODE_COMMON_NAME_LEN \ 1854581Ssherrym (sizeof (UCODE_INSTALL_COMMON_PATH) + (UCODE_SHORT_NAME_LEN)) 1864581Ssherrym #define UCODE_MAX_PATH_LEN (PATH_MAX - UCODE_COMMON_NAME_LEN) 1874581Ssherrym 1884581Ssherrym 1897605SMark.Johnson@Sun.COM #define UCODE_HEADER_SIZE_INTEL (sizeof (struct ucode_header_intel)) 1907605SMark.Johnson@Sun.COM #define UCODE_EXT_TABLE_SIZE_INTEL (20) /* 20-bytes */ 1917605SMark.Johnson@Sun.COM #define UCODE_EXT_SIG_SIZE_INTEL (sizeof (struct ucode_ext_sig_intel)) 1924581Ssherrym 1934581Ssherrym #define UCODE_KB(a) ((a) << 10) /* KB */ 1944581Ssherrym #define UCODE_MB(a) ((a) << 20) /* MB */ 1954581Ssherrym #define UCODE_DEFAULT_TOTAL_SIZE UCODE_KB(2) 1967605SMark.Johnson@Sun.COM #define UCODE_DEFAULT_BODY_SIZE (UCODE_KB(2) - UCODE_HEADER_SIZE_INTEL) 1974581Ssherrym 1984581Ssherrym /* 1994581Ssherrym * For a single microcode file, the minimum size is 1K, maximum size is 16K. 2004581Ssherrym * Such limitations, while somewhat artificial, are not only to provide better 2014581Ssherrym * sanity checks, but also avoid wasting precious memory at startup time as the 2024581Ssherrym * microcode buffer for the first processor has to be statically allocated. 2034581Ssherrym * 2044581Ssherrym * For the concatenation of all the microcode binary files, the maximum size 2054581Ssherrym * is 16M. 2064581Ssherrym */ 2074581Ssherrym #define UCODE_MIN_SIZE UCODE_KB(1) 2084581Ssherrym #define UCODE_MAX_SIZE UCODE_KB(16) 2094581Ssherrym #define UCODE_MAX_COMBINED_SIZE UCODE_MB(16) 2104581Ssherrym 2114581Ssherrym #define UCODE_SIZE_CONVERT(size, default_size) \ 2124581Ssherrym ((size) == 0 ? (default_size) : (size)) 2134581Ssherrym 2147605SMark.Johnson@Sun.COM #define UCODE_BODY_SIZE_INTEL(size) \ 2154581Ssherrym UCODE_SIZE_CONVERT((size), UCODE_DEFAULT_BODY_SIZE) 2164581Ssherrym 2177605SMark.Johnson@Sun.COM #define UCODE_TOTAL_SIZE_INTEL(size) \ 2184581Ssherrym UCODE_SIZE_CONVERT((size), UCODE_DEFAULT_TOTAL_SIZE) 2194581Ssherrym 2207605SMark.Johnson@Sun.COM #define UCODE_MATCH_INTEL(sig1, sig2, pf1, pf2) \ 2214581Ssherrym (((sig1) == (sig2)) && \ 2224581Ssherrym (((pf1) & (pf2)) || (((pf1) == 0) && ((pf2) == 0)))) 2234581Ssherrym 2247605SMark.Johnson@Sun.COM extern ucode_errno_t ucode_header_validate_intel(ucode_header_intel_t *); 2257605SMark.Johnson@Sun.COM extern uint32_t ucode_checksum_intel(uint32_t, uint32_t, uint8_t *); 2267605SMark.Johnson@Sun.COM 2277605SMark.Johnson@Sun.COM extern ucode_errno_t ucode_validate_amd(uint8_t *, int); 2287605SMark.Johnson@Sun.COM extern ucode_errno_t ucode_validate_intel(uint8_t *, int); 2297605SMark.Johnson@Sun.COM 2307605SMark.Johnson@Sun.COM #ifdef _KERNEL 2314581Ssherrym extern ucode_errno_t ucode_get_rev(uint32_t *); 2324581Ssherrym extern ucode_errno_t ucode_update(uint8_t *, int); 2334581Ssherrym 2347605SMark.Johnson@Sun.COM /* 2357605SMark.Johnson@Sun.COM * Microcode specific information per core 2367605SMark.Johnson@Sun.COM */ 2377605SMark.Johnson@Sun.COM typedef struct cpu_ucode_info { 2387605SMark.Johnson@Sun.COM uint32_t cui_platid; /* platform id */ 2397605SMark.Johnson@Sun.COM uint32_t cui_rev; /* microcode revision */ 2407605SMark.Johnson@Sun.COM } cpu_ucode_info_t; 2417605SMark.Johnson@Sun.COM 2427605SMark.Johnson@Sun.COM /* 2437605SMark.Johnson@Sun.COM * Data structure used for xcall 2447605SMark.Johnson@Sun.COM */ 2457605SMark.Johnson@Sun.COM typedef struct ucode_update { 2467605SMark.Johnson@Sun.COM uint32_t sig; /* signature */ 2477605SMark.Johnson@Sun.COM cpu_ucode_info_t info; /* ucode info */ 2487605SMark.Johnson@Sun.COM uint32_t expected_rev; 2497605SMark.Johnson@Sun.COM uint32_t new_rev; 2507605SMark.Johnson@Sun.COM uint8_t *ucodep; /* pointer to ucode */ 2517605SMark.Johnson@Sun.COM uint32_t usize; 2527605SMark.Johnson@Sun.COM } ucode_update_t; 2537605SMark.Johnson@Sun.COM 2547605SMark.Johnson@Sun.COM /* 2557605SMark.Johnson@Sun.COM * Microcode kernel operations 2567605SMark.Johnson@Sun.COM */ 2577605SMark.Johnson@Sun.COM struct ucode_ops { 2587605SMark.Johnson@Sun.COM uint32_t write_msr; 2597605SMark.Johnson@Sun.COM int (*capable)(cpu_t *); 2607605SMark.Johnson@Sun.COM void (*file_reset)(ucode_file_t *, processorid_t); 2617605SMark.Johnson@Sun.COM void (*read_rev)(cpu_ucode_info_t *); 2627605SMark.Johnson@Sun.COM uint32_t (*load)(ucode_file_t *, cpu_ucode_info_t *, cpu_t *); 2637605SMark.Johnson@Sun.COM ucode_errno_t (*validate)(uint8_t *, int); 2647605SMark.Johnson@Sun.COM ucode_errno_t (*extract)(ucode_update_t *, uint8_t *, int); 2657605SMark.Johnson@Sun.COM ucode_errno_t (*locate)(cpu_t *, cpu_ucode_info_t *, ucode_file_t *); 2667605SMark.Johnson@Sun.COM }; 2677605SMark.Johnson@Sun.COM #else 2687605SMark.Johnson@Sun.COM 2694581Ssherrym #define UCODE_MAX_VENDORS_NAME_LEN 20 2704581Ssherrym 2714581Ssherrym #define UCODE_VENDORS \ 2724581Ssherrym static struct { \ 2734581Ssherrym char *filestr; \ 2747605SMark.Johnson@Sun.COM char *extstr; \ 2754581Ssherrym char *vendorstr; \ 2764581Ssherrym int supported; \ 2774581Ssherrym } ucode_vendors[] = { \ 2787605SMark.Johnson@Sun.COM { "intel", "txt", "GenuineIntel", 1 }, \ 2797605SMark.Johnson@Sun.COM { "amd", "bin", "AuthenticAMD", 1 }, \ 2807605SMark.Johnson@Sun.COM { NULL, NULL, NULL, 0 } \ 2814581Ssherrym } 2824581Ssherrym 2837605SMark.Johnson@Sun.COM /* 2847605SMark.Johnson@Sun.COM * Microcode user operations 2857605SMark.Johnson@Sun.COM */ 2867605SMark.Johnson@Sun.COM struct ucode_ops { 2877605SMark.Johnson@Sun.COM int (*convert)(const char *, uint8_t *, size_t); 2887605SMark.Johnson@Sun.COM ucode_errno_t (*gen_files)(uint8_t *, int, char *); 2897605SMark.Johnson@Sun.COM ucode_errno_t (*validate)(uint8_t *, int); 2907605SMark.Johnson@Sun.COM }; 2917605SMark.Johnson@Sun.COM #endif 2927605SMark.Johnson@Sun.COM 2937605SMark.Johnson@Sun.COM extern const struct ucode_ops *ucode; 2947605SMark.Johnson@Sun.COM 2954581Ssherrym #ifdef __cplusplus 2964581Ssherrym } 2974581Ssherrym #endif 2984581Ssherrym 2994581Ssherrym #endif /* _SYS_UCODE_H */ 300