/* * 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 2023 Oxide Computer Company */ /* * A collection of utility functions for interacting with fabric IDs. */ #include /* * Validate whether a fabric ID actually represents a valid ID for a given data * fabric. */ boolean_t zen_fabric_id_valid_fabid(const df_fabric_decomp_t *decomp, const uint32_t fabid) { uint32_t mask = decomp->dfd_node_mask | decomp->dfd_comp_mask; return ((fabid & ~mask) == 0); } /* * Validate whether the parts of a fabric ID (e.g. the socket, die, and * component) are in fact valid for a given data fabric. */ 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) { uint32_t node; if (((sock << decomp->dfd_sock_shift) & ~decomp->dfd_sock_mask) != 0) { return (B_FALSE); } if (((die << decomp->dfd_die_shift) & ~decomp->dfd_die_mask) != 0) { return (B_FALSE); } if ((comp & ~decomp->dfd_comp_mask) != 0) { return (B_FALSE); } node = die << decomp->dfd_die_shift; node |= sock << decomp->dfd_sock_shift; if (((node << decomp->dfd_node_shift) & ~decomp->dfd_node_mask) != 0) { return (B_FALSE); } return (B_TRUE); } /* * Take apart a fabric ID into its constituent parts. The decomposition * information has the die and socket information relative to the node ID. */ void zen_fabric_id_decompose(const df_fabric_decomp_t *decomp, const uint32_t fabid, uint32_t *sockp, uint32_t *diep, uint32_t *compp) { uint32_t node; ASSERT(zen_fabric_id_valid_fabid(decomp, fabid)); *compp = (fabid & decomp->dfd_comp_mask) >> decomp->dfd_comp_shift; node = (fabid & decomp->dfd_node_mask) >> decomp->dfd_node_shift; *diep = (node & decomp->dfd_die_mask) >> decomp->dfd_die_shift; *sockp = (node & decomp->dfd_sock_mask) >> decomp->dfd_sock_shift; } /* * Compose a fabric ID from its constituent parts: the socket, die, and fabric. */ 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) { uint32_t node; ASSERT(zen_fabric_id_valid_parts(decomp, sock, die, comp)); node = die << decomp->dfd_die_shift; node |= sock << decomp->dfd_sock_shift; *fabidp = (node << decomp->dfd_node_shift) | (comp << decomp->dfd_comp_shift); } #ifdef DEBUG 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) { ASSERT3U(decomp->aad_sock_shift, <, 32); ASSERT3U(decomp->aad_die_shift, <, 32); ASSERT3U(decomp->aad_ccd_shift, <, 32); ASSERT3U(decomp->aad_ccx_shift, <, 32); ASSERT3U(decomp->aad_core_shift, <, 32); ASSERT3U(decomp->aad_thread_shift, <, 32); if (((sock << decomp->aad_sock_shift) & ~decomp->aad_sock_mask) != 0) { return (B_FALSE); } if (((die << decomp->aad_die_shift) & ~decomp->aad_die_mask) != 0) { return (B_FALSE); } if (((ccd << decomp->aad_ccd_shift) & ~decomp->aad_ccd_mask) != 0) { return (B_FALSE); } if (((ccx << decomp->aad_ccx_shift) & ~decomp->aad_ccx_mask) != 0) { return (B_FALSE); } if (((core << decomp->aad_core_shift) & ~decomp->aad_core_mask) != 0) { return (B_FALSE); } if (((thread << decomp->aad_thread_shift) & ~decomp->aad_thread_mask) != 0) { return (B_FALSE); } return (B_TRUE); } #endif /* DEBUG */ /* * Compose an APIC ID from its constituent parts. */ 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) { uint32_t id; ASSERT(zen_apic_id_valid_parts(decomp, sock, die, ccd, ccx, core, thread)); id = thread << decomp->aad_thread_shift; id |= core << decomp->aad_core_shift; id |= ccx << decomp->aad_ccx_shift; id |= ccd << decomp->aad_ccd_shift; id |= die << decomp->aad_die_shift; id |= sock << decomp->aad_sock_shift; *apicid = id; }