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 * Copyright 2022 Joyent, Inc. 27 * Copyright 2024 Oxide Computer Company 28 */ 29 30 #ifndef _SYS_UCODE_H 31 #define _SYS_UCODE_H 32 33 #ifdef _KERNEL 34 #include <sys/cpuvar.h> 35 #include <sys/linker_set.h> 36 #endif 37 #include <sys/stdbool.h> 38 #include <sys/types.h> 39 #include <sys/priv.h> 40 #include <sys/processor.h> 41 #include <ucode/ucode_errno.h> 42 43 #ifdef __cplusplus 44 extern "C" { 45 #endif 46 47 /* 48 * /dev/ucode 49 */ 50 #define UCODE_DRIVER_NAME "ucode" 51 #define UCODE_NODE_NAME "ucode" 52 #define UCODE_MINOR ((minor_t)0x3fffful) 53 54 /* 55 * ioctl numbers 56 */ 57 #define UCODE_IOC (('u'<<24)|('c'<<16)|('o'<<8)) 58 59 #define UCODE_GET_VERSION (UCODE_IOC|0) 60 #define UCODE_UPDATE (UCODE_IOC|1) 61 62 struct ucode_get_rev_struct { 63 uint32_t *ugv_rev; /* microcode revision array */ 64 int ugv_size; /* size of the array */ 65 ucode_errno_t ugv_errno; /* EUC error code */ 66 }; 67 68 struct ucode_write_struct { 69 uint32_t uw_size; /* size of the uw_code buffer */ 70 uint8_t *uw_ucode; /* pointer to the undigested microcode */ 71 ucode_errno_t uw_errno; /* EUC error code */ 72 }; 73 74 #if defined(_SYSCALL32_IMPL) 75 76 #include <sys/types32.h> 77 78 struct ucode_get_rev_struct32 { 79 caddr32_t ugv_rev; /* microcode revision array */ 80 int ugv_size; /* size of the array */ 81 ucode_errno_t ugv_errno; /* EUC error code */ 82 }; 83 84 struct ucode_write_struct32 { 85 uint32_t uw_size; /* size of the uw_code buffer */ 86 caddr32_t uw_ucode; /* pointer to the undigested microcode */ 87 ucode_errno_t uw_errno; /* EUC error code */ 88 }; 89 90 #endif /* _SYSCALL32_IMPL */ 91 92 #define UCODE_KB(a) ((a) << 10) /* KiB */ 93 #define UCODE_MB(a) ((a) << 20) /* MiB */ 94 95 /* 96 * For a single microcode file, the following minimum and maximum sizes are 97 * defined. Such limitations, while somewhat artificial, are not only to 98 * provide better sanity checks, but also avoid wasting precious memory at 99 * startup time as the microcode buffer for the first processor has to be 100 * statically allocated. 101 * 102 * The last limit is for the concatenation of all the microcode binary files. 103 */ 104 #define UCODE_MIN_SIZE UCODE_KB(1) 105 #define UCODE_MAX_SIZE UCODE_MB(2) 106 #define UCODE_MAX_COMBINED_SIZE UCODE_MB(16) 107 108 #ifdef _KERNEL 109 110 extern ucode_errno_t ucode_get_rev(uint32_t *); 111 extern ucode_errno_t ucode_validate(uint8_t *, int); 112 extern ucode_errno_t ucode_update(uint8_t *, int); 113 114 /* 115 * Microcode specific information per core 116 */ 117 typedef struct cpu_ucode_info { 118 uint32_t cui_platid; /* platform id */ 119 uint32_t cui_rev; /* microcode revision */ 120 uint32_t cui_pending_rev; /* pending microcode revision */ 121 void *cui_pending_ucode; /* pending microcode update */ 122 size_t cui_pending_size; /* pending microcode size */ 123 } cpu_ucode_info_t; 124 125 /* 126 * Data structure used for xcall 127 */ 128 typedef struct ucode_update { 129 uint32_t sig; /* signature */ 130 cpu_ucode_info_t info; /* ucode info */ 131 uint32_t expected_rev; 132 uint32_t new_rev; 133 uint8_t *ucodep; /* pointer to ucode */ 134 uint32_t usize; 135 } ucode_update_t; 136 137 /* 138 * To register a microcode update method, a ucode_source_t instance should be 139 * created and passed to UCODE_SOURCE() to include it in the list of sources 140 * that are tried. 141 */ 142 typedef struct ucode_source { 143 const char *us_name; 144 uint32_t us_write_msr; 145 bool us_invalidate; 146 bool (*us_select)(cpu_t *); 147 bool (*us_capable)(cpu_t *); 148 void (*us_file_reset)(void); 149 void (*us_read_rev)(cpu_ucode_info_t *); 150 void (*us_load)(cpu_ucode_info_t *); 151 ucode_errno_t (*us_validate)(uint8_t *, int); 152 ucode_errno_t (*us_extract)(ucode_update_t *, uint8_t *, int); 153 ucode_errno_t (*us_locate)(cpu_t *, cpu_ucode_info_t *); 154 } ucode_source_t; 155 #define UCODE_SOURCE(x) DATA_SET(ucode_source_set, x) 156 157 #endif /* _KERNEL */ 158 159 #ifdef __cplusplus 160 } 161 #endif 162 163 #endif /* _SYS_UCODE_H */ 164