1 1.39 imil /* $NetBSD: acpi_machdep.c,v 1.39 2025/04/30 05:15:07 imil Exp $ */ 2 1.1 jruoho 3 1.1 jruoho /* 4 1.1 jruoho * Copyright 2001 Wasabi Systems, Inc. 5 1.1 jruoho * All rights reserved. 6 1.1 jruoho * 7 1.1 jruoho * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 1.1 jruoho * 9 1.1 jruoho * Redistribution and use in source and binary forms, with or without 10 1.1 jruoho * modification, are permitted provided that the following conditions 11 1.1 jruoho * are met: 12 1.1 jruoho * 1. Redistributions of source code must retain the above copyright 13 1.1 jruoho * notice, this list of conditions and the following disclaimer. 14 1.1 jruoho * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 jruoho * notice, this list of conditions and the following disclaimer in the 16 1.1 jruoho * documentation and/or other materials provided with the distribution. 17 1.1 jruoho * 3. All advertising materials mentioning features or use of this software 18 1.1 jruoho * must display the following acknowledgement: 19 1.1 jruoho * This product includes software developed for the NetBSD Project by 20 1.1 jruoho * Wasabi Systems, Inc. 21 1.1 jruoho * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 1.1 jruoho * or promote products derived from this software without specific prior 23 1.1 jruoho * written permission. 24 1.1 jruoho * 25 1.1 jruoho * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 1.1 jruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 jruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 jruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 1.1 jruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 jruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 jruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 jruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 jruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 jruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 jruoho * POSSIBILITY OF SUCH DAMAGE. 36 1.1 jruoho */ 37 1.1 jruoho 38 1.1 jruoho /* 39 1.1 jruoho * Machine-dependent routines for ACPICA. 40 1.1 jruoho */ 41 1.1 jruoho 42 1.1 jruoho #include <sys/cdefs.h> 43 1.39 imil __KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.39 2025/04/30 05:15:07 imil Exp $"); 44 1.1 jruoho 45 1.1 jruoho #include <sys/param.h> 46 1.1 jruoho #include <sys/systm.h> 47 1.2 dyoung #include <sys/bus.h> 48 1.3 rmind #include <sys/cpu.h> 49 1.1 jruoho #include <sys/device.h> 50 1.1 jruoho 51 1.1 jruoho #include <uvm/uvm_extern.h> 52 1.1 jruoho 53 1.1 jruoho #include <machine/cpufunc.h> 54 1.9 msaitoh #include <machine/bootinfo.h> 55 1.13 jmcneill #include <machine/autoconf.h> 56 1.1 jruoho 57 1.1 jruoho #include <dev/acpi/acpica.h> 58 1.1 jruoho #include <dev/acpi/acpivar.h> 59 1.9 msaitoh #include <dev/acpi/acpi_mcfg.h> 60 1.1 jruoho 61 1.1 jruoho #include <machine/acpi_machdep.h> 62 1.1 jruoho #include <machine/mpbiosvar.h> 63 1.1 jruoho #include <machine/mpacpi.h> 64 1.1 jruoho #include <machine/i82093reg.h> 65 1.1 jruoho #include <machine/i82093var.h> 66 1.1 jruoho #include <machine/pic.h> 67 1.33 riastrad #include <machine/pmap_private.h> 68 1.1 jruoho 69 1.11 christos #include <x86/efi.h> 70 1.11 christos 71 1.1 jruoho #include <dev/pci/pcivar.h> 72 1.1 jruoho 73 1.1 jruoho #include <dev/isa/isareg.h> 74 1.1 jruoho #include <dev/isa/isavar.h> 75 1.36 bouyer #include <arch/x86/include/genfb_machdep.h> 76 1.1 jruoho 77 1.1 jruoho #include "ioapic.h" 78 1.1 jruoho 79 1.1 jruoho #include "acpica.h" 80 1.1 jruoho #include "opt_mpbios.h" 81 1.1 jruoho #include "opt_acpi.h" 82 1.13 jmcneill #include "opt_vga.h" 83 1.13 jmcneill 84 1.30 bouyer #ifdef XEN 85 1.30 bouyer #include <xen/hypervisor.h> 86 1.30 bouyer #endif 87 1.30 bouyer 88 1.13 jmcneill /* 89 1.13 jmcneill * Default VBIOS reset method for non-HW accelerated VGA drivers. 90 1.13 jmcneill */ 91 1.13 jmcneill #ifdef VGA_POST 92 1.13 jmcneill # define VBIOS_RESET_DEFAULT 2 93 1.13 jmcneill #else 94 1.13 jmcneill # define VBIOS_RESET_DEFAULT 1 95 1.13 jmcneill #endif 96 1.1 jruoho 97 1.1 jruoho ACPI_STATUS 98 1.1 jruoho acpi_md_OsInitialize(void) 99 1.1 jruoho { 100 1.1 jruoho return AE_OK; 101 1.1 jruoho } 102 1.1 jruoho 103 1.1 jruoho ACPI_PHYSICAL_ADDRESS 104 1.1 jruoho acpi_md_OsGetRootPointer(void) 105 1.1 jruoho { 106 1.1 jruoho ACPI_PHYSICAL_ADDRESS PhysicalAddress; 107 1.1 jruoho ACPI_STATUS Status; 108 1.1 jruoho 109 1.27 manu #ifdef XENPV 110 1.27 manu /* 111 1.35 riastrad * Obtain the ACPI RSDP from the hypervisor. 112 1.35 riastrad * This is the only way to go if Xen booted from EFI: the 113 1.35 riastrad * Extended BIOS Data Area (EBDA) is not mapped, and Xen 114 1.27 manu * does not pass an EFI SystemTable to the kernel. 115 1.27 manu */ 116 1.27 manu struct xen_platform_op op = { 117 1.27 manu .cmd = XENPF_firmware_info, 118 1.27 manu .u.firmware_info = { 119 1.35 riastrad .type = XEN_FW_EFI_INFO, 120 1.27 manu .index = XEN_FW_EFI_CONFIG_TABLE 121 1.27 manu } 122 1.27 manu }; 123 1.27 manu union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info; 124 1.27 manu 125 1.27 manu if (HYPERVISOR_platform_op(&op) == 0) { 126 1.27 manu struct efi_cfgtbl *ct; 127 1.27 manu int i; 128 1.27 manu 129 1.35 riastrad ct = AcpiOsMapMemory(info->cfg.addr, 130 1.27 manu sizeof(*ct) * info->cfg.nent); 131 1.27 manu 132 1.27 manu for (i = 0; i < info->cfg.nent; i++) { 133 1.27 manu if (memcmp(&ct[i].ct_uuid, 134 1.27 manu &EFI_UUID_ACPI20, sizeof(EFI_UUID_ACPI20)) == 0) { 135 1.28 martin PhysicalAddress = (ACPI_PHYSICAL_ADDRESS) 136 1.28 martin (uintptr_t)ct[i].ct_data; 137 1.27 manu if (PhysicalAddress) 138 1.27 manu goto out; 139 1.35 riastrad 140 1.27 manu } 141 1.27 manu } 142 1.27 manu 143 1.27 manu for (i = 0; i < info->cfg.nent; i++) { 144 1.27 manu if (memcmp(&ct[i].ct_uuid, 145 1.27 manu &EFI_UUID_ACPI10, sizeof(EFI_UUID_ACPI10)) == 0) { 146 1.28 martin PhysicalAddress = (ACPI_PHYSICAL_ADDRESS) 147 1.28 martin (uintptr_t)ct[i].ct_data; 148 1.27 manu if (PhysicalAddress) 149 1.27 manu goto out; 150 1.35 riastrad 151 1.27 manu } 152 1.27 manu } 153 1.27 manu out: 154 1.27 manu AcpiOsUnmapMemory(ct, sizeof(*ct) * info->cfg.nent); 155 1.27 manu 156 1.27 manu if (PhysicalAddress) 157 1.27 manu return PhysicalAddress; 158 1.27 manu } 159 1.27 manu #else 160 1.30 bouyer #ifdef XEN 161 1.39 imil if (pvh_boot) { 162 1.30 bouyer PhysicalAddress = hvm_start_info->rsdp_paddr; 163 1.30 bouyer if (PhysicalAddress) 164 1.30 bouyer return PhysicalAddress; 165 1.30 bouyer } 166 1.30 bouyer #endif 167 1.35 riastrad /* 168 1.35 riastrad * Get the ACPI RSDP from EFI SystemTable. This works when the 169 1.27 manu * kernel was loaded from EFI bootloader. 170 1.27 manu */ 171 1.11 christos if (efi_probe()) { 172 1.11 christos PhysicalAddress = efi_getcfgtblpa(&EFI_UUID_ACPI20); 173 1.11 christos if (!PhysicalAddress) 174 1.11 christos PhysicalAddress = efi_getcfgtblpa(&EFI_UUID_ACPI10); 175 1.11 christos if (PhysicalAddress) 176 1.11 christos return PhysicalAddress; 177 1.11 christos } 178 1.11 christos 179 1.12 htodd #endif 180 1.27 manu /* 181 1.27 manu * Find ACPI RSDP from Extended BIOS Data Area (EBDA). This 182 1.27 manu * works when the kernel was started from BIOS bootloader, 183 1.27 manu * or for Xen PV when Xen was started from BIOS bootloader. 184 1.27 manu */ 185 1.1 jruoho Status = AcpiFindRootPointer(&PhysicalAddress); 186 1.1 jruoho if (ACPI_FAILURE(Status)) 187 1.1 jruoho PhysicalAddress = 0; 188 1.1 jruoho 189 1.1 jruoho return PhysicalAddress; 190 1.1 jruoho } 191 1.1 jruoho 192 1.5 chs struct acpi_md_override { 193 1.5 chs int irq; 194 1.5 chs int pin; 195 1.5 chs int flags; 196 1.5 chs }; 197 1.5 chs 198 1.8 joerg #if NIOAPIC > 0 199 1.5 chs static ACPI_STATUS 200 1.5 chs acpi_md_findoverride(ACPI_SUBTABLE_HEADER *hdrp, void *aux) 201 1.5 chs { 202 1.5 chs ACPI_MADT_INTERRUPT_OVERRIDE *iop; 203 1.5 chs struct acpi_md_override *ovrp; 204 1.5 chs 205 1.5 chs if (hdrp->Type != ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) { 206 1.5 chs return AE_OK; 207 1.5 chs } 208 1.5 chs 209 1.5 chs iop = (void *)hdrp; 210 1.5 chs ovrp = aux; 211 1.5 chs if (iop->SourceIrq == ovrp->irq) { 212 1.5 chs ovrp->pin = iop->GlobalIrq; 213 1.5 chs ovrp->flags = iop->IntiFlags; 214 1.5 chs } 215 1.5 chs return AE_OK; 216 1.5 chs } 217 1.8 joerg #endif 218 1.5 chs 219 1.1 jruoho ACPI_STATUS 220 1.1 jruoho acpi_md_OsInstallInterruptHandler(uint32_t InterruptNumber, 221 1.19 bouyer ACPI_OSD_HANDLER ServiceRoutine, void *Context, void **cookiep, 222 1.19 bouyer const char *xname) 223 1.1 jruoho { 224 1.1 jruoho void *ih; 225 1.21 jmcneill 226 1.21 jmcneill ih = acpi_md_intr_establish(InterruptNumber, IPL_TTY, IST_LEVEL, 227 1.34 riastrad (int (*)(void *))ServiceRoutine, Context, /*mpsafe*/true, xname); 228 1.21 jmcneill if (ih == NULL) 229 1.21 jmcneill return AE_NO_MEMORY; 230 1.21 jmcneill 231 1.21 jmcneill *cookiep = ih; 232 1.21 jmcneill 233 1.21 jmcneill return AE_OK; 234 1.21 jmcneill } 235 1.21 jmcneill 236 1.21 jmcneill void 237 1.21 jmcneill acpi_md_OsRemoveInterruptHandler(void *cookie) 238 1.21 jmcneill { 239 1.21 jmcneill intr_disestablish(cookie); 240 1.21 jmcneill } 241 1.21 jmcneill 242 1.21 jmcneill void * 243 1.21 jmcneill acpi_md_intr_establish(uint32_t InterruptNumber, int ipl, int type, 244 1.21 jmcneill int (*handler)(void *), void *arg, bool mpsafe, const char *xname) 245 1.21 jmcneill { 246 1.21 jmcneill void *ih; 247 1.1 jruoho struct pic *pic; 248 1.26 mlelstv int irq = InterruptNumber, pin; 249 1.1 jruoho #if NIOAPIC > 0 250 1.26 mlelstv struct ioapic_softc *ioapic; 251 1.5 chs struct acpi_md_override ovr; 252 1.5 chs struct mp_intr_map tmpmap, *mip, **mipp = NULL; 253 1.26 mlelstv intr_handle_t mpih; 254 1.25 kre int redir, mpflags; 255 1.5 chs 256 1.5 chs /* 257 1.5 chs * ACPI interrupts default to level-triggered active-low. 258 1.5 chs */ 259 1.5 chs 260 1.5 chs mpflags = (MPS_INTTR_LEVEL << 2) | MPS_INTPO_ACTLO; 261 1.5 chs redir = IOAPIC_REDLO_LEVEL | IOAPIC_REDLO_ACTLO; 262 1.1 jruoho 263 1.1 jruoho /* 264 1.5 chs * Apply any MADT override setting. 265 1.1 jruoho */ 266 1.5 chs 267 1.26 mlelstv ovr.irq = irq; 268 1.5 chs ovr.pin = -1; 269 1.5 chs if (acpi_madt_map() == AE_OK) { 270 1.5 chs acpi_madt_walk(acpi_md_findoverride, &ovr); 271 1.5 chs acpi_madt_unmap(); 272 1.5 chs } else { 273 1.5 chs aprint_debug("acpi_madt_map() failed, can't check for MADT override\n"); 274 1.5 chs } 275 1.5 chs 276 1.5 chs if (ovr.pin != -1) { 277 1.26 mlelstv bool sci = irq == AcpiGbl_FADT.SciInterrupt; 278 1.5 chs int polarity = ovr.flags & ACPI_MADT_POLARITY_MASK; 279 1.5 chs int trigger = ovr.flags & ACPI_MADT_TRIGGER_MASK; 280 1.5 chs 281 1.26 mlelstv irq = ovr.pin; 282 1.5 chs if (polarity == ACPI_MADT_POLARITY_ACTIVE_HIGH || 283 1.5 chs (!sci && polarity == ACPI_MADT_POLARITY_CONFORMS)) { 284 1.5 chs mpflags &= ~MPS_INTPO_ACTLO; 285 1.6 chs mpflags |= MPS_INTPO_ACTHI; 286 1.5 chs redir &= ~IOAPIC_REDLO_ACTLO; 287 1.5 chs } 288 1.5 chs if (trigger == ACPI_MADT_TRIGGER_EDGE || 289 1.5 chs (!sci && trigger == ACPI_MADT_TRIGGER_CONFORMS)) { 290 1.5 chs type = IST_EDGE; 291 1.5 chs mpflags &= ~(MPS_INTTR_LEVEL << 2); 292 1.6 chs mpflags |= (MPS_INTTR_EDGE << 2); 293 1.5 chs redir &= ~IOAPIC_REDLO_LEVEL; 294 1.5 chs } 295 1.1 jruoho } 296 1.1 jruoho 297 1.26 mlelstv pic = NULL; 298 1.26 mlelstv pin = irq; 299 1.26 mlelstv 300 1.1 jruoho /* 301 1.5 chs * If the interrupt is handled via IOAPIC, update the map. 302 1.5 chs * If the map isn't set up yet, install a temporary one. 303 1.26 mlelstv * Identify ISA & EISA interrupts 304 1.1 jruoho */ 305 1.26 mlelstv if (mp_busses != NULL) { 306 1.26 mlelstv if (intr_find_mpmapping(mp_isa_bus, irq, &mpih) == 0 || 307 1.26 mlelstv intr_find_mpmapping(mp_eisa_bus, irq, &mpih) == 0) { 308 1.26 mlelstv if (!APIC_IRQ_ISLEGACY(mpih)) { 309 1.26 mlelstv pin = APIC_IRQ_PIN(mpih); 310 1.26 mlelstv ioapic = ioapic_find(APIC_IRQ_APIC(mpih)); 311 1.26 mlelstv if (ioapic != NULL) 312 1.26 mlelstv pic = &ioapic->sc_pic; 313 1.26 mlelstv } 314 1.1 jruoho } 315 1.26 mlelstv } 316 1.1 jruoho 317 1.26 mlelstv if (pic == NULL) { 318 1.26 mlelstv /* 319 1.26 mlelstv * If the interrupt is handled via IOAPIC, update the map. 320 1.26 mlelstv * If the map isn't set up yet, install a temporary one. 321 1.26 mlelstv */ 322 1.26 mlelstv ioapic = ioapic_find_bybase(irq); 323 1.26 mlelstv if (ioapic != NULL) { 324 1.26 mlelstv pic = &ioapic->sc_pic; 325 1.35 riastrad 326 1.26 mlelstv if (pic->pic_type == PIC_IOAPIC) { 327 1.26 mlelstv pin = irq - pic->pic_vecbase; 328 1.26 mlelstv irq = -1; 329 1.26 mlelstv } else { 330 1.26 mlelstv pin = irq; 331 1.26 mlelstv } 332 1.35 riastrad 333 1.26 mlelstv mip = ioapic->sc_pins[pin].ip_map; 334 1.26 mlelstv if (mip) { 335 1.26 mlelstv mip->flags &= ~0xf; 336 1.26 mlelstv mip->flags |= mpflags; 337 1.26 mlelstv mip->redir &= ~(IOAPIC_REDLO_LEVEL | 338 1.26 mlelstv IOAPIC_REDLO_ACTLO); 339 1.26 mlelstv mip->redir |= redir; 340 1.26 mlelstv } else { 341 1.26 mlelstv mipp = &ioapic->sc_pins[pin].ip_map; 342 1.26 mlelstv *mipp = &tmpmap; 343 1.26 mlelstv tmpmap.redir = redir; 344 1.26 mlelstv tmpmap.flags = mpflags; 345 1.26 mlelstv } 346 1.1 jruoho } 347 1.26 mlelstv } 348 1.35 riastrad 349 1.26 mlelstv if (pic == NULL) 350 1.1 jruoho #endif 351 1.1 jruoho { 352 1.1 jruoho pic = &i8259_pic; 353 1.26 mlelstv pin = irq; 354 1.1 jruoho } 355 1.1 jruoho 356 1.21 jmcneill ih = intr_establish_xname(irq, pic, pin, type, ipl, 357 1.21 jmcneill handler, arg, mpsafe, xname); 358 1.1 jruoho 359 1.5 chs #if NIOAPIC > 0 360 1.5 chs if (mipp) { 361 1.5 chs *mipp = NULL; 362 1.5 chs } 363 1.5 chs #endif 364 1.5 chs 365 1.21 jmcneill return ih; 366 1.20 jmcneill } 367 1.20 jmcneill 368 1.20 jmcneill void 369 1.29 thorpej acpi_md_intr_mask(void *ih) 370 1.29 thorpej { 371 1.29 thorpej intr_mask(ih); 372 1.29 thorpej } 373 1.29 thorpej 374 1.29 thorpej void 375 1.29 thorpej acpi_md_intr_unmask(void *ih) 376 1.29 thorpej { 377 1.29 thorpej intr_unmask(ih); 378 1.29 thorpej } 379 1.29 thorpej 380 1.29 thorpej void 381 1.20 jmcneill acpi_md_intr_disestablish(void *ih) 382 1.20 jmcneill { 383 1.20 jmcneill intr_disestablish(ih); 384 1.20 jmcneill } 385 1.20 jmcneill 386 1.1 jruoho ACPI_STATUS 387 1.1 jruoho acpi_md_OsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, 388 1.1 jruoho uint32_t Length, void **LogicalAddress) 389 1.1 jruoho { 390 1.1 jruoho int rv; 391 1.1 jruoho 392 1.1 jruoho rv = _x86_memio_map(x86_bus_space_mem, PhysicalAddress, 393 1.1 jruoho Length, 0, (bus_space_handle_t *)LogicalAddress); 394 1.1 jruoho 395 1.1 jruoho return (rv != 0) ? AE_NO_MEMORY : AE_OK; 396 1.1 jruoho } 397 1.1 jruoho 398 1.1 jruoho void 399 1.1 jruoho acpi_md_OsUnmapMemory(void *LogicalAddress, uint32_t Length) 400 1.1 jruoho { 401 1.1 jruoho (void) _x86_memio_unmap(x86_bus_space_mem, 402 1.1 jruoho (bus_space_handle_t)LogicalAddress, Length, NULL); 403 1.1 jruoho } 404 1.1 jruoho 405 1.1 jruoho ACPI_STATUS 406 1.1 jruoho acpi_md_OsGetPhysicalAddress(void *LogicalAddress, 407 1.1 jruoho ACPI_PHYSICAL_ADDRESS *PhysicalAddress) 408 1.1 jruoho { 409 1.1 jruoho paddr_t pa; 410 1.1 jruoho 411 1.1 jruoho if (pmap_extract(pmap_kernel(), (vaddr_t) LogicalAddress, &pa)) { 412 1.1 jruoho *PhysicalAddress = pa; 413 1.1 jruoho return AE_OK; 414 1.1 jruoho } 415 1.1 jruoho 416 1.1 jruoho return AE_ERROR; 417 1.1 jruoho } 418 1.1 jruoho 419 1.1 jruoho BOOLEAN 420 1.1 jruoho acpi_md_OsReadable(void *Pointer, uint32_t Length) 421 1.1 jruoho { 422 1.1 jruoho BOOLEAN rv = TRUE; 423 1.1 jruoho vaddr_t sva, eva; 424 1.1 jruoho pt_entry_t *pte; 425 1.1 jruoho 426 1.1 jruoho sva = trunc_page((vaddr_t) Pointer); 427 1.1 jruoho eva = round_page((vaddr_t) Pointer + Length); 428 1.1 jruoho 429 1.1 jruoho if (sva < VM_MIN_KERNEL_ADDRESS) 430 1.1 jruoho return FALSE; 431 1.1 jruoho 432 1.1 jruoho for (; sva < eva; sva += PAGE_SIZE) { 433 1.1 jruoho pte = kvtopte(sva); 434 1.24 maxv if ((*pte & PTE_P) == 0) { 435 1.1 jruoho rv = FALSE; 436 1.1 jruoho break; 437 1.1 jruoho } 438 1.1 jruoho } 439 1.1 jruoho 440 1.1 jruoho return rv; 441 1.1 jruoho } 442 1.1 jruoho 443 1.1 jruoho BOOLEAN 444 1.1 jruoho acpi_md_OsWritable(void *Pointer, uint32_t Length) 445 1.1 jruoho { 446 1.7 jakllsch BOOLEAN rv = TRUE; 447 1.1 jruoho vaddr_t sva, eva; 448 1.1 jruoho pt_entry_t *pte; 449 1.1 jruoho 450 1.1 jruoho sva = trunc_page((vaddr_t) Pointer); 451 1.1 jruoho eva = round_page((vaddr_t) Pointer + Length); 452 1.1 jruoho 453 1.1 jruoho if (sva < VM_MIN_KERNEL_ADDRESS) 454 1.1 jruoho return FALSE; 455 1.1 jruoho 456 1.1 jruoho for (; sva < eva; sva += PAGE_SIZE) { 457 1.1 jruoho pte = kvtopte(sva); 458 1.24 maxv if ((*pte & (PTE_P|PTE_W)) != (PTE_P|PTE_W)) { 459 1.1 jruoho rv = FALSE; 460 1.1 jruoho break; 461 1.1 jruoho } 462 1.1 jruoho } 463 1.1 jruoho 464 1.1 jruoho return rv; 465 1.1 jruoho } 466 1.1 jruoho 467 1.1 jruoho void 468 1.1 jruoho acpi_md_OsDisableInterrupt(void) 469 1.1 jruoho { 470 1.1 jruoho x86_disable_intr(); 471 1.1 jruoho } 472 1.1 jruoho 473 1.1 jruoho void 474 1.1 jruoho acpi_md_OsEnableInterrupt(void) 475 1.1 jruoho { 476 1.1 jruoho x86_enable_intr(); 477 1.1 jruoho } 478 1.1 jruoho 479 1.1 jruoho uint32_t 480 1.1 jruoho acpi_md_ncpus(void) 481 1.1 jruoho { 482 1.3 rmind return kcpuset_countset(kcpuset_attached); 483 1.1 jruoho } 484 1.1 jruoho 485 1.9 msaitoh static bool 486 1.9 msaitoh acpi_md_mcfg_validate(uint64_t addr, int bus_start, int *bus_end) 487 1.9 msaitoh { 488 1.17 nonaka struct btinfo_memmap *bim; 489 1.9 msaitoh uint64_t size, mapaddr, mapsize; 490 1.9 msaitoh uint32_t type; 491 1.17 nonaka int i, n; 492 1.9 msaitoh 493 1.22 cherry #ifndef XENPV 494 1.17 nonaka if (lookup_bootinfo(BTINFO_EFIMEMMAP) != NULL) 495 1.17 nonaka bim = efi_get_e820memmap(); 496 1.17 nonaka else 497 1.17 nonaka #endif 498 1.17 nonaka bim = lookup_bootinfo(BTINFO_MEMMAP); 499 1.17 nonaka if (bim == NULL) 500 1.17 nonaka return false; 501 1.9 msaitoh 502 1.10 christos size = *bus_end - bus_start + 1; 503 1.10 christos size *= ACPIMCFG_SIZE_PER_BUS; 504 1.17 nonaka for (i = 0; i < bim->num; i++) { 505 1.17 nonaka mapaddr = bim->entry[i].addr; 506 1.17 nonaka mapsize = bim->entry[i].size; 507 1.17 nonaka type = bim->entry[i].type; 508 1.17 nonaka 509 1.17 nonaka aprint_debug("MCFG: MEMMAP: 0x%016" PRIx64 510 1.17 nonaka "-0x%016" PRIx64 ", size=0x%016" PRIx64 511 1.17 nonaka ", type=%d(%s)\n", 512 1.17 nonaka mapaddr, mapaddr + mapsize - 1, mapsize, type, 513 1.17 nonaka (type == BIM_Memory) ? "Memory" : 514 1.17 nonaka (type == BIM_Reserved) ? "Reserved" : 515 1.17 nonaka (type == BIM_ACPI) ? "ACPI" : 516 1.17 nonaka (type == BIM_NVS) ? "NVS" : 517 1.18 nonaka (type == BIM_PMEM) ? "Persistent" : 518 1.18 nonaka (type == BIM_PRAM) ? "Persistent (Legacy)" : 519 1.17 nonaka "unknown"); 520 1.9 msaitoh 521 1.9 msaitoh switch (type) { 522 1.9 msaitoh case BIM_ACPI: 523 1.9 msaitoh case BIM_Reserved: 524 1.9 msaitoh if (addr < mapaddr || addr >= mapaddr + mapsize) 525 1.9 msaitoh break; 526 1.9 msaitoh 527 1.9 msaitoh /* full map */ 528 1.9 msaitoh if (addr + size <= mapaddr + mapsize) 529 1.9 msaitoh return true; 530 1.9 msaitoh 531 1.9 msaitoh /* partial map */ 532 1.9 msaitoh n = (mapsize - (addr - mapaddr)) / 533 1.9 msaitoh ACPIMCFG_SIZE_PER_BUS; 534 1.9 msaitoh /* bus_start == bus_end is not allowed. */ 535 1.9 msaitoh if (n > 1) { 536 1.9 msaitoh *bus_end = bus_start + n - 1; 537 1.9 msaitoh return true; 538 1.9 msaitoh } 539 1.9 msaitoh aprint_debug("MCFG: bus %d-%d, address 0x%016" PRIx64 540 1.9 msaitoh ": invalid size: request 0x%016" PRIx64 ", " 541 1.9 msaitoh "actual 0x%016" PRIx64 "\n", 542 1.9 msaitoh bus_start, *bus_end, addr, size, mapsize); 543 1.9 msaitoh break; 544 1.9 msaitoh } 545 1.9 msaitoh } 546 1.9 msaitoh aprint_debug("MCFG: bus %d-%d, address 0x%016" PRIx64 ": " 547 1.9 msaitoh "no valid region\n", bus_start, *bus_end, addr); 548 1.9 msaitoh return false; 549 1.9 msaitoh } 550 1.9 msaitoh 551 1.9 msaitoh static uint32_t 552 1.9 msaitoh acpi_md_mcfg_read(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t addr) 553 1.9 msaitoh { 554 1.9 msaitoh vaddr_t va = bsh + addr; 555 1.9 msaitoh uint32_t data = (uint32_t) -1; 556 1.9 msaitoh 557 1.9 msaitoh KASSERT(bst == x86_bus_space_mem); 558 1.9 msaitoh 559 1.9 msaitoh __asm("movl %1, %0" : "=a" (data) : "m" (*(volatile uint32_t *)va)); 560 1.9 msaitoh 561 1.9 msaitoh return data; 562 1.9 msaitoh } 563 1.9 msaitoh 564 1.9 msaitoh static void 565 1.9 msaitoh acpi_md_mcfg_write(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t addr, 566 1.9 msaitoh uint32_t data) 567 1.9 msaitoh { 568 1.9 msaitoh vaddr_t va = bsh + addr; 569 1.9 msaitoh 570 1.9 msaitoh KASSERT(bst == x86_bus_space_mem); 571 1.9 msaitoh 572 1.9 msaitoh __asm("movl %1, %0" : "=m" (*(volatile uint32_t *)va) : "a" (data)); 573 1.9 msaitoh } 574 1.9 msaitoh 575 1.9 msaitoh static const struct acpimcfg_ops acpi_md_mcfg_ops = { 576 1.9 msaitoh .ao_validate = acpi_md_mcfg_validate, 577 1.9 msaitoh 578 1.9 msaitoh .ao_read = acpi_md_mcfg_read, 579 1.9 msaitoh .ao_write = acpi_md_mcfg_write, 580 1.9 msaitoh }; 581 1.9 msaitoh 582 1.1 jruoho void 583 1.4 chs acpi_md_callback(struct acpi_softc *sc) 584 1.1 jruoho { 585 1.1 jruoho #ifdef MPBIOS 586 1.1 jruoho if (!mpbios_scanned) 587 1.1 jruoho #endif 588 1.4 chs mpacpi_find_interrupts(sc); 589 1.1 jruoho 590 1.22 cherry #ifndef XENPV 591 1.1 jruoho acpi_md_sleep_init(); 592 1.1 jruoho #endif 593 1.9 msaitoh 594 1.9 msaitoh acpimcfg_init(x86_bus_space_mem, &acpi_md_mcfg_ops); 595 1.1 jruoho } 596 1.13 jmcneill 597 1.22 cherry #ifndef XENPV 598 1.36 bouyer int acpi_md_vbios_reset = 0; 599 1.36 bouyer 600 1.13 jmcneill void 601 1.13 jmcneill device_acpi_register(device_t dev, void *aux) 602 1.13 jmcneill { 603 1.13 jmcneill device_t parent; 604 1.13 jmcneill bool device_is_vga, device_is_pci, device_is_isa; 605 1.13 jmcneill 606 1.13 jmcneill parent = device_parent(dev); 607 1.13 jmcneill if (parent == NULL) 608 1.13 jmcneill return; 609 1.13 jmcneill 610 1.13 jmcneill device_is_vga = device_is_a(dev, "vga") || device_is_a(dev, "genfb"); 611 1.13 jmcneill device_is_pci = device_is_a(parent, "pci"); 612 1.13 jmcneill device_is_isa = device_is_a(parent, "isa"); 613 1.13 jmcneill 614 1.13 jmcneill if (device_is_vga && (device_is_pci || device_is_isa)) { 615 1.13 jmcneill acpi_md_vbios_reset = VBIOS_RESET_DEFAULT; 616 1.13 jmcneill } 617 1.13 jmcneill } 618 1.13 jmcneill #endif 619