1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2024 Oxide Computer Company 14 */ 15 16 #ifndef _AMDZEN_TOPO_H 17 #define _AMDZEN_TOPO_H 18 19 #include "amdzen_client.h" 20 21 /* 22 * This contains the ioctl definitions for allowing and exploring access to the 23 * internal device topology of the Zen CPUs on the system. This ioctl interface 24 * is private and subject to change. 25 */ 26 27 #ifdef __cplusplus 28 extern "C" { 29 #endif 30 31 #define AMDZEN_TOPO_IOCTL (('z' << 24) | ('z' << 16) | ('t' << 8)) 32 33 /* 34 * Get base information about the system's present sockets and the DF 35 * configuration. Our current assumption is that even in a case where we have 36 * heterogeneous DF instances (like some of the DFv3.5 devices), then we'll need 37 * to revisit this structure and move the DF decomposition into the DF 38 * structure. 39 */ 40 #define AMDZEN_TOPO_IOCTL_BASE (AMDZEN_TOPO_IOCTL | 0x00) 41 typedef struct amdzen_topo_base { 42 uint32_t atb_ndf; 43 uint32_t atb_maxdfent; 44 df_rev_t atb_rev; 45 df_fabric_decomp_t atb_df_decomp; 46 amdzen_apic_decomp_t atb_apic_decomp; 47 } amdzen_topo_base_t; 48 49 /* 50 * Get information about a basic instance of the data fabric. If we're in a Zen 51 * 1 / DFv2 style environment, then this is a part of the underlying die. In a 52 * DFv3 (aka Zen 2+) then this represents a relatively coherent set of 53 * resources. Though there are some DFv3.5 parts that theoretically have two 54 * different types of DFs. 55 * 56 * We include all of the entities in the DF here as well. Note, that the types 57 * and subtypes are currently not normalized across DF generations and device 58 * families. 59 */ 60 #define AMDZEN_TOPO_IOCTL_DF (AMDZEN_TOPO_IOCTL | 0x01) 61 62 /* 63 * The current maximum number of peers is derived from the width of the bitfield 64 * in the data fabric. 65 */ 66 #define AMDZEN_TOPO_DF_MAX_PEERS 8 67 68 typedef struct amdzen_topo_ccm_data { 69 uint32_t atcd_nccds; 70 uint32_t atcd_ccd_en[DF_MAX_CCDS_PER_CCM]; 71 uint32_t atcd_ccd_ids[DF_MAX_CCDS_PER_CCM]; 72 } amdzen_topo_ccm_data_t; 73 74 typedef union amdzen_topo_df_data { 75 amdzen_topo_ccm_data_t atded_ccm; 76 } amdzen_topo_df_data_t; 77 78 typedef struct amdzen_topo_df_ent { 79 df_type_t atde_type; 80 uint8_t atde_subtype; 81 uint8_t atde_fabric_id; 82 uint8_t atde_inst_id; 83 uint8_t atde_npeers; 84 uint8_t atde_peers[AMDZEN_TOPO_DF_MAX_PEERS]; 85 amdzen_topo_df_data_t atde_data; 86 } amdzen_topo_df_ent_t; 87 88 typedef struct amdzen_topo_df { 89 /* 90 * Users specify the DF number which is in the range from 0 to the 91 * number of DFs specified in the amdzen_topo_base_t. The nodeid and its 92 * corresponding decomposed socket and die IDs will all be filled in. 93 */ 94 uint32_t atd_dfno; 95 uint32_t atd_nodeid; 96 uint32_t atd_sockid; 97 uint32_t atd_dieid; 98 df_rev_t atd_rev; 99 uint32_t atd_major; 100 uint32_t atd_minor; 101 /* 102 * atd_ndf_buf_nents should be set to the size of the number of DF 103 * entries that are present in atd_df_ents. atd_ndf_buf_valid will 104 * determine the number of entries that are considered valid in the 105 * resulting array. atd_ndf_act_nents is the total number of entries 106 * that are present in the underlying DF. Setting atd_ndf_buf_nents to 107 * atb_maxdfent will ensure that we can obtain everything. 108 */ 109 uint32_t atd_df_buf_nents; 110 uint32_t atd_df_buf_nvalid; 111 uint32_t atd_df_act_nents; 112 amdzen_topo_df_ent_t *atd_df_ents; 113 } amdzen_topo_df_t; 114 115 #ifdef _KERNEL 116 typedef struct { 117 uint32_t atd_dfno; 118 uint32_t atd_nodeid; 119 uint32_t atd_sockid; 120 uint32_t atd_dieid; 121 df_rev_t atd_rev; 122 uint32_t atd_major; 123 uint32_t atd_minor; 124 uint32_t atd_df_buf_nents; 125 uint32_t atd_df_buf_nvalid; 126 uint32_t atd_df_act_nents; 127 caddr32_t atd_df_ents; 128 } amdzen_topo_df32_t; 129 #endif /* _KERNEL */ 130 131 /* 132 * This describes information about what is physically enabled for a given 133 * compute based CCM. This is only known for Zen 3+. Input is the DF number and 134 * the CCM's fabric ID. Information about the resulting CCXs, cores, and their 135 * logical and physical numbers is then returned. All data is sized in terms of 136 * uint32_t's to try and keep the data independent of the model (i.e. ILP32 vs. 137 * LP64). 138 * 139 * Note, the maximum numbers defined below are subject to change and ABI 140 * compatibility is not guaranteed. 141 */ 142 #define AMDZEN_TOPO_IOCTL_CCD (AMDZEN_TOPO_IOCTL | 0x02) 143 144 #define AMDZEN_TOPO_CORE_MAX_THREADS 2 145 #define AMDZEN_TOPO_CCX_MAX_CORES 16 146 #define AMDZEN_TOPO_CCD_MAX_CCX 2 147 148 typedef struct amdzen_topo_core { 149 uint32_t atcore_log_no; 150 uint32_t atcore_phys_no; 151 uint32_t atcore_nthreads; 152 uint32_t atcore_thr_en[AMDZEN_TOPO_CORE_MAX_THREADS]; 153 uint32_t atcore_apicids[AMDZEN_TOPO_CORE_MAX_THREADS]; 154 } amdzen_topo_core_t; 155 156 typedef struct amdzen_topo_ccx { 157 uint32_t atccx_log_no; 158 uint32_t atccx_phys_no; 159 uint32_t atccx_nlog_cores; 160 uint32_t atccx_nphys_cores; 161 uint32_t atccx_core_en[AMDZEN_TOPO_CCX_MAX_CORES]; 162 amdzen_topo_core_t atccx_cores[AMDZEN_TOPO_CCX_MAX_CORES]; 163 } amdzen_topo_ccx_t; 164 165 typedef enum amdzen_topo_ccd_err { 166 AMDZEN_TOPO_CCD_E_OK = 0, 167 /* 168 * Indicates that the system was unable to determine the APIC 169 * decomposition and therefore we do not have mapping information 170 * available. 171 */ 172 AMDZEN_TOPO_CCD_E_NO_APIC_DECOMP, 173 /* 174 * Indicates that this DF number did not map to something that exists. 175 */ 176 AMDZEN_TOPO_CCD_E_BAD_DFNO, 177 /* 178 * Indicates that the current system is unsupported. Generally this is 179 * only the case for Zen 1 / DFv2. 180 */ 181 AMDZEN_TOPO_CCD_E_SOC_UNSUPPORTED, 182 /* 183 * Indicates that the instance ID in question doesn't map to a DF entity 184 * and is invalid. 185 */ 186 AMDZEN_TOPO_CCD_E_BAD_INSTID, 187 /* 188 * Indicates that the named DF element does not actually point to a CCD. 189 */ 190 AMDZEN_TOPO_CCD_E_NOT_A_CCD, 191 /* 192 * Indicates that the specified CCD ID is not known within the given 193 * instance. 194 */ 195 AMDZEN_TOPO_CCD_E_BAD_CCDID, 196 /* 197 * Indicates that the fabric ID does point to a CCD, but we don't 198 * believe it is actually present in the system. This often happens 199 * when a CCM is enabled but there is no CCD. This is the case in many 200 * DFv3 (Zen 2/3) systems. 201 */ 202 AMDZEN_TOPO_CCD_E_CCD_MISSING 203 } amdzen_topo_ccd_err_t; 204 205 /* 206 * The following flags are set to cover our understanding of the output. 207 */ 208 typedef enum amdzen_topo_ccd_flags { 209 /* 210 * Indicates that we don't actually know the mapping of physical to 211 * logical cores in the CCX and therefore we have assumed a 1:1 212 * relationship. 213 */ 214 AMDZEN_TOPO_CCD_F_CORE_PHYS_UNKNOWN = 1 << 0 215 } amdzen_topo_ccd_flags_t; 216 217 typedef struct amdzen_topo_ccd { 218 uint32_t atccd_dfno; 219 uint32_t atccd_instid; 220 uint32_t atccd_phys_no; 221 amdzen_topo_ccd_err_t atccd_err; 222 amdzen_topo_ccd_flags_t atccd_flags; 223 uint32_t atccd_log_no; 224 uint32_t atccd_nlog_ccx; 225 uint32_t atccd_nphys_ccx; 226 uint32_t atccd_ccx_en[AMDZEN_TOPO_CCD_MAX_CCX]; 227 amdzen_topo_ccx_t atccd_ccx[AMDZEN_TOPO_CCD_MAX_CCX]; 228 } amdzen_topo_ccd_t; 229 230 #ifdef __cplusplus 231 } 232 #endif 233 234 #endif /* _AMDZEN_TOPO_H */ 235