acpi_cpu_md.c revision 1.3 1 1.3 jruoho /* $NetBSD: acpi_cpu_md.c,v 1.3 2010/07/23 13:54:21 jruoho Exp $ */
2 1.1 jruoho
3 1.1 jruoho /*-
4 1.1 jruoho * Copyright (c) 2010 Jukka Ruohonen <jruohonen (at) iki.fi>
5 1.1 jruoho * All rights reserved.
6 1.1 jruoho *
7 1.1 jruoho * Redistribution and use in source and binary forms, with or without
8 1.1 jruoho * modification, are permitted provided that the following conditions
9 1.1 jruoho * are met:
10 1.1 jruoho *
11 1.1 jruoho * 1. Redistributions of source code must retain the above copyright
12 1.1 jruoho * notice, this list of conditions and the following disclaimer.
13 1.1 jruoho * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 jruoho * notice, this list of conditions and the following disclaimer in the
15 1.1 jruoho * documentation and/or other materials provided with the distribution.
16 1.1 jruoho *
17 1.1 jruoho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 1.1 jruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.1 jruoho * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.1 jruoho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 1.1 jruoho * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 jruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.1 jruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.1 jruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.1 jruoho * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.1 jruoho * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.1 jruoho * SUCH DAMAGE.
28 1.1 jruoho */
29 1.1 jruoho #include <sys/cdefs.h>
30 1.3 jruoho __KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.3 2010/07/23 13:54:21 jruoho Exp $");
31 1.1 jruoho
32 1.1 jruoho #include <sys/param.h>
33 1.1 jruoho #include <sys/bus.h>
34 1.1 jruoho #include <sys/kcore.h>
35 1.1 jruoho
36 1.1 jruoho #include <x86/cpu.h>
37 1.1 jruoho #include <x86/cpuvar.h>
38 1.1 jruoho #include <x86/machdep.h>
39 1.1 jruoho #include <x86/cputypes.h>
40 1.1 jruoho
41 1.1 jruoho #include <dev/acpi/acpica.h>
42 1.1 jruoho #include <dev/acpi/acpi_cpu.h>
43 1.1 jruoho
44 1.1 jruoho static char native_idle_text[16];
45 1.1 jruoho void (*native_idle)(void) = NULL;
46 1.1 jruoho
47 1.1 jruoho extern uint32_t cpus_running;
48 1.1 jruoho
49 1.1 jruoho uint32_t
50 1.1 jruoho acpicpu_md_cap(void)
51 1.1 jruoho {
52 1.1 jruoho struct cpu_info *ci = curcpu();
53 1.1 jruoho uint32_t val = 0;
54 1.1 jruoho
55 1.1 jruoho if (cpu_vendor != CPUVENDOR_INTEL)
56 1.1 jruoho return val;
57 1.1 jruoho
58 1.1 jruoho /*
59 1.1 jruoho * Basic SMP C-states (required for _CST).
60 1.1 jruoho */
61 1.1 jruoho val |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3;
62 1.1 jruoho
63 1.1 jruoho /*
64 1.1 jruoho * If MONITOR/MWAIT is available, announce
65 1.1 jruoho * support for native instructions in all C-states.
66 1.1 jruoho */
67 1.1 jruoho if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
68 1.1 jruoho val |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH;
69 1.1 jruoho
70 1.1 jruoho return val;
71 1.1 jruoho }
72 1.1 jruoho
73 1.1 jruoho uint32_t
74 1.1 jruoho acpicpu_md_quirks(void)
75 1.1 jruoho {
76 1.1 jruoho struct cpu_info *ci = curcpu();
77 1.1 jruoho uint32_t val = 0;
78 1.1 jruoho
79 1.1 jruoho if (acpicpu_md_cpus_running() == 1)
80 1.1 jruoho val |= ACPICPU_FLAG_C_BM;
81 1.1 jruoho
82 1.1 jruoho if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
83 1.1 jruoho val |= ACPICPU_FLAG_C_MWAIT;
84 1.1 jruoho
85 1.1 jruoho switch (cpu_vendor) {
86 1.1 jruoho
87 1.1 jruoho case CPUVENDOR_INTEL:
88 1.1 jruoho val |= ACPICPU_FLAG_C_BM | ACPICPU_FLAG_C_ARB;
89 1.1 jruoho
90 1.1 jruoho /*
91 1.1 jruoho * Bus master arbitration is not
92 1.1 jruoho * needed on some recent Intel CPUs.
93 1.1 jruoho */
94 1.1 jruoho if (CPUID2FAMILY(ci->ci_signature) > 15)
95 1.1 jruoho val &= ~ACPICPU_FLAG_C_ARB;
96 1.1 jruoho
97 1.1 jruoho if (CPUID2FAMILY(ci->ci_signature) == 6 &&
98 1.1 jruoho CPUID2MODEL(ci->ci_signature) >= 15)
99 1.1 jruoho val &= ~ACPICPU_FLAG_C_ARB;
100 1.1 jruoho
101 1.1 jruoho break;
102 1.1 jruoho
103 1.1 jruoho case CPUVENDOR_AMD:
104 1.1 jruoho
105 1.1 jruoho /*
106 1.1 jruoho * XXX: Deal with the AMD C1E extension here.
107 1.1 jruoho */
108 1.1 jruoho break;
109 1.1 jruoho }
110 1.1 jruoho
111 1.1 jruoho return val;
112 1.1 jruoho }
113 1.1 jruoho
114 1.1 jruoho uint32_t
115 1.1 jruoho acpicpu_md_cpus_running(void)
116 1.1 jruoho {
117 1.1 jruoho
118 1.1 jruoho return popcount32(cpus_running);
119 1.1 jruoho }
120 1.1 jruoho
121 1.1 jruoho int
122 1.1 jruoho acpicpu_md_idle_init(void)
123 1.1 jruoho {
124 1.1 jruoho const size_t size = sizeof(native_idle_text);
125 1.1 jruoho
126 1.1 jruoho KASSERT(native_idle == NULL);
127 1.1 jruoho
128 1.1 jruoho x86_disable_intr();
129 1.1 jruoho x86_cpu_idle_get(&native_idle, native_idle_text, size);
130 1.1 jruoho x86_enable_intr();
131 1.1 jruoho
132 1.1 jruoho return 0;
133 1.1 jruoho }
134 1.1 jruoho
135 1.1 jruoho int
136 1.1 jruoho acpicpu_md_idle_start(void)
137 1.1 jruoho {
138 1.1 jruoho
139 1.1 jruoho KASSERT(native_idle != NULL);
140 1.1 jruoho KASSERT(native_idle_text[0] != '\0');
141 1.1 jruoho
142 1.1 jruoho x86_disable_intr();
143 1.1 jruoho x86_cpu_idle_set(acpicpu_cstate_idle, "acpi");
144 1.1 jruoho x86_enable_intr();
145 1.1 jruoho
146 1.1 jruoho DELAY(10000);
147 1.1 jruoho
148 1.1 jruoho return 0;
149 1.1 jruoho }
150 1.1 jruoho
151 1.1 jruoho int
152 1.1 jruoho acpicpu_md_idle_stop(void)
153 1.1 jruoho {
154 1.1 jruoho
155 1.1 jruoho KASSERT(native_idle != NULL);
156 1.1 jruoho KASSERT(native_idle_text[0] != '\0');
157 1.1 jruoho
158 1.1 jruoho x86_disable_intr();
159 1.1 jruoho x86_cpu_idle_set(native_idle, native_idle_text);
160 1.1 jruoho x86_enable_intr();
161 1.1 jruoho
162 1.1 jruoho DELAY(10000);
163 1.1 jruoho
164 1.1 jruoho return 0;
165 1.1 jruoho }
166 1.1 jruoho
167 1.3 jruoho /*
168 1.3 jruoho * The MD idle loop. Called with interrupts disabled.
169 1.3 jruoho */
170 1.1 jruoho void
171 1.1 jruoho acpicpu_md_idle_enter(int method, int state)
172 1.1 jruoho {
173 1.3 jruoho struct cpu_info *ci = curcpu();
174 1.1 jruoho
175 1.1 jruoho switch (method) {
176 1.1 jruoho
177 1.1 jruoho case ACPICPU_C_STATE_FFH:
178 1.3 jruoho
179 1.3 jruoho x86_enable_intr();
180 1.3 jruoho x86_monitor(&ci->ci_want_resched, 0, 0);
181 1.3 jruoho
182 1.3 jruoho if (__predict_false(ci->ci_want_resched) != 0)
183 1.3 jruoho return;
184 1.3 jruoho
185 1.1 jruoho x86_mwait((state - 1) << 4, 0);
186 1.1 jruoho break;
187 1.1 jruoho
188 1.1 jruoho case ACPICPU_C_STATE_HALT:
189 1.3 jruoho
190 1.3 jruoho if (__predict_false(ci->ci_want_resched) != 0) {
191 1.3 jruoho x86_enable_intr();
192 1.3 jruoho return;
193 1.3 jruoho }
194 1.3 jruoho
195 1.1 jruoho x86_stihlt();
196 1.1 jruoho break;
197 1.1 jruoho }
198 1.1 jruoho }
199