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