1 1.8 thorpej /* $NetBSD: cpunode.c,v 1.8 2021/08/07 16:19:02 thorpej Exp $ */ 2 1.2 matt /*- 3 1.2 matt * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc. 4 1.2 matt * All rights reserved. 5 1.2 matt * 6 1.2 matt * This code is derived from software contributed to The NetBSD Foundation 7 1.2 matt * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects 8 1.2 matt * Agency and which was developed by Matt Thomas of 3am Software Foundry. 9 1.2 matt * 10 1.2 matt * This material is based upon work supported by the Defense Advanced Research 11 1.2 matt * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under 12 1.2 matt * Contract No. N66001-09-C-2073. 13 1.2 matt * Approved for Public Release, Distribution Unlimited 14 1.2 matt * 15 1.2 matt * Redistribution and use in source and binary forms, with or without 16 1.2 matt * modification, are permitted provided that the following conditions 17 1.2 matt * are met: 18 1.2 matt * 1. Redistributions of source code must retain the above copyright 19 1.2 matt * notice, this list of conditions and the following disclaimer. 20 1.2 matt * 2. Redistributions in binary form must reproduce the above copyright 21 1.2 matt * notice, this list of conditions and the following disclaimer in the 22 1.2 matt * documentation and/or other materials provided with the distribution. 23 1.2 matt * 24 1.2 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 25 1.2 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 1.2 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 1.2 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 28 1.2 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 1.2 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 1.2 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 1.2 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 1.2 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 1.2 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 1.2 matt * POSSIBILITY OF SUCH DAMAGE. 35 1.2 matt */ 36 1.2 matt 37 1.2 matt #include <sys/cdefs.h> 38 1.8 thorpej __KERNEL_RCSID(0, "$NetBSD: cpunode.c,v 1.8 2021/08/07 16:19:02 thorpej Exp $"); 39 1.2 matt 40 1.6 rin #include "ioconf.h" 41 1.2 matt 42 1.2 matt #include <sys/param.h> 43 1.2 matt #include <sys/device.h> 44 1.2 matt #include <sys/cpu.h> 45 1.2 matt 46 1.2 matt #include <powerpc/booke/cpuvar.h> 47 1.2 matt 48 1.2 matt static int cpunode_match(device_t, cfdata_t, void *); 49 1.2 matt static void cpunode_attach(device_t, device_t, void *); 50 1.2 matt 51 1.2 matt CFATTACH_DECL_NEW(cpunode, sizeof(struct cpunode_softc), 52 1.2 matt cpunode_match, cpunode_attach, NULL, NULL); 53 1.2 matt 54 1.2 matt static u_int nodes; 55 1.2 matt 56 1.2 matt static int 57 1.2 matt cpunode_match(device_t parent, cfdata_t cf, void *aux) 58 1.2 matt { 59 1.2 matt struct mainbus_attach_args * const ma = aux; 60 1.2 matt if (strcmp(ma->ma_name, cpunode_cd.cd_name) != 0) 61 1.2 matt return 0; 62 1.2 matt 63 1.2 matt if (ma->ma_node > 8 || (nodes & (1 << ma->ma_node))) 64 1.2 matt return 0; 65 1.2 matt 66 1.2 matt return 1; 67 1.2 matt } 68 1.2 matt 69 1.2 matt static int 70 1.2 matt cpunode_print(void *aux, const char *pnp) 71 1.2 matt { 72 1.2 matt struct cpunode_attach_args *cna = aux; 73 1.2 matt 74 1.2 matt if (pnp) 75 1.2 matt #if 0 76 1.2 matt return QUIET; 77 1.2 matt #else 78 1.2 matt aprint_normal("%s at %s", cna->cna_locs.cnl_name, pnp); 79 1.2 matt #endif 80 1.2 matt 81 1.2 matt if (cna->cna_locs.cnl_instance != 0) 82 1.2 matt aprint_normal(" instance %d", cna->cna_locs.cnl_instance); 83 1.2 matt 84 1.2 matt return UNCONF; 85 1.2 matt } 86 1.2 matt 87 1.2 matt static void 88 1.2 matt cpunode_attach(device_t parent, device_t self, void *aux) 89 1.2 matt { 90 1.2 matt const struct cpunode_locators *cnl = cpu_md_ops.md_cpunode_locs; 91 1.2 matt struct cpunode_softc * const sc = device_private(self); 92 1.2 matt struct mainbus_attach_args * const ma = aux; 93 1.2 matt struct cpunode_attach_args cna; 94 1.2 matt 95 1.2 matt sc->sc_dev = self; 96 1.2 matt 97 1.2 matt aprint_normal("\n"); 98 1.2 matt aprint_normal_dev(self, 99 1.2 matt "%"PRIu64"KB/%"PRIu64"B %"PRIu64"-banked %"PRIu64"-way unified L2 cache\n", 100 1.2 matt board_info_get_number("l2-cache-size") / 1024, 101 1.2 matt board_info_get_number("l2-cache-line-size"), 102 1.2 matt board_info_get_number("l2-cache-banks"), 103 1.2 matt board_info_get_number("l2-cache-ways")); 104 1.2 matt 105 1.2 matt nodes |= 1 << ma->ma_node; 106 1.2 matt 107 1.3 matt const uint16_t my_id = board_info_get_number("my-id"); 108 1.3 matt 109 1.3 matt for (u_int childmask = 1; cnl->cnl_name != NULL; cnl++) { 110 1.3 matt bool inclusive = true; 111 1.3 matt bool found = (cnl->cnl_ids[0] == 0); 112 1.5 matt 113 1.5 matt #if DEBUG > 1 114 1.5 matt aprint_normal_dev(self, "dev=%s[%u], addr=%x@%x", 115 1.5 matt cnl->cnl_name, cnl->cnl_instance, cnl->cnl_size, 116 1.5 matt cnl->cnl_addr); 117 1.5 matt if (cnl->cnl_nintr > 0) { 118 1.5 matt aprint_normal(", intrs=%u", cnl->cnl_intrs[0]); 119 1.5 matt for (u_int i = 1; i < cnl->cnl_nintr; i++) 120 1.5 matt aprint_normal(",%u", cnl->cnl_intrs[i]); 121 1.5 matt } 122 1.5 matt aprint_normal("\n"); 123 1.5 matt #endif 124 1.5 matt 125 1.3 matt for (u_int i = 0; 126 1.3 matt !found 127 1.3 matt && i < __arraycount(cnl->cnl_ids) 128 1.3 matt && cnl->cnl_ids[i] != 0; 129 1.3 matt i++) { 130 1.3 matt if (cnl->cnl_ids[i] == 0xffff) { 131 1.3 matt inclusive = false; 132 1.3 matt continue; 133 1.3 matt } 134 1.3 matt found = (cnl->cnl_ids[i] == my_id); 135 1.3 matt } 136 1.3 matt /* 137 1.3 matt * found & inclusive == match 138 1.3 matt * !found & !inclusive == match 139 1.3 matt * found & !inclusive == no match 140 1.3 matt * !found & inclusive == no match 141 1.3 matt * therefore 142 1.3 matt * found ^ inclusive = no match 143 1.3 matt * so 144 1.3 matt * !(found ^ inclusive) = match 145 1.3 matt */ 146 1.3 matt if (found ^ inclusive) 147 1.3 matt continue; 148 1.3 matt 149 1.2 matt cna.cna_busname = "cpunode"; 150 1.2 matt cna.cna_memt = ma->ma_memt; 151 1.4 matt cna.cna_le_memt = ma->ma_le_memt; 152 1.2 matt cna.cna_dmat = ma->ma_dmat; 153 1.2 matt cna.cna_childmask = childmask; 154 1.2 matt cna.cna_locs = *cnl; 155 1.2 matt 156 1.7 thorpej config_found(self, &cna, cpunode_print, 157 1.8 thorpej CFARGS(.iattr = "cpunode")); 158 1.3 matt childmask <<= 1; 159 1.2 matt } 160 1.2 matt /* 161 1.2 matt * Anything MD left to do? 162 1.2 matt */ 163 1.2 matt if (cpu_md_ops.md_cpunode_attach != NULL) 164 1.2 matt (*cpu_md_ops.md_cpunode_attach)(parent, self, aux); 165 1.2 matt } 166 1.2 matt 167 1.2 matt static int cpu_match(device_t, cfdata_t, void *); 168 1.2 matt static void cpu_attach(device_t, device_t, void *); 169 1.2 matt 170 1.2 matt CFATTACH_DECL_NEW(cpu, 0, 171 1.2 matt cpu_match, cpu_attach, NULL, NULL); 172 1.2 matt 173 1.2 matt static int 174 1.2 matt cpu_match(device_t parent, cfdata_t cf, void *aux) 175 1.2 matt { 176 1.2 matt struct cpunode_softc * const psc = device_private(parent); 177 1.2 matt struct cpunode_attach_args * const cna = aux; 178 1.2 matt 179 1.2 matt if (strcmp(cna->cna_locs.cnl_name, cpu_cd.cd_name) != 0) 180 1.2 matt return 0; 181 1.2 matt 182 1.2 matt if (psc->sc_children & cna->cna_childmask) 183 1.2 matt return 0; 184 1.2 matt 185 1.2 matt return 1; 186 1.2 matt } 187 1.2 matt 188 1.2 matt static void 189 1.2 matt cpu_attach(device_t parent, device_t self, void *aux) 190 1.2 matt { 191 1.2 matt struct cpunode_softc * const psc = device_private(parent); 192 1.2 matt struct cpunode_attach_args * const cna = aux; 193 1.2 matt 194 1.2 matt psc->sc_children |= cna->cna_childmask; 195 1.2 matt 196 1.2 matt aprint_normal("\n"); 197 1.2 matt 198 1.2 matt (*cpu_md_ops.md_cpu_attach)(self, cna->cna_locs.cnl_instance); 199 1.2 matt } 200