Module Name: src Committed By: jruoho Date: Sun Jun 12 10:11:53 UTC 2011
Modified Files: src/sys/arch/ia64/acpi: acpi_machdep.c src/sys/arch/ia64/include: acpi_machdep.h src/sys/arch/x86/acpi: acpi_cpu_md.c src/sys/arch/x86/conf: files.x86 src/sys/arch/x86/include: acpi_machdep.h src/sys/dev/acpi: acpi.c acpi_cpu.c acpi_cpu.h Added Files: src/sys/arch/x86/acpi: acpi_pdc.c Log Message: Move the evaluation of the _PDC control method out from the acpicpu(4) driver to the main acpi(4) stack. Follow Linux and evaluate it early. Should fix PR port-amd64/42895, possibly also PR kern/42583, and many other comparable bugs. A common sense explanation is that Intel supplies additional CPU tables to OEMs. BIOS writers do not bother to modify their DSDTs, but instead load these extra tables dynamically as secondary SSDT tables. The actual Load() happens when the _PDC method is invoked, and thus namespace errors occur when the CPU-specific ACPI methods are not yet present but referenced in the AML by various drivers, including, but not limited to, acpitz(4). To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/arch/ia64/acpi/acpi_machdep.c cvs rdiff -u -r1.3 -r1.4 src/sys/arch/ia64/include/acpi_machdep.h cvs rdiff -u -r1.60 -r1.61 src/sys/arch/x86/acpi/acpi_cpu_md.c cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/acpi/acpi_pdc.c cvs rdiff -u -r1.69 -r1.70 src/sys/arch/x86/conf/files.x86 cvs rdiff -u -r1.8 -r1.9 src/sys/arch/x86/include/acpi_machdep.h cvs rdiff -u -r1.242 -r1.243 src/sys/dev/acpi/acpi.c cvs rdiff -u -r1.40 -r1.41 src/sys/dev/acpi/acpi_cpu.c \ src/sys/dev/acpi/acpi_cpu.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/ia64/acpi/acpi_machdep.c diff -u src/sys/arch/ia64/acpi/acpi_machdep.c:1.3 src/sys/arch/ia64/acpi/acpi_machdep.c:1.4 --- src/sys/arch/ia64/acpi/acpi_machdep.c:1.3 Thu Jan 13 03:40:50 2011 +++ src/sys/arch/ia64/acpi/acpi_machdep.c Sun Jun 12 10:11:52 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_machdep.c,v 1.3 2011/01/13 03:40:50 jruoho Exp $ */ +/* $NetBSD: acpi_machdep.c,v 1.4 2011/06/12 10:11:52 jruoho Exp $ */ /* * Copyright (c) 2009 KIYOHARA Takashi * All rights reserved. @@ -28,7 +28,7 @@ * Machine-dependent routines for ACPICA. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.3 2011/01/13 03:40:50 jruoho Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.4 2011/06/12 10:11:52 jruoho Exp $"); #include <sys/param.h> @@ -186,20 +186,23 @@ } uint32_t -acpi_md_ncpus(void) +acpi_md_pdc(void) { + return 0; +} +uint32_t +acpi_md_ncpus(void) +{ return 0; /* XXX. */ } void acpi_md_callback(void) { - - /* nothing */ + /* Nothing. */ } - int acpi_md_sleep(int state) { Index: src/sys/arch/ia64/include/acpi_machdep.h diff -u src/sys/arch/ia64/include/acpi_machdep.h:1.3 src/sys/arch/ia64/include/acpi_machdep.h:1.4 --- src/sys/arch/ia64/include/acpi_machdep.h:1.3 Thu Jan 13 03:40:50 2011 +++ src/sys/arch/ia64/include/acpi_machdep.h Sun Jun 12 10:11:52 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_machdep.h,v 1.3 2011/01/13 03:40:50 jruoho Exp $ */ +/* $NetBSD: acpi_machdep.h,v 1.4 2011/06/12 10:11:52 jruoho Exp $ */ ACPI_STATUS acpi_md_OsInitialize(void); ACPI_STATUS acpi_md_OsTerminate(void); @@ -27,5 +27,6 @@ void acpi_md_OsDisableInterrupt(void); int acpi_md_sleep(int); +uint32_t acpi_md_pdc(void); uint32_t acpi_md_ncpus(void); void acpi_md_callback(void); Index: src/sys/arch/x86/acpi/acpi_cpu_md.c diff -u src/sys/arch/x86/acpi/acpi_cpu_md.c:1.60 src/sys/arch/x86/acpi/acpi_cpu_md.c:1.61 --- src/sys/arch/x86/acpi/acpi_cpu_md.c:1.60 Mon Jun 6 07:42:32 2011 +++ src/sys/arch/x86/acpi/acpi_cpu_md.c Sun Jun 12 10:11:52 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_cpu_md.c,v 1.60 2011/06/06 07:42:32 jruoho Exp $ */ +/* $NetBSD: acpi_cpu_md.c,v 1.61 2011/06/12 10:11:52 jruoho Exp $ */ /*- * Copyright (c) 2010, 2011 Jukka Ruohonen <jruoho...@iki.fi> @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.60 2011/06/06 07:42:32 jruoho Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.61 2011/06/12 10:11:52 jruoho Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -141,57 +141,6 @@ } uint32_t -acpicpu_md_cap(void) -{ - struct cpu_info *ci = curcpu(); - uint32_t regs[4]; - uint32_t val = 0; - - if (cpu_vendor != CPUVENDOR_IDT && - cpu_vendor != CPUVENDOR_INTEL) - return val; - - /* - * Basic SMP C-states (required for e.g. _CST). - */ - val |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3; - - /* - * Claim to support dependency coordination. - */ - val |= ACPICPU_PDC_P_SW | ACPICPU_PDC_C_SW | ACPICPU_PDC_T_SW; - - /* - * If MONITOR/MWAIT is available, announce - * support for native instructions in all C-states. - */ - if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) - val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH; - - /* - * Set native P- and T-states, if available. - */ - if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) - val |= ACPICPU_PDC_P_FFH; - - if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0) - val |= ACPICPU_PDC_T_FFH; - - /* - * Declare support for APERF and MPERF. - */ - if (cpuid_level >= 0x06) { - - x86_cpuid(0x00000006, regs); - - if ((regs[2] & CPUID_DSPM_HWF) != 0) - val |= ACPICPU_PDC_P_HWF; - } - - return val; -} - -uint32_t acpicpu_md_flags(void) { struct cpu_info *ci = curcpu(); Index: src/sys/arch/x86/conf/files.x86 diff -u src/sys/arch/x86/conf/files.x86:1.69 src/sys/arch/x86/conf/files.x86:1.70 --- src/sys/arch/x86/conf/files.x86:1.69 Sun Jun 12 03:35:49 2011 +++ src/sys/arch/x86/conf/files.x86 Sun Jun 12 10:11:52 2011 @@ -1,4 +1,4 @@ -# $NetBSD: files.x86,v 1.69 2011/06/12 03:35:49 rmind Exp $ +# $NetBSD: files.x86,v 1.70 2011/06/12 10:11:52 jruoho Exp $ # options for MP configuration through the MP spec defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI @@ -107,6 +107,7 @@ file arch/x86/x86/acpi_machdep.c acpi +file arch/x86/acpi/acpi_pdc.c acpi file arch/x86/acpi/acpi_wakeup.c acpi file arch/x86/isa/isa_machdep.c isa Index: src/sys/arch/x86/include/acpi_machdep.h diff -u src/sys/arch/x86/include/acpi_machdep.h:1.8 src/sys/arch/x86/include/acpi_machdep.h:1.9 --- src/sys/arch/x86/include/acpi_machdep.h:1.8 Thu Jan 13 03:40:50 2011 +++ src/sys/arch/x86/include/acpi_machdep.h Sun Jun 12 10:11:52 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_machdep.h,v 1.8 2011/01/13 03:40:50 jruoho Exp $ */ +/* $NetBSD: acpi_machdep.h,v 1.9 2011/06/12 10:11:52 jruoho Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -73,6 +73,8 @@ int acpi_md_sleep(int); void acpi_md_sleep_init(void); + +uint32_t acpi_md_pdc(void); uint32_t acpi_md_ncpus(void); void acpi_md_callback(void); Index: src/sys/dev/acpi/acpi.c diff -u src/sys/dev/acpi/acpi.c:1.242 src/sys/dev/acpi/acpi.c:1.243 --- src/sys/dev/acpi/acpi.c:1.242 Fri Jun 3 09:15:02 2011 +++ src/sys/dev/acpi/acpi.c Sun Jun 12 10:11:52 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi.c,v 1.242 2011/06/03 09:15:02 jruoho Exp $ */ +/* $NetBSD: acpi.c,v 1.243 2011/06/12 10:11:52 jruoho Exp $ */ /*- * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. @@ -100,7 +100,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.242 2011/06/03 09:15:02 jruoho Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.243 2011/06/12 10:11:52 jruoho Exp $"); #include "opt_acpi.h" #include "opt_pcifixup.h" @@ -441,9 +441,15 @@ goto fail; /* - * Early EC handler initialization if ECDT table is available. + * Early initialization of the _PDC control method + * that may load additional SSDT tables dynamically. */ - config_found_ia(self, "acpiecdtbus", aa, NULL); + (void)acpi_md_pdc(); + + /* + * Early initialization of acpiec(4) via ECDT. + */ + (void)config_found_ia(self, "acpiecdtbus", aa, NULL); rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); Index: src/sys/dev/acpi/acpi_cpu.c diff -u src/sys/dev/acpi/acpi_cpu.c:1.40 src/sys/dev/acpi/acpi_cpu.c:1.41 --- src/sys/dev/acpi/acpi_cpu.c:1.40 Mon Apr 25 05:30:21 2011 +++ src/sys/dev/acpi/acpi_cpu.c Sun Jun 12 10:11:52 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_cpu.c,v 1.40 2011/04/25 05:30:21 jruoho Exp $ */ +/* $NetBSD: acpi_cpu.c,v 1.41 2011/06/12 10:11:52 jruoho Exp $ */ /*- * Copyright (c) 2010, 2011 Jukka Ruohonen <jruoho...@iki.fi> @@ -27,7 +27,7 @@ * SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.40 2011/04/25 05:30:21 jruoho Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.41 2011/06/12 10:11:52 jruoho Exp $"); #include <sys/param.h> #include <sys/cpu.h> @@ -60,7 +60,6 @@ static int acpicpu_find(struct cpu_info *, struct acpi_devnode **); static uint32_t acpicpu_cap(struct acpicpu_softc *); -static ACPI_STATUS acpicpu_cap_pdc(struct acpicpu_softc *, uint32_t); static ACPI_STATUS acpicpu_cap_osc(struct acpicpu_softc *, uint32_t, uint32_t *); static void acpicpu_notify(ACPI_HANDLE, uint32_t, void *); @@ -455,60 +454,24 @@ acpicpu_cap(struct acpicpu_softc *sc) { uint32_t flags, cap = 0; - const char *str; ACPI_STATUS rv; /* * Query and set machine-dependent capabilities. - * Note that the Intel-specific _PDC method was + * Note that the Intel-specific _PDC method has + * already been evaluated. It was furthermore * deprecated in the ACPI 3.0 in favor of _OSC. */ - flags = acpicpu_md_cap(); + flags = acpi_md_pdc(); rv = acpicpu_cap_osc(sc, flags, &cap); if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) { - str = "_OSC"; - goto fail; - } - rv = acpicpu_cap_pdc(sc, flags); - - if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) { - str = "_PDC"; - goto fail; + aprint_error_dev(sc->sc_dev, "failed to evaluate " + "_OSC: %s\n", AcpiFormatException(rv)); } - if (cap == 0) - cap = flags; - - return cap; - -fail: - aprint_error_dev(sc->sc_dev, "failed to evaluate " - "%s: %s\n", str, AcpiFormatException(rv)); - - return 0; -} - -static ACPI_STATUS -acpicpu_cap_pdc(struct acpicpu_softc *sc, uint32_t flags) -{ - ACPI_OBJECT_LIST arg; - ACPI_OBJECT obj; - uint32_t cap[3]; - - arg.Count = 1; - arg.Pointer = &obj; - - cap[0] = ACPICPU_PDC_REVID; - cap[1] = 1; - cap[2] = flags; - - obj.Type = ACPI_TYPE_BUFFER; - obj.Buffer.Length = sizeof(cap); - obj.Buffer.Pointer = (void *)cap; - - return AcpiEvaluateObject(sc->sc_node->ad_handle, "_PDC", &arg, NULL); + return (cap != 0) ? cap : flags; } static ACPI_STATUS Index: src/sys/dev/acpi/acpi_cpu.h diff -u src/sys/dev/acpi/acpi_cpu.h:1.40 src/sys/dev/acpi/acpi_cpu.h:1.41 --- src/sys/dev/acpi/acpi_cpu.h:1.40 Thu Mar 24 05:10:06 2011 +++ src/sys/dev/acpi/acpi_cpu.h Sun Jun 12 10:11:52 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_cpu.h,v 1.40 2011/03/24 05:10:06 jruoho Exp $ */ +/* $NetBSD: acpi_cpu.h,v 1.41 2011/06/12 10:11:52 jruoho Exp $ */ /*- * Copyright (c) 2010, 2011 Jukka Ruohonen <jruoho...@iki.fi> @@ -260,7 +260,6 @@ struct cpu_info *acpicpu_md_match(device_t, cfdata_t, void *); struct cpu_info *acpicpu_md_attach(device_t, device_t, void *); -uint32_t acpicpu_md_cap(void); uint32_t acpicpu_md_flags(void); void acpicpu_md_quirk_c1e(void); int acpicpu_md_cstate_start(struct acpicpu_softc *); Added files: Index: src/sys/arch/x86/acpi/acpi_pdc.c diff -u /dev/null src/sys/arch/x86/acpi/acpi_pdc.c:1.1 --- /dev/null Sun Jun 12 10:11:53 2011 +++ src/sys/arch/x86/acpi/acpi_pdc.c Sun Jun 12 10:11:52 2011 @@ -0,0 +1,142 @@ +/* $NetBSD: acpi_pdc.c,v 1.1 2011/06/12 10:11:52 jruoho Exp $ */ + +/*- + * Copyright (c) 2010, 2011 Jukka Ruohonen <jruoho...@iki.fi> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: acpi_pdc.c,v 1.1 2011/06/12 10:11:52 jruoho Exp $"); + +#include <sys/param.h> + +#include <x86/cpu.h> +#include <x86/cputypes.h> +#include <x86/cpuvar.h> + +#include <dev/acpi/acpireg.h> +#include <dev/acpi/acpivar.h> +#include <dev/acpi/acpi_cpu.h> + +#include <machine/acpi_machdep.h> + +#define _COMPONENT ACPI_BUS_COMPONENT +ACPI_MODULE_NAME ("acpi_pdc") + +static uint32_t flags = 0; + +static ACPI_STATUS acpi_md_pdc_walk(ACPI_HANDLE, uint32_t,void *,void **); +static ACPI_STATUS acpi_md_pdc_set(ACPI_HANDLE, uint32_t); + +uint32_t +acpi_md_pdc(void) +{ + char *hid = __UNCONST("ACPI0007"); + struct cpu_info *ci = curcpu(); + uint32_t regs[4]; + + if (flags != 0) + return flags; + + if (cpu_vendor != CPUVENDOR_IDT && + cpu_vendor != CPUVENDOR_INTEL) + return 0; + + /* + * Basic SMP C-states (required for e.g. _CST). + */ + flags |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3; + + /* + * Claim to support dependency coordination. + */ + flags |= ACPICPU_PDC_P_SW | ACPICPU_PDC_C_SW | ACPICPU_PDC_T_SW; + + /* + * If MONITOR/MWAIT is available, announce + * support for native instructions in all C-states. + */ + if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0) + flags |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH; + + /* + * Set native P- and T-states, if available. + */ + if ((ci->ci_feat_val[1] & CPUID2_EST) != 0) + flags |= ACPICPU_PDC_P_FFH; + + if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0) + flags |= ACPICPU_PDC_T_FFH; + + /* + * Declare support for APERF and MPERF. + */ + if (cpuid_level >= 0x06) { + + x86_cpuid(0x00000006, regs); + + if ((regs[2] & CPUID_DSPM_HWF) != 0) + flags |= ACPICPU_PDC_P_HWF; + } + + /* + * As the _PDC must be evaluated before the internal namespace + * is built, we have no option but to walk with the interpreter. + */ + (void)AcpiGetDevices(hid, acpi_md_pdc_walk, NULL, NULL); + + (void)AcpiWalkNamespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, + UINT32_MAX, acpi_md_pdc_walk, NULL, NULL, NULL); + + return flags; +} + +static ACPI_STATUS +acpi_md_pdc_walk(ACPI_HANDLE hdl, uint32_t level, void *context, void **status) +{ + return acpi_md_pdc_set(hdl, flags); +} + +static ACPI_STATUS +acpi_md_pdc_set(ACPI_HANDLE hdl, uint32_t val) +{ + ACPI_OBJECT_LIST arg; + ACPI_OBJECT obj; + uint32_t cap[3]; + + arg.Count = 1; + arg.Pointer = &obj; + + cap[0] = ACPICPU_PDC_REVID; + cap[1] = 1; + cap[2] = val; + + obj.Type = ACPI_TYPE_BUFFER; + obj.Buffer.Length = sizeof(cap); + obj.Buffer.Pointer = (void *)cap; + + (void)AcpiEvaluateObject(hdl, "_PDC", &arg, NULL); + + return AE_OK; +}