1 /* $NetBSD: mainbus.c,v 1.7 2021/08/07 16:19:08 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2018 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 31 __KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.7 2021/08/07 16:19:08 thorpej Exp $"); 32 33 #include "opt_acpi.h" 34 #include "opt_mpbios.h" 35 #include "opt_pcifixup.h" 36 #include "opt_pci.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/device.h> 41 #include <sys/reboot.h> 42 43 #include <machine/cpuvar.h> 44 #include <machine/mpbiosvar.h> 45 #include <machine/mpacpi.h> 46 #include <xen/hypervisor.h> 47 48 #include "pci.h" 49 #include "isa.h" 50 #include "isadma.h" 51 #include "acpica.h" 52 #include "ipmi.h" 53 54 #if NACPICA > 0 55 #include <dev/acpi/acpivar.h> 56 #endif 57 58 #include <x86/autoconf.h> 59 60 #if NIPMI > 0 61 #include <x86/ipmivar.h> 62 #endif 63 64 #if NPCI > 0 65 #include <dev/pci/pcivar.h> 66 #if defined(PCI_BUS_FIXUP) 67 #include <arch/x86/pci/pci_bus_fixup.h> 68 #if defined(PCI_ADDR_FIXUP) 69 #include <arch/x86/pci/pci_addr_fixup.h> 70 #endif 71 #endif 72 #ifdef __HAVE_PCI_MSI_MSIX 73 #include <arch/x86/pci/msipic.h> 74 #endif /* __HAVE_PCI_MSI_MSIX */ 75 #endif 76 77 bool acpi_present = false; 78 bool mpacpi_active = false; 79 80 int mainbus_rescan(device_t, const char *, const int *); 81 void mainbus_childdetached(device_t, device_t); 82 void mainbus_attach(device_t, device_t, void *); 83 int mainbus_match(device_t, cfdata_t, void *); 84 85 CFATTACH_DECL2_NEW(mainbus, sizeof(struct mainbus_softc), 86 mainbus_match, mainbus_attach, 87 NULL, NULL, 88 mainbus_rescan, mainbus_childdetached); 89 90 #if defined(__i386__) && !defined(XENPV) 91 void i386_mainbus_childdetached(device_t, device_t); 92 int i386_mainbus_rescan(device_t, const char *, const int *); 93 void i386_mainbus_attach(device_t, device_t, void *); 94 #endif 95 96 #if defined(__x86_64__) && !defined(XENPV) 97 void amd64_mainbus_attach(device_t, device_t, void *); 98 #endif 99 100 static int 101 mainbus_cpu_print(void *aux, const char *busname) 102 { 103 char *cpuname = aux; 104 105 if (busname) 106 aprint_normal("%s at %s", cpuname, busname); 107 return UNCONF; 108 } 109 110 /* 111 * On x86, CPUs can be enumerated and attached to mainbus in mainly two ways 112 * depending on the platform (configuration): via MP BIOS tables, and via 113 * ACPI tables. 114 * 115 * Since CPUs are not an optional part of computers, this attachment is made 116 * common across all x86 architectures and modes, and thus hard-coded into 117 * the boot path, with the exception of XEN PV domU. 118 * 119 * Along with CPUs, APICs come in various shapes and forms, and to accommodate 120 * for the configurable ioapic topology, the "ioapicbus" is also enumerated 121 * here as part of the mpbios/mpacpi probe path. 122 * 123 * All other busses are attached variously depending on the platform 124 * architecture and config(5). 125 * 126 * These configurations and attach orderings for various platforms are 127 * currently respectively driven in the functions: 128 * 129 * i386_mainbus_attach(); 130 * amd64_mainbus_attach(); 131 * xen_mainbus_attach(); 132 * 133 * This arrangement gives us the flexibility to do things such as dynamic 134 * attach path traversal at boot time, depending on the "mode" of operation, 135 * ie: virtualition aware or native. 136 * 137 * For (a contrived) eg: XEN PVHVM would allow us to attach pci(9) either via 138 * hypervisorbus or mainbus depending on if the kernel is running under the 139 * hypervisor or not. 140 */ 141 142 static void 143 x86_cpubus_attach(device_t self) 144 { 145 int numcpus = 0; 146 147 #if NPCI > 0 148 149 #ifdef __HAVE_PCI_MSI_MSIX 150 msipic_init(); 151 #endif 152 153 /* 154 * ACPI needs to be able to access PCI configuration space. 155 */ 156 pci_mode_detect(); 157 #if defined(PCI_BUS_FIXUP) 158 int pci_maxbus = 0; 159 160 if (pci_mode_detect() != 0) { 161 pci_maxbus = pci_bus_fixup(NULL, 0); 162 aprint_debug("PCI bus max, after pci_bus_fixup: %i\n", 163 pci_maxbus); 164 #if defined(PCI_ADDR_FIXUP) 165 pciaddr.extent_port = NULL; 166 pciaddr.extent_mem = NULL; 167 pci_addr_fixup(NULL, pci_maxbus); 168 #endif 169 } 170 #endif 171 #endif /* NPCI */ 172 173 #if NACPICA > 0 174 if ((boothowto & RB_MD2) == 0 && acpi_check(self, "acpibus")) 175 acpi_present = acpi_probe() != 0; 176 /* 177 * First, see if the MADT contains CPUs, and possibly I/O APICs. 178 * Building the interrupt routing structures can only 179 * be done later (via a callback). 180 */ 181 if (acpi_present) 182 mpacpi_active = mpacpi_scan_apics(self, &numcpus) != 0; 183 184 if (!mpacpi_active) { 185 #endif 186 #ifdef MPBIOS 187 if (mpbios_probe(self)) 188 mpbios_scan(self, &numcpus); 189 else 190 #endif 191 if (numcpus == 0) { 192 struct cpu_attach_args caa; 193 194 memset(&caa, 0, sizeof(caa)); 195 caa.cpu_number = 0; 196 caa.cpu_role = CPU_ROLE_SP; 197 caa.cpu_func = 0; 198 199 config_found(self, &caa, mainbus_cpu_print, 200 CFARGS(.iattr = "cpubus")); 201 } 202 #if NACPICA > 0 203 } 204 #endif 205 } 206 207 int 208 mainbus_match(device_t parent, cfdata_t match, void *aux) 209 { 210 211 return 1; 212 } 213 214 void 215 mainbus_attach(device_t parent, device_t self, void *aux) 216 { 217 218 aprint_naive("\n"); 219 aprint_normal("\n"); 220 221 #if defined(XENPVHVM) 222 xen_hvm_init(); /* before attaching CPUs */ 223 #endif 224 225 #if defined(XENPV) 226 if (xendomain_is_dom0()) { 227 #endif /* XENPV */ 228 x86_cpubus_attach(self); 229 230 #if defined(XENPV) 231 } 232 #endif /* XENPV */ 233 #if defined(XEN) 234 /* 235 * before isa/pci probe, so that PV devices are not probed again 236 * as emulated 237 */ 238 xen_mainbus_attach(parent, self, aux); 239 #endif 240 #if defined(__i386__) && !defined(XENPV) 241 i386_mainbus_attach(parent, self, aux); 242 #elif defined(__x86_64__) && !defined(XENPV) 243 amd64_mainbus_attach(parent, self, aux); 244 #endif 245 } 246 247 int 248 mainbus_rescan(device_t self, const char *ifattr, const int *locators) 249 { 250 #if defined(__i386__) && !defined(XEN) 251 return i386_mainbus_rescan(self, ifattr, locators); 252 #endif 253 return ENOTTY; /* Inappropriate ioctl for this device */ 254 } 255 256 void 257 mainbus_childdetached(device_t self, device_t child) 258 { 259 #if defined(__i386__) && !defined(XEN) 260 i386_mainbus_childdetached(self, child); 261 #endif 262 } 263 264