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;
+}

Reply via email to