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