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