xref: /illumos-gate/usr/src/common/amdzen/zen_fabric_utils.c (revision dd23d762c65e503874085a3893fbd3df9688da30)
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 2023 Oxide Computer Company
14  */
15 
16 /*
17  * A collection of utility functions for interacting with fabric IDs.
18  */
19 
20 #include <amdzen_client.h>
21 
22 /*
23  * Validate whether a fabric ID actually represents a valid ID for a given data
24  * fabric.
25  */
26 boolean_t
zen_fabric_id_valid_fabid(const df_fabric_decomp_t * decomp,const uint32_t fabid)27 zen_fabric_id_valid_fabid(const df_fabric_decomp_t *decomp,
28     const uint32_t fabid)
29 {
30 	uint32_t mask = decomp->dfd_node_mask | decomp->dfd_comp_mask;
31 	return ((fabid & ~mask) == 0);
32 }
33 
34 /*
35  * Validate whether the parts of a fabric ID (e.g. the socket, die, and
36  * component) are in fact valid for a given data fabric.
37  */
38 boolean_t
zen_fabric_id_valid_parts(const df_fabric_decomp_t * decomp,const uint32_t sock,const uint32_t die,const uint32_t comp)39 zen_fabric_id_valid_parts(const df_fabric_decomp_t *decomp, const uint32_t sock,
40     const uint32_t die, const uint32_t comp)
41 {
42 	uint32_t node;
43 
44 	if (((sock << decomp->dfd_sock_shift) & ~decomp->dfd_sock_mask) != 0) {
45 		return (B_FALSE);
46 	}
47 	if (((die << decomp->dfd_die_shift) & ~decomp->dfd_die_mask) != 0) {
48 		return (B_FALSE);
49 	}
50 	if ((comp & ~decomp->dfd_comp_mask) != 0) {
51 		return (B_FALSE);
52 	}
53 
54 	node = die << decomp->dfd_die_shift;
55 	node |= sock << decomp->dfd_sock_shift;
56 
57 	if (((node << decomp->dfd_node_shift) & ~decomp->dfd_node_mask) != 0) {
58 		return (B_FALSE);
59 	}
60 
61 	return (B_TRUE);
62 }
63 
64 /*
65  * Take apart a fabric ID into its constituent parts. The decomposition
66  * information has the die and socket information relative to the node ID.
67  */
68 void
zen_fabric_id_decompose(const df_fabric_decomp_t * decomp,const uint32_t fabid,uint32_t * sockp,uint32_t * diep,uint32_t * compp)69 zen_fabric_id_decompose(const df_fabric_decomp_t *decomp, const uint32_t fabid,
70     uint32_t *sockp, uint32_t *diep, uint32_t *compp)
71 {
72 	uint32_t node;
73 
74 	ASSERT(zen_fabric_id_valid_fabid(decomp, fabid));
75 
76 	*compp = (fabid & decomp->dfd_comp_mask) >> decomp->dfd_comp_shift;
77 	node = (fabid & decomp->dfd_node_mask) >> decomp->dfd_node_shift;
78 	*diep = (node & decomp->dfd_die_mask) >> decomp->dfd_die_shift;
79 	*sockp = (node & decomp->dfd_sock_mask) >> decomp->dfd_sock_shift;
80 }
81 
82 /*
83  * Compose a fabric ID from its constituent parts: the socket, die, and fabric.
84  */
85 void
zen_fabric_id_compose(const df_fabric_decomp_t * decomp,const uint32_t sock,const uint32_t die,const uint32_t comp,uint32_t * fabidp)86 zen_fabric_id_compose(const df_fabric_decomp_t *decomp, const uint32_t sock,
87     const uint32_t die, const uint32_t comp, uint32_t *fabidp)
88 {
89 	uint32_t node;
90 
91 	ASSERT(zen_fabric_id_valid_parts(decomp, sock, die, comp));
92 
93 	node = die << decomp->dfd_die_shift;
94 	node |= sock << decomp->dfd_sock_shift;
95 	*fabidp = (node << decomp->dfd_node_shift) |
96 	    (comp << decomp->dfd_comp_shift);
97 }
98 
99 #ifdef	DEBUG
100 static boolean_t
zen_apic_id_valid_parts(const amdzen_apic_decomp_t * decomp,const uint32_t sock,const uint32_t die,const uint32_t ccd,const uint32_t ccx,const uint32_t core,const uint32_t thread)101 zen_apic_id_valid_parts(const amdzen_apic_decomp_t *decomp, const uint32_t sock,
102     const uint32_t die, const uint32_t ccd, const uint32_t ccx,
103     const uint32_t core, const uint32_t thread)
104 {
105 	ASSERT3U(decomp->aad_sock_shift, <, 32);
106 	ASSERT3U(decomp->aad_die_shift, <, 32);
107 	ASSERT3U(decomp->aad_ccd_shift, <, 32);
108 	ASSERT3U(decomp->aad_ccx_shift, <, 32);
109 	ASSERT3U(decomp->aad_core_shift, <, 32);
110 	ASSERT3U(decomp->aad_thread_shift, <, 32);
111 
112 	if (((sock << decomp->aad_sock_shift) & ~decomp->aad_sock_mask) != 0) {
113 		return (B_FALSE);
114 	}
115 
116 	if (((die << decomp->aad_die_shift) & ~decomp->aad_die_mask) != 0) {
117 		return (B_FALSE);
118 	}
119 
120 	if (((ccd << decomp->aad_ccd_shift) & ~decomp->aad_ccd_mask) != 0) {
121 		return (B_FALSE);
122 	}
123 
124 	if (((ccx << decomp->aad_ccx_shift) & ~decomp->aad_ccx_mask) != 0) {
125 		return (B_FALSE);
126 	}
127 
128 	if (((core << decomp->aad_core_shift) & ~decomp->aad_core_mask) != 0) {
129 		return (B_FALSE);
130 	}
131 
132 	if (((thread << decomp->aad_thread_shift) &
133 	    ~decomp->aad_thread_mask) != 0) {
134 		return (B_FALSE);
135 	}
136 	return (B_TRUE);
137 }
138 #endif	/* DEBUG */
139 
140 /*
141  * Compose an APIC ID from its constituent parts.
142  */
143 void
zen_apic_id_compose(const amdzen_apic_decomp_t * decomp,const uint32_t sock,const uint32_t die,const uint32_t ccd,const uint32_t ccx,const uint32_t core,const uint32_t thread,uint32_t * apicid)144 zen_apic_id_compose(const amdzen_apic_decomp_t *decomp, const uint32_t sock,
145     const uint32_t die, const uint32_t ccd, const uint32_t ccx,
146     const uint32_t core, const uint32_t thread, uint32_t *apicid)
147 {
148 	uint32_t id;
149 
150 	ASSERT(zen_apic_id_valid_parts(decomp, sock, die, ccd, ccx, core,
151 	    thread));
152 	id = thread << decomp->aad_thread_shift;
153 	id |= core << decomp->aad_core_shift;
154 	id |= ccx << decomp->aad_ccx_shift;
155 	id |= ccd << decomp->aad_ccd_shift;
156 	id |= die << decomp->aad_die_shift;
157 	id |= sock << decomp->aad_sock_shift;
158 
159 	*apicid = id;
160 }
161