xref: /freebsd/sys/x86/cpufreq/hwpstate_amd.c (revision 1a3d61552546407786148221a961b0ce810ebabb)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2005 Nate Lawson
5  * Copyright (c) 2004 Colin Percival
6  * Copyright (c) 2004-2005 Bruno Durcot
7  * Copyright (c) 2004 FUKUDA Nobuhiko
8  * Copyright (c) 2009 Michael Reifenberger
9  * Copyright (c) 2009 Norikatsu Shigemura
10  * Copyright (c) 2008-2009 Gen Otsuji
11  * Copyright (c) 2025 ShengYi Hung
12  * Copyright (c) 2026 The FreeBSD Foundation
13  *
14  * Portions of this software were developed by Olivier Certner
15  * <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD
16  * Foundation.
17  *
18  * This code is depending on kern_cpu.c, est.c, powernow.c, p4tcc.c, smist.c
19  * in various parts. The authors of these files are Nate Lawson,
20  * Colin Percival, Bruno Durcot, and FUKUDA Nobuhiko.
21  * This code contains patches by Michael Reifenberger and Norikatsu Shigemura.
22  * Thank you.
23  *
24  * Redistribution and use in source and binary forms, with or without
25  * modification, are permitted providing that the following conditions
26  * are met:
27  * 1. Redistributions of source code must retain the above copyright
28  *    notice, this list of conditions and the following disclaimer.
29  * 2. Redistributions in binary form must reproduce the above copyright
30  *    notice, this list of conditions and the following disclaimer in the
31  *    documentation and/or other materials provided with the distribution.
32  *
33  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR``AS IS'' AND ANY EXPRESS OR
34  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43  * POSSIBILITY OF SUCH DAMAGE.
44  */
45 
46 /*
47  * For more info:
48  * BIOS and Kernel Developer's Guide(BKDG) for AMD Family 10h Processors
49  * 31116 Rev 3.20  February 04, 2009
50  * BIOS and Kernel Developer's Guide(BKDG) for AMD Family 11h Processors
51  * 41256 Rev 3.00 - July 07, 2008
52  * Processor Programming Reference (PPR) for AMD Family 1Ah Model 02h,
53  * Revision C1 Processors Volume 1 of 7 - Sep 29, 2024
54  */
55 
56 #include <sys/param.h>
57 #include <sys/bus.h>
58 #include <sys/cpu.h>
59 #include <sys/kernel.h>
60 #include <sys/malloc.h>
61 #include <sys/module.h>
62 #include <sys/pcpu.h>
63 #include <sys/proc.h>
64 #include <sys/sbuf.h>
65 #include <sys/sched.h>
66 #include <sys/smp.h>
67 
68 #include <machine/_inttypes.h>
69 #include <machine/cputypes.h>
70 #include <machine/md_var.h>
71 #include <machine/specialreg.h>
72 
73 #include <contrib/dev/acpica/include/acpi.h>
74 
75 #include <dev/acpica/acpivar.h>
76 
77 #include <x86/cpufreq/hwpstate_common.h>
78 
79 #include "acpi_if.h"
80 #include "cpufreq_if.h"
81 
82 
83 #define	MSR_AMD_10H_11H_LIMIT	0xc0010061
84 #define	MSR_AMD_10H_11H_CONTROL	0xc0010062
85 #define	MSR_AMD_10H_11H_STATUS	0xc0010063
86 #define	MSR_AMD_10H_11H_CONFIG	0xc0010064
87 
88 #define	MSR_AMD_CPPC_CAPS_1	0xc00102b0
89 #define	MSR_AMD_CPPC_ENABLE	0xc00102b1
90 #define	MSR_AMD_CPPC_CAPS_2	0xc00102b2
91 #define	MSR_AMD_CPPC_REQUEST	0xc00102b3
92 #define	MSR_AMD_CPPC_STATUS	0xc00102b4
93 
94 #define	MSR_AMD_CPPC_CAPS_1_NAME	"CPPC_CAPABILITY_1"
95 #define	MSR_AMD_CPPC_ENABLE_NAME	"CPPC_ENABLE"
96 #define	MSR_AMD_CPPC_REQUEST_NAME	"CPPC_REQUEST"
97 
98 #define	MSR_AMD_PWR_ACC		0xc001007a
99 #define	MSR_AMD_PWR_ACC_MX	0xc001007b
100 
101 #define	AMD_10H_11H_MAX_STATES	16
102 
103 /* for MSR_AMD_10H_11H_LIMIT C001_0061 */
104 #define	AMD_10H_11H_GET_PSTATE_MAX_VAL(msr)	(((msr) >> 4) & 0x7)
105 #define	AMD_10H_11H_GET_PSTATE_LIMIT(msr)	(((msr)) & 0x7)
106 /* for MSR_AMD_10H_11H_CONFIG 10h:C001_0064:68 / 11h:C001_0064:6B */
107 #define	AMD_10H_11H_CUR_VID(msr)		(((msr) >> 9) & 0x7F)
108 #define	AMD_10H_11H_CUR_DID(msr)		(((msr) >> 6) & 0x07)
109 #define	AMD_10H_11H_CUR_FID(msr)		((msr) & 0x3F)
110 
111 #define	AMD_17H_CUR_IDIV(msr)			(((msr) >> 30) & 0x03)
112 #define	AMD_17H_CUR_IDD(msr)			(((msr) >> 22) & 0xFF)
113 #define	AMD_17H_CUR_VID(msr)			(((msr) >> 14) & 0xFF)
114 #define	AMD_17H_CUR_DID(msr)			(((msr) >> 8) & 0x3F)
115 #define	AMD_17H_CUR_FID(msr)			((msr) & 0xFF)
116 
117 #define	AMD_1AH_CUR_FID(msr)			((msr) & 0xFFF)
118 
119 #define	AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS	0xff000000
120 #define	AMD_CPPC_CAPS_1_NOMINAL_PERF_BITS	0x00ff0000
121 #define	AMD_CPPC_CAPS_1_EFFICIENT_PERF_BITS	0x0000ff00
122 #define	AMD_CPPC_CAPS_1_LOWEST_PERF_BITS	0x000000ff
123 
124 #define	AMD_CPPC_REQUEST_EPP_BITS		0xff000000
125 #define	AMD_CPPC_REQUEST_DES_PERF_BITS		0x00ff0000
126 #define	AMD_CPPC_REQUEST_MIN_PERF_BITS		0x0000ff00
127 #define	AMD_CPPC_REQUEST_MAX_PERF_BITS		0x000000ff
128 
129 #define	HWP_AMD_CLASSNAME			"hwpstate_amd"
130 
131 #define	BITS_VALUE(bits, val)						\
132 	(((val) & (bits)) >> (ffsll((bits)) - 1))
133 #define	BITS_WITH_VALUE(bits, val)					\
134 	(((uintmax_t)(val) << (ffsll((bits)) - 1)) & (bits))
135 #define	SET_BITS_VALUE(var, bits, val)					\
136 	((var) = ((var) & ~(bits)) | BITS_WITH_VALUE((bits), (val)))
137 
138 #define	HWPSTATE_DEBUG(dev, msg...)			\
139 	do {						\
140 		if (hwpstate_verbose)			\
141 			device_printf(dev, msg);	\
142 	} while (0)
143 
144 struct hwpstate_setting {
145 	int	freq;		/* CPU clock in Mhz or 100ths of a percent. */
146 	int	volts;		/* Voltage in mV. */
147 	int	power;		/* Power consumed in mW. */
148 	int	lat;		/* Transition latency in us. */
149 	int	pstate_id;	/* P-State id */
150 };
151 
152 #define HWPFL_USE_CPPC			(1 << 0)
153 #define HWPFL_CPPC_REQUEST_NOT_READ	(1 << 1)
154 
155 struct hwpstate_cpufreq_methods {
156 	int (*get)(device_t dev, struct cf_setting *cf);
157 	int (*set)(device_t dev, const struct cf_setting *cf);
158 	int (*settings)(device_t dev, struct cf_setting *sets, int *count);
159 	int (*type)(device_t dev, int *type);
160 };
161 
162 /*
163  * Atomicity is achieved by only modifying a given softc on its associated CPU
164  * and with interrupts disabled.
165  *
166  * XXX - Only the CPPC support complies at the moment.
167  */
168 struct hwpstate_softc {
169 	device_t	dev;
170 	u_int		flags;
171 	const struct hwpstate_cpufreq_methods *cpufreq_methods;
172 	union {
173 		struct {
174 			struct hwpstate_setting
175 			hwpstate_settings[AMD_10H_11H_MAX_STATES];
176 			int cfnum;
177 		};
178 		struct {
179 			uint64_t request;
180 		} cppc;
181 	};
182 	u_int		cpuid;
183 };
184 
185 static void	hwpstate_identify(driver_t *driver, device_t parent);
186 static int	hwpstate_probe(device_t dev);
187 static int	hwpstate_attach(device_t dev);
188 static int	hwpstate_detach(device_t dev);
189 static int	hwpstate_set(device_t dev, const struct cf_setting *cf);
190 static int	hwpstate_get(device_t dev, struct cf_setting *cf);
191 static int	hwpstate_settings(device_t dev, struct cf_setting *sets, int *count);
192 static int	hwpstate_type(device_t dev, int *type);
193 static int	hwpstate_shutdown(device_t dev);
194 static int	hwpstate_features(driver_t *driver, u_int *features);
195 static int	hwpstate_get_info_from_acpi_perf(device_t dev, device_t perf_dev);
196 static int	hwpstate_get_info_from_msr(device_t dev);
197 static int	hwpstate_goto_pstate(device_t dev, int pstate_id);
198 
199 static int	hwpstate_verify;
200 SYSCTL_INT(_debug, OID_AUTO, hwpstate_verify, CTLFLAG_RWTUN,
201     &hwpstate_verify, 0, "Verify P-state after setting");
202 
203 static bool	hwpstate_pstate_limit;
204 SYSCTL_BOOL(_debug, OID_AUTO, hwpstate_pstate_limit, CTLFLAG_RWTUN,
205     &hwpstate_pstate_limit, 0,
206     "If enabled (1), limit administrative control of P-states to the value in "
207     "CurPstateLimit");
208 
209 static bool	hwpstate_amd_cppc_enable = true;
210 SYSCTL_BOOL(_machdep, OID_AUTO, hwpstate_amd_cppc_enable, CTLFLAG_RDTUN,
211     &hwpstate_amd_cppc_enable, 0,
212     "Set 1 (default) to enable AMD CPPC, 0 to disable");
213 
214 static device_method_t hwpstate_methods[] = {
215 	/* Device interface */
216 	DEVMETHOD(device_identify,	hwpstate_identify),
217 	DEVMETHOD(device_probe,		hwpstate_probe),
218 	DEVMETHOD(device_attach,	hwpstate_attach),
219 	DEVMETHOD(device_detach,	hwpstate_detach),
220 	DEVMETHOD(device_shutdown,	hwpstate_shutdown),
221 
222 	/* cpufreq interface */
223 	DEVMETHOD(cpufreq_drv_set,	hwpstate_set),
224 	DEVMETHOD(cpufreq_drv_get,	hwpstate_get),
225 	DEVMETHOD(cpufreq_drv_settings,	hwpstate_settings),
226 	DEVMETHOD(cpufreq_drv_type,	hwpstate_type),
227 
228 	/* ACPI interface */
229 	DEVMETHOD(acpi_get_features,	hwpstate_features),
230 	{0, 0}
231 };
232 
233 static inline void
check_cppc_in_use(const struct hwpstate_softc * const sc,const char * const func)234 check_cppc_in_use(const struct hwpstate_softc *const sc, const char *const func)
235 {
236 	KASSERT((sc->flags & HWPFL_USE_CPPC) != 0, (HWP_AMD_CLASSNAME
237 	    ": %s() called but HWPFL_USE_CPPC not set", func));
238 }
239 
240 static void
print_msr_bits(struct sbuf * const sb,const char * const legend,const uint64_t bits,const uint64_t msr_value)241 print_msr_bits(struct sbuf *const sb, const char *const legend,
242     const uint64_t bits, const uint64_t msr_value)
243 {
244 	sbuf_printf(sb, "\t%s: %" PRIu64 "\n", legend,
245 	    BITS_VALUE(bits, msr_value));
246 }
247 
248 static void
print_cppc_caps_1(struct sbuf * const sb,const uint64_t caps)249 print_cppc_caps_1(struct sbuf *const sb, const uint64_t caps)
250 {
251 	sbuf_printf(sb, MSR_AMD_CPPC_CAPS_1_NAME ": %#016" PRIx64 "\n", caps);
252 	print_msr_bits(sb, "Highest Performance",
253 	    AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, caps);
254 	print_msr_bits(sb, "Guaranteed Performance",
255 	    AMD_CPPC_CAPS_1_NOMINAL_PERF_BITS, caps);
256 	print_msr_bits(sb, "Efficient Performance",
257 	    AMD_CPPC_CAPS_1_EFFICIENT_PERF_BITS, caps);
258 	print_msr_bits(sb, "Lowest Performance",
259 	    AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, caps);
260 }
261 
262 #define MSR_NOT_READ_MSG	"Not read (fault or previous errors)"
263 
264 static void
print_cppc_no_caps_1(struct sbuf * const sb)265 print_cppc_no_caps_1(struct sbuf *const sb)
266 {
267 	sbuf_printf(sb, MSR_AMD_CPPC_CAPS_1_NAME ": " MSR_NOT_READ_MSG "\n");
268 }
269 
270 static void
print_cppc_request(struct sbuf * const sb,const uint64_t request)271 print_cppc_request(struct sbuf *const sb, const uint64_t request)
272 {
273 	sbuf_printf(sb, MSR_AMD_CPPC_REQUEST_NAME ": %#016" PRIx64 "\n",
274 	    request);
275 	print_msr_bits(sb, "Efficiency / Energy Preference",
276 	    AMD_CPPC_REQUEST_EPP_BITS, request);
277 	print_msr_bits(sb, "Desired Performance",
278 	    AMD_CPPC_REQUEST_DES_PERF_BITS, request);
279 	print_msr_bits(sb, "Minimum Performance",
280 	    AMD_CPPC_REQUEST_MIN_PERF_BITS, request);
281 	print_msr_bits(sb, "Maximum Performance",
282 	    AMD_CPPC_REQUEST_MAX_PERF_BITS, request);
283 }
284 
285 static void
print_cppc_no_request(struct sbuf * const sb)286 print_cppc_no_request(struct sbuf *const sb)
287 {
288 	sbuf_printf(sb, MSR_AMD_CPPC_REQUEST_NAME ": " MSR_NOT_READ_MSG "\n");
289 }
290 
291 /*
292  * Internal errors conveyed by code executing on another CPU.
293  */
294 #define HWP_ERROR_CPPC_ENABLE		(1 << 0)
295 #define HWP_ERROR_CPPC_CAPS		(1 << 1)
296 #define HWP_ERROR_CPPC_REQUEST		(1 << 2)
297 #define HWP_ERROR_CPPC_REQUEST_WRITE	(1 << 3)
298 
299 static inline bool
hwp_has_error(u_int res,u_int err)300 hwp_has_error(u_int res, u_int err)
301 {
302 	return ((res & err) != 0);
303 }
304 
305 struct get_cppc_regs_data {
306 	uint64_t enable;
307 	uint64_t caps;
308 	uint64_t req;
309 	/* HWP_ERROR_CPPC_* except HWP_ERROR_*_WRITE */
310 	u_int res;
311 };
312 
313 static void
get_cppc_regs_cb(void * args)314 get_cppc_regs_cb(void *args)
315 {
316 	struct get_cppc_regs_data *data = args;
317 	int error;
318 
319 	data->res = 0;
320 
321 	error = rdmsr_safe(MSR_AMD_CPPC_ENABLE, &data->enable);
322 	if (error != 0)
323 		data->res |= HWP_ERROR_CPPC_ENABLE;
324 
325 	error = rdmsr_safe(MSR_AMD_CPPC_CAPS_1, &data->caps);
326 	if (error != 0)
327 		data->res |= HWP_ERROR_CPPC_CAPS;
328 
329 	error = rdmsr_safe(MSR_AMD_CPPC_REQUEST, &data->req);
330 	if (error != 0)
331 		data->res |= HWP_ERROR_CPPC_REQUEST;
332 }
333 
334 /*
335  * Debug: Read all MSRs (bypassing the softc) and dump them.
336  */
337 static int
sysctl_cppc_dump_handler(SYSCTL_HANDLER_ARGS)338 sysctl_cppc_dump_handler(SYSCTL_HANDLER_ARGS)
339 {
340 	const struct hwpstate_softc *const sc = arg1;
341 	struct sbuf *sb;
342 	struct sbuf sbs;
343 	struct get_cppc_regs_data data;
344 	int error;
345 
346 	/* Sysctl knob does not exist if HWPFL_USE_CPPC is not set. */
347 	check_cppc_in_use(sc, __func__);
348 
349 	sb = sbuf_new_for_sysctl(&sbs, NULL, 0, req);
350 
351 	smp_rendezvous_cpu(sc->cpuid, smp_no_rendezvous_barrier,
352 	    get_cppc_regs_cb, smp_no_rendezvous_barrier, &data);
353 
354 	if (hwp_has_error(data.res, HWP_ERROR_CPPC_ENABLE))
355 		sbuf_printf(sb, "CPU%u: " MSR_AMD_CPPC_ENABLE_NAME ": "
356 		    MSR_NOT_READ_MSG "\n", sc->cpuid);
357 	else
358 		sbuf_printf(sb, "CPU%u: HWP %sabled (" MSR_AMD_CPPC_REQUEST_NAME
359 		    ": %#" PRIx64 ")\n", sc->cpuid, data.enable & 1 ?
360 		    "En" : "Dis", data.enable);
361 
362 	if (hwp_has_error(data.res, HWP_ERROR_CPPC_CAPS))
363 		print_cppc_no_caps_1(sb);
364 	else
365 		print_cppc_caps_1(sb, data.caps);
366 
367 	if (hwp_has_error(data.res, HWP_ERROR_CPPC_REQUEST))
368 		print_cppc_no_request(sb);
369 	else
370 		print_cppc_request(sb, data.req);
371 
372 	error = sbuf_finish(sb);
373 	sbuf_delete(sb);
374 
375 	return (error);
376 }
377 
378 /*
379  * Read CPPC_REQUEST's value in the softc, if not already present.
380  */
381 static int
get_cppc_request(struct hwpstate_softc * const sc)382 get_cppc_request(struct hwpstate_softc *const sc)
383 {
384 	uint64_t val;
385 	int error;
386 
387 	check_cppc_in_use(sc, __func__);
388 
389 	if ((sc->flags & HWPFL_CPPC_REQUEST_NOT_READ) != 0) {
390 		error = rdmsr_safe(MSR_AMD_CPPC_REQUEST, &val);
391 		if (error != 0)
392 			return (EIO);
393 		sc->flags &= ~HWPFL_CPPC_REQUEST_NOT_READ;
394 		sc->cppc.request = val;
395 	}
396 
397 	return (0);
398 }
399 
400 struct set_cppc_request_cb {
401 	struct hwpstate_softc	*sc;
402 	uint64_t		 request;
403 	uint64_t		 mask;
404 	int			 res; /* 0 or HWP_ERROR_CPPC_REQUEST* */
405 };
406 
407 static void
set_cppc_request_cb(void * args)408 set_cppc_request_cb(void *args)
409 {
410 	struct set_cppc_request_cb *const data = args;
411 	uint64_t *const sc_req = &data->sc->cppc.request;
412 	uint64_t new_req;
413 	int error;
414 
415 	/* We proceed sequentially, so we'll clear out errors on progress. */
416 	data->res = HWP_ERROR_CPPC_REQUEST | HWP_ERROR_CPPC_REQUEST_WRITE;
417 
418 	error = get_cppc_request(data->sc);
419 	if (error != 0)
420 		return;
421 	data->res &= ~HWP_ERROR_CPPC_REQUEST;
422 
423 	new_req = (*sc_req & ~data->mask) | (data->request & data->mask);
424 
425 	error = wrmsr_safe(MSR_AMD_CPPC_REQUEST, new_req);
426 	if (error != 0)
427 		return;
428 	data->res &= ~HWP_ERROR_CPPC_REQUEST_WRITE;
429 	*sc_req = new_req;
430 }
431 
432 static inline void
set_cppc_request_send_one(struct set_cppc_request_cb * const data,device_t dev)433 set_cppc_request_send_one(struct set_cppc_request_cb *const data, device_t dev)
434 {
435 	data->sc = device_get_softc(dev);
436 	smp_rendezvous_cpu(data->sc->cpuid, smp_no_rendezvous_barrier,
437 	    set_cppc_request_cb, smp_no_rendezvous_barrier, data);
438 }
439 
440 static inline void
set_cppc_request_update_error(const struct set_cppc_request_cb * const data,int * const error)441 set_cppc_request_update_error(const struct set_cppc_request_cb *const data,
442     int *const error)
443 {
444 	/* A read error has precedence on a write error. */
445 	if (hwp_has_error(data->res, HWP_ERROR_CPPC_REQUEST))
446 		*error = EIO;
447 	else if (hwp_has_error(data->res, HWP_ERROR_CPPC_REQUEST_WRITE) &&
448 	    *error != EIO)
449 		*error = EOPNOTSUPP;
450 	else if (data->res != 0)
451 		/* Fallback case (normally not needed; defensive). */
452 		*error = EFAULT;
453 }
454 
455 static int
set_cppc_request(device_t hwp_dev,uint64_t request,uint64_t mask)456 set_cppc_request(device_t hwp_dev, uint64_t request, uint64_t mask)
457 {
458 	struct set_cppc_request_cb data = {
459 		.request = request,
460 		.mask = mask,
461 		/* 'sc' filled by set_cppc_request_send_one(). */
462 	};
463 	int error = 0;
464 
465 	if (hwpstate_pkg_ctrl_enable) {
466 		const devclass_t dc = devclass_find(HWP_AMD_CLASSNAME);
467 		const int units = devclass_get_maxunit(dc);
468 
469 		for (int i = 0; i < units; ++i) {
470 			const device_t dev = devclass_get_device(dc, i);
471 
472 			set_cppc_request_send_one(&data, dev);
473 			/* Note errors, but always continue. */
474 			set_cppc_request_update_error(&data, &error);
475 		}
476 	} else {
477 		set_cppc_request_send_one(&data, hwp_dev);
478 		set_cppc_request_update_error(&data, &error);
479 	}
480 
481 	return (error);
482 }
483 
484 static void
get_cppc_request_cb(void * args)485 get_cppc_request_cb(void *args)
486 {
487 	struct hwpstate_softc *const sc = args;
488 
489 	(void)get_cppc_request(sc);
490 }
491 
492 static int
sysctl_cppc_request_field_handler(SYSCTL_HANDLER_ARGS)493 sysctl_cppc_request_field_handler(SYSCTL_HANDLER_ARGS)
494 {
495 	const u_int max = BITS_VALUE(arg2, (uint64_t)-1);
496 	const device_t dev = arg1;
497 	struct hwpstate_softc *const sc = device_get_softc(dev);
498 	u_int val;
499 	int error;
500 
501 	/* Sysctl knob does not exist if HWPFL_USE_CPPC is not set. */
502 	check_cppc_in_use(sc, __func__);
503 
504 	if ((sc->flags & HWPFL_CPPC_REQUEST_NOT_READ) != 0) {
505 		smp_rendezvous_cpu(sc->cpuid, smp_no_rendezvous_barrier,
506 		    get_cppc_request_cb, smp_no_rendezvous_barrier, sc);
507 
508 		if ((sc->flags & HWPFL_CPPC_REQUEST_NOT_READ) != 0)
509 			return (EIO);
510 	}
511 
512 	val = BITS_VALUE(arg2, sc->cppc.request);
513 
514 	error = sysctl_handle_int(oidp, &val, 0, req);
515 	if (error != 0 || req->newptr == NULL)
516 		return (error);
517 
518 	if (val > max)
519 		return (EINVAL);
520 	error = set_cppc_request(dev, BITS_WITH_VALUE(arg2, val),
521 	    BITS_WITH_VALUE(arg2, -1));
522 	return (error);
523 }
524 
525 static driver_t hwpstate_driver = {
526 	HWP_AMD_CLASSNAME,
527 	hwpstate_methods,
528 	sizeof(struct hwpstate_softc),
529 };
530 
531 DRIVER_MODULE(hwpstate, cpu, hwpstate_driver, 0, 0);
532 
533 static int
hwpstate_amd_iscale(int val,int div)534 hwpstate_amd_iscale(int val, int div)
535 {
536 	switch (div) {
537 	case 3: /* divide by 1000 */
538 		val /= 10;
539 	case 2: /* divide by 100 */
540 		val /= 10;
541 	case 1: /* divide by 10 */
542 		val /= 10;
543 	case 0: /* divide by 1 */
544 	    ;
545 	}
546 
547 	return (val);
548 }
549 
550 static void
hwpstate_pstate_read_limit(u_int cpuid,uint64_t * msr)551 hwpstate_pstate_read_limit(u_int cpuid, uint64_t *msr)
552 {
553 	(void)x86_msr_op(MSR_AMD_10H_11H_LIMIT,
554 	    MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpuid),
555 	    0, msr);
556 }
557 
558 static void
hwpstate_pstate_read_status(u_int cpuid,uint64_t * msr)559 hwpstate_pstate_read_status(u_int cpuid, uint64_t *msr)
560 {
561 	(void)x86_msr_op(MSR_AMD_10H_11H_STATUS,
562 	    MSR_OP_READ | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpuid),
563 	    0, msr);
564 }
565 
566 /*
567  * Go to Px-state on all cpus, considering the limit register (if so
568  * configured).
569  */
570 static int
hwpstate_goto_pstate(device_t dev,int id)571 hwpstate_goto_pstate(device_t dev, int id)
572 {
573 	const struct hwpstate_softc *const sc = device_get_softc(dev);
574 	const u_int cpuid = sc->cpuid;
575 	uint64_t msr;
576 
577 	if (hwpstate_pstate_limit) {
578 		int limit;
579 
580 		/* get the current pstate limit */
581 		hwpstate_pstate_read_limit(cpuid, &msr);
582 		limit = AMD_10H_11H_GET_PSTATE_LIMIT(msr);
583 		if (limit > id) {
584 			HWPSTATE_DEBUG(dev, "Restricting requested P%d to P%d "
585 			    "due to HW limit\n", id, limit);
586 			id = limit;
587 		}
588 	}
589 
590 	HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, cpuid);
591 	/* Go To Px-state */
592 	x86_msr_op(MSR_AMD_10H_11H_CONTROL,
593 	    MSR_OP_WRITE | MSR_OP_RENDEZVOUS_ONE | MSR_OP_CPUID(cpuid),
594 	    id, NULL);
595 
596 	/*
597 	 * Verify whether each core is in the requested P-state.
598 	 */
599 	if (hwpstate_verify) {
600 		/* wait loop (100*100 usec is enough ?) */
601 		for (int j = 0; j < 100; j++) {
602 			sbintime_t sbt;
603 
604 			/* get the result. not assure msr=id */
605 			hwpstate_pstate_read_status(cpuid, &msr);
606 			if (msr == id)
607 				break;
608 			sbt = SBT_1MS / 10;
609 			tsleep_sbt(dev, PZERO, "pstate_goto", sbt,
610 			    sbt >> tc_precexp, 0);
611 		}
612 		HWPSTATE_DEBUG(dev, "result: P%d-state on cpu%d\n", (int)msr,
613 		    cpuid);
614 		if (msr != id) {
615 			HWPSTATE_DEBUG(dev, "error: loop is not enough.\n");
616 			return (ENXIO);
617 		}
618 	}
619 
620 	return (0);
621 }
622 
623 static int
hwpstate_set_cppc(device_t dev __unused,const struct cf_setting * cf __unused)624 hwpstate_set_cppc(device_t dev __unused, const struct cf_setting *cf __unused)
625 {
626 	return (EOPNOTSUPP);
627 }
628 
629 static int
hwpstate_set_pstate(device_t dev,const struct cf_setting * cf)630 hwpstate_set_pstate(device_t dev, const struct cf_setting *cf)
631 {
632 	struct hwpstate_softc *sc;
633 	struct hwpstate_setting *set;
634 	int i;
635 
636 	sc = device_get_softc(dev);
637 	set = sc->hwpstate_settings;
638 	for (i = 0; i < sc->cfnum; i++)
639 		if (CPUFREQ_CMP(cf->freq, set[i].freq))
640 			break;
641 	if (i == sc->cfnum)
642 		return (EINVAL);
643 	return (hwpstate_goto_pstate(dev, set[i].pstate_id));
644 }
645 
646 static int
hwpstate_set(device_t dev,const struct cf_setting * cf)647 hwpstate_set(device_t dev, const struct cf_setting *cf)
648 {
649 	struct hwpstate_softc *sc = device_get_softc(dev);
650 
651 	if (cf == NULL)
652 		return (EINVAL);
653 	return (sc->cpufreq_methods->set(dev, cf));
654 }
655 
656 static int
hwpstate_get_cppc(device_t dev,struct cf_setting * cf)657 hwpstate_get_cppc(device_t dev, struct cf_setting *cf)
658 {
659 	const struct hwpstate_softc *const sc = device_get_softc(dev);
660 	uint64_t rate;
661 	int ret;
662 
663 	memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
664 	cf->dev = dev;
665 	if ((ret = cpu_est_clockrate(sc->cpuid, &rate)))
666 		return (ret);
667 	cf->freq = rate / 1000000;
668 	return (0);
669 }
670 
671 static int
hwpstate_get_pstate(device_t dev,struct cf_setting * cf)672 hwpstate_get_pstate(device_t dev, struct cf_setting *cf)
673 {
674 	const struct hwpstate_softc *const sc = device_get_softc(dev);
675 	struct hwpstate_setting set;
676 	uint64_t msr;
677 
678 	hwpstate_pstate_read_status(sc->cpuid, &msr);
679 	if (msr >= sc->cfnum)
680 		return (EINVAL);
681 	set = sc->hwpstate_settings[msr];
682 	cf->freq = set.freq;
683 	cf->volts = set.volts;
684 	cf->power = set.power;
685 	cf->lat = set.lat;
686 	cf->dev = dev;
687 
688 	return (0);
689 }
690 
691 static int
hwpstate_get(device_t dev,struct cf_setting * cf)692 hwpstate_get(device_t dev, struct cf_setting *cf)
693 {
694 	struct hwpstate_softc *sc;
695 
696 	sc = device_get_softc(dev);
697 	if (cf == NULL)
698 		return (EINVAL);
699 	return (sc->cpufreq_methods->get(dev, cf));
700 }
701 
702 static int
hwpstate_settings_cppc(device_t dev __unused,struct cf_setting * sets __unused,int * count __unused)703 hwpstate_settings_cppc(device_t dev __unused, struct cf_setting *sets __unused,
704     int *count __unused)
705 {
706 	return (EOPNOTSUPP);
707 }
708 
709 static int
hwpstate_settings_pstate(device_t dev,struct cf_setting * sets,int * count)710 hwpstate_settings_pstate(device_t dev, struct cf_setting *sets, int *count)
711 {
712 	struct hwpstate_setting set;
713 	struct hwpstate_softc *sc;
714 	int i;
715 
716 	sc = device_get_softc(dev);
717 	if (*count < sc->cfnum)
718 		return (E2BIG);
719 	for (i = 0; i < sc->cfnum; i++, sets++) {
720 		set = sc->hwpstate_settings[i];
721 		sets->freq = set.freq;
722 		sets->volts = set.volts;
723 		sets->power = set.power;
724 		sets->lat = set.lat;
725 		sets->dev = dev;
726 	}
727 	*count = sc->cfnum;
728 
729 	return (0);
730 }
731 
732 static int
hwpstate_settings(device_t dev,struct cf_setting * sets,int * count)733 hwpstate_settings(device_t dev, struct cf_setting *sets, int *count)
734 {
735 	struct hwpstate_softc *sc;
736 
737 	if (sets == NULL || count == NULL)
738 		return (EINVAL);
739 	sc = device_get_softc(dev);
740 	return (sc->cpufreq_methods->settings(dev, sets, count));
741 }
742 
743 static int
hwpstate_type_cppc(device_t dev,int * type)744 hwpstate_type_cppc(device_t dev, int *type)
745 {
746 	*type = CPUFREQ_TYPE_ABSOLUTE | CPUFREQ_FLAG_INFO_ONLY |
747 	    CPUFREQ_FLAG_UNCACHED;
748 	return (0);
749 }
750 
751 static int
hwpstate_type_pstate(device_t dev,int * type)752 hwpstate_type_pstate(device_t dev, int *type)
753 {
754 	*type = CPUFREQ_TYPE_ABSOLUTE;
755 	return (0);
756 }
757 
758 static int
hwpstate_type(device_t dev,int * type)759 hwpstate_type(device_t dev, int *type)
760 {
761 	struct hwpstate_softc *sc;
762 
763 	sc = device_get_softc(dev);
764 	return (sc->cpufreq_methods->type(dev, type));
765 }
766 
767 static void
hwpstate_identify(driver_t * driver,device_t parent)768 hwpstate_identify(driver_t *driver, device_t parent)
769 {
770 	if (device_find_child(parent, HWP_AMD_CLASSNAME, DEVICE_UNIT_ANY) !=
771 	    NULL)
772 		return;
773 
774 	if ((cpu_vendor_id != CPU_VENDOR_AMD || CPUID_TO_FAMILY(cpu_id) < 0x10) &&
775 	    cpu_vendor_id != CPU_VENDOR_HYGON)
776 		return;
777 
778 	/*
779 	 * Check if hardware pstate enable bit is set.
780 	 */
781 	if ((amd_pminfo & AMDPM_HW_PSTATE) == 0) {
782 		HWPSTATE_DEBUG(parent, "hwpstate enable bit is not set.\n");
783 		return;
784 	}
785 
786 	if (resource_disabled(HWP_AMD_CLASSNAME, 0))
787 		return;
788 
789 	if (BUS_ADD_CHILD(parent, 10, HWP_AMD_CLASSNAME,
790 		device_get_unit(parent)) == NULL)
791 		device_printf(parent, "hwpstate: add child failed\n");
792 }
793 
794 struct enable_cppc_data {
795 	/* Inputs */
796 	struct hwpstate_softc *sc;
797 	/* Outputs */
798 	/* HWP_ERROR_CPPC_* */
799 	u_int res;
800 	/* Below fields filled depending on 'res'. */
801 	uint64_t caps;
802 	uint64_t init_request;
803 	uint64_t request;
804 };
805 
806 static void
enable_cppc_cb(void * args)807 enable_cppc_cb(void *args)
808 {
809 	struct enable_cppc_data *const data = args;
810 	struct hwpstate_softc *const sc = data->sc;
811 	uint64_t lowest_perf, highest_perf;
812 	int error;
813 
814 	/*
815 	 * We proceed mostly sequentially, so we'll clear out errors on
816 	 * progress.
817 	 */
818 	data->res = HWP_ERROR_CPPC_ENABLE | HWP_ERROR_CPPC_CAPS |
819 	    HWP_ERROR_CPPC_REQUEST | HWP_ERROR_CPPC_REQUEST_WRITE;
820 
821 	sc->flags |= HWPFL_CPPC_REQUEST_NOT_READ;
822 
823 	error = wrmsr_safe(MSR_AMD_CPPC_ENABLE, 1);
824 	if (error != 0)
825 		return;
826 	data->res &= ~HWP_ERROR_CPPC_ENABLE;
827 
828 	error = rdmsr_safe(MSR_AMD_CPPC_CAPS_1, &data->caps);
829 	/* We can do away without CAPABILITY_1, so just continue on error. */
830 	if (error == 0)
831 		data->res &= ~HWP_ERROR_CPPC_CAPS;
832 
833 	error = get_cppc_request(sc);
834 	if (error != 0)
835 		return;
836 	data->res &= ~HWP_ERROR_CPPC_REQUEST;
837 	data->init_request = sc->cppc.request;
838 
839 	data->request = sc->cppc.request;
840 	/*
841 	 * Assuming reading MSR_AMD_CPPC_CAPS_1 succeeded, if it stays at its
842 	 * reset value (0) before CPPC activation (not supposed to happen, but
843 	 * happens in the field), we use reasonable default values that are
844 	 * explicitly described by the ACPI spec (all 0s for the minimum value,
845 	 * all 1s for the maximum one).  Going further, we actually do the same
846 	 * as long as the minimum and maximum performance levels are not sorted
847 	 * or are equal (in which case CPPC is not supposed to make sense at
848 	 * all), which covers the reset value case.  And we also fallback to
849 	 * these if MSR_AMD_CPPC_CAPS_1 could not be read at all.
850 	 */
851 	lowest_perf = 0;
852 	highest_perf = -1;
853 	if (!hwp_has_error(data->res, HWP_ERROR_CPPC_CAPS)) {
854 		const uint64_t lowest_cand =
855 		    BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, data->caps);
856 		const uint64_t highest_cand =
857 		    BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, data->caps);
858 
859 		if (lowest_cand < highest_cand) {
860 			lowest_perf = lowest_cand;
861 			highest_perf = highest_cand;
862 		}
863 	}
864 	SET_BITS_VALUE(data->request, AMD_CPPC_REQUEST_MIN_PERF_BITS,
865 	    lowest_perf);
866 	SET_BITS_VALUE(data->request, AMD_CPPC_REQUEST_MAX_PERF_BITS,
867 	    highest_perf);
868 	/*
869 	 * Set controls to maximum performance to avoid regressions now that
870 	 * CPPC is activated by default and to match what the P-state support
871 	 * does.
872 	 */
873 	SET_BITS_VALUE(data->request, AMD_CPPC_REQUEST_EPP_BITS, 0);
874 	/* 0 in "Desired Performance" is autonomous mode. */
875 	MPASS(highest_perf != 0);
876 	SET_BITS_VALUE(data->request, AMD_CPPC_REQUEST_DES_PERF_BITS,
877 	    highest_perf);
878 
879 	error = wrmsr_safe(MSR_AMD_CPPC_REQUEST, data->request);
880 	if (error != 0)
881 		return;
882 	data->res &= ~HWP_ERROR_CPPC_REQUEST_WRITE;
883 	sc->cppc.request = data->request;
884 }
885 
886 static int
enable_cppc(struct hwpstate_softc * sc)887 enable_cppc(struct hwpstate_softc *sc)
888 {
889 	const device_t dev = sc->dev;
890 	const u_int cpuid = sc->cpuid;
891 	struct enable_cppc_data data;
892 	struct sbuf sbs;
893 	struct sbuf *sb;
894 
895 	data.sc = sc;
896 	smp_rendezvous_cpu(cpuid, smp_no_rendezvous_barrier,
897 	    enable_cppc_cb, smp_no_rendezvous_barrier, &data);
898 
899 	if (hwp_has_error(data.res, HWP_ERROR_CPPC_ENABLE)) {
900 		device_printf(dev, "CPU%u: Failed to enable CPPC!\n", cpuid);
901 		return (ENXIO);
902 	}
903 	device_printf(dev, "CPU%u: CPPC enabled.\n", cpuid);
904 
905 	/*
906 	 * Now that we have enabled CPPC, we can't go back (hardware does not
907 	 * support doing so), so we'll attach even in case of further
908 	 * malfunction, allowing the user to retry retrieving/setting MSRs via
909 	 * the sysctl knobs.
910 	 */
911 
912 	sb = sbuf_new(&sbs, NULL, 0, SBUF_AUTOEXTEND);
913 
914 	if (hwpstate_verbose)
915 		sbuf_printf(sb,
916 		    "CPU%u: Initial MSR values after CPPC enable:\n", cpuid);
917 	if (hwp_has_error(data.res, HWP_ERROR_CPPC_CAPS))
918 		print_cppc_no_caps_1(sb);
919 	else if (hwpstate_verbose)
920 		print_cppc_caps_1(sb, data.caps);
921 	if (hwp_has_error(data.res, HWP_ERROR_CPPC_REQUEST))
922 		print_cppc_no_request(sb);
923 	else if (hwpstate_verbose)
924 		print_cppc_request(sb, data.init_request);
925 	if (hwp_has_error(data.res, HWP_ERROR_CPPC_REQUEST_WRITE)) {
926 		const bool request_read = !hwp_has_error(data.res,
927 		    HWP_ERROR_CPPC_REQUEST);
928 
929 		/* This is printed first, as it is not printed into 'sb'. */
930 		device_printf(dev, "CPU%u: %s not write into "
931 		    MSR_AMD_CPPC_REQUEST_NAME "!\n", cpuid,
932 		    request_read ? "Could" : "Did");
933 		if (request_read) {
934 			sbuf_printf(sb, "CPU%u: Failed when trying to set:",
935 			    cpuid);
936 			print_cppc_request(sb, data.request);
937 		}
938 	} else if (hwpstate_verbose) {
939 		sbuf_printf(sb, "CPU%u: Tweaked MSR values:\n", cpuid);
940 		print_cppc_request(sb, data.request);
941 	}
942 
943 	sbuf_finish(sb);
944 	sbuf_putbuf(sb);
945 	sbuf_delete(sb);
946 
947 	return (0);
948 }
949 
950 static int
hwpstate_probe_pstate(device_t dev)951 hwpstate_probe_pstate(device_t dev)
952 {
953 	const struct hwpstate_softc *const sc = device_get_softc(dev);
954 	device_t perf_dev;
955 	int error, type;
956 	uint64_t msr;
957 
958 	/*
959 	 * Check if acpi_perf has INFO only flag.
960 	 */
961 	perf_dev = device_find_child(device_get_parent(dev), "acpi_perf",
962 	    DEVICE_UNIT_ANY);
963 	error = TRUE;
964 	if (perf_dev && device_is_attached(perf_dev)) {
965 		error = CPUFREQ_DRV_TYPE(perf_dev, &type);
966 		if (error == 0) {
967 			if ((type & CPUFREQ_FLAG_INFO_ONLY) == 0) {
968 				/*
969 				 * If acpi_perf doesn't have INFO_ONLY flag,
970 				 * it will take care of pstate transitions.
971 				 */
972 				HWPSTATE_DEBUG(dev, "acpi_perf will take care of pstate transitions.\n");
973 				return (ENXIO);
974 			}
975 			/*
976 			 * If acpi_perf has INFO_ONLY flag, (_PCT has FFixedHW)
977 			 * we can get _PSS info from acpi_perf
978 			 * without going into ACPI.
979 			 */
980 			HWPSTATE_DEBUG(dev,
981 			    "going to fetch info from acpi_perf\n");
982 			error = hwpstate_get_info_from_acpi_perf(dev, perf_dev);
983 		}
984 	}
985 
986 	if (error == 0) {
987 		/*
988 		 * Now we get _PSS info from acpi_perf without error.
989 		 * Let's check it.
990 		 */
991 		hwpstate_pstate_read_limit(sc->cpuid, &msr);
992 		if (sc->cfnum != 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr)) {
993 			HWPSTATE_DEBUG(dev, "MSR (%jd) and ACPI _PSS (%d)"
994 			    " count mismatch\n", (intmax_t)msr, sc->cfnum);
995 			error = TRUE;
996 		}
997 	}
998 
999 	/*
1000 	 * If we cannot get info from acpi_perf,
1001 	 * Let's get info from MSRs.
1002 	 */
1003 	if (error)
1004 		error = hwpstate_get_info_from_msr(dev);
1005 	return (error);
1006 }
1007 
1008 static const struct hwpstate_cpufreq_methods cppc_methods = {
1009 	.get = hwpstate_get_cppc,
1010 	.set = hwpstate_set_cppc,
1011 	.settings = hwpstate_settings_cppc,
1012 	.type = hwpstate_type_cppc
1013 };
1014 
1015 static const struct hwpstate_cpufreq_methods pstate_methods = {
1016 	.get = hwpstate_get_pstate,
1017 	.set = hwpstate_set_pstate,
1018 	.settings = hwpstate_settings_pstate,
1019 	.type = hwpstate_type_pstate
1020 };
1021 
1022 static int
hwpstate_probe(device_t dev)1023 hwpstate_probe(device_t dev)
1024 {
1025 	struct hwpstate_softc *const sc = device_get_softc(dev);
1026 
1027 	if (cpu_get_pcpu(dev) == NULL) {
1028 		device_printf(dev,
1029 		    "Parent bus does not provide a per-CPU structure!");
1030 		return (ENXIO);
1031 	}
1032 	sc->cpuid = cpu_get_pcpuid(dev);
1033 
1034 	if (hwpstate_amd_cppc_enable &&
1035 	    (amd_extended_feature_extensions & AMDFEID_CPPC)) {
1036 		sc->flags |= HWPFL_USE_CPPC;
1037 		device_set_desc(dev,
1038 		    "AMD Collaborative Processor Performance Control (CPPC)");
1039 	} else
1040 		device_set_desc(dev, "Cool`n'Quiet 2.0");
1041 
1042 	sc->dev = dev;
1043 	if ((sc->flags & HWPFL_USE_CPPC) != 0) {
1044 		sc->cpufreq_methods = &cppc_methods;
1045 		return (0);
1046 	}
1047 	sc->cpufreq_methods = &pstate_methods;
1048 	return (hwpstate_probe_pstate(dev));
1049 }
1050 
1051 static int
hwpstate_attach(device_t dev)1052 hwpstate_attach(device_t dev)
1053 {
1054 	struct hwpstate_softc *const sc = device_get_softc(dev);
1055 	int res;
1056 
1057 	if ((sc->flags & HWPFL_USE_CPPC) != 0) {
1058 		if ((res = enable_cppc(sc)) != 0)
1059 			return (res);
1060 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1061 		    SYSCTL_STATIC_CHILDREN(_debug), OID_AUTO,
1062 		    device_get_nameunit(dev),
1063 		    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP | CTLFLAG_MPSAFE,
1064 		    sc, 0, sysctl_cppc_dump_handler, "A", "");
1065 
1066 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1067 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1068 		    "epp", CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1069 		    dev, AMD_CPPC_REQUEST_EPP_BITS,
1070 		    sysctl_cppc_request_field_handler, "IU",
1071 		    "Efficiency/Performance Preference (from 0, "
1072 		    "most performant, to 255, most efficient)");
1073 
1074 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1075 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1076 		    "minimum_performance",
1077 		    CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1078 		    dev, AMD_CPPC_REQUEST_MIN_PERF_BITS,
1079 		    sysctl_cppc_request_field_handler, "IU",
1080 		    "Minimum allowed performance level (from 0 to 255; "
1081 		    "should be smaller than 'maximum_performance'; "
1082 		    "effective range limited by CPU)");
1083 
1084 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1085 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1086 		    "maximum_performance",
1087 		    CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1088 		    dev, AMD_CPPC_REQUEST_MAX_PERF_BITS,
1089 		    sysctl_cppc_request_field_handler, "IU",
1090 		    "Maximum allowed performance level (from 0 to 255; "
1091 		    "should be larger than 'minimum_performance'; "
1092 		    "effective range limited by CPU)");
1093 
1094 		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1095 		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
1096 		    "desired_performance",
1097 		    CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, dev,
1098 		    AMD_CPPC_REQUEST_DES_PERF_BITS,
1099 		    sysctl_cppc_request_field_handler, "IU",
1100 		    "Desired performance level (from 0 to 255; "
1101 		    "0 enables autonomous mode, otherwise value should be "
1102 		    "between 'minimum_performance' and 'maximum_performance' "
1103 		    "inclusive)");
1104 	}
1105 	return (cpufreq_register(dev));
1106 }
1107 
1108 struct hwpstate_pstate_read_settings_cb {
1109 	struct hwpstate_softc *sc;
1110 	uint64_t *vals;
1111 	int err;
1112 };
1113 
1114 static void
hwpstate_pstate_read_settings_cb(void * args)1115 hwpstate_pstate_read_settings_cb(void *args)
1116 {
1117 	struct hwpstate_pstate_read_settings_cb *req = args;
1118 	int i;
1119 
1120 	req->err = 0;
1121 	for (i = 0; i < req->sc->cfnum; i++) {
1122 		req->err = rdmsr_safe(MSR_AMD_10H_11H_CONFIG + i,
1123 		    &req->vals[i]);
1124 		if (req->err != 0)
1125 			return;
1126 	}
1127 }
1128 
1129 static int
hwpstate_pstate_read_settings(struct hwpstate_softc * sc,uint64_t vals[])1130 hwpstate_pstate_read_settings(struct hwpstate_softc *sc, uint64_t vals[])
1131 {
1132 	struct hwpstate_pstate_read_settings_cb req;
1133 
1134 	req.sc = sc;
1135 	req.vals = vals;
1136 	smp_rendezvous_cpu(sc->cpuid, smp_no_rendezvous_barrier,
1137 	    hwpstate_pstate_read_settings_cb, smp_no_rendezvous_barrier, &req);
1138 	return (req.err);
1139 }
1140 
1141 static int
hwpstate_get_info_from_msr(device_t dev)1142 hwpstate_get_info_from_msr(device_t dev)
1143 {
1144 	struct hwpstate_softc *const sc = device_get_softc(dev);
1145 	struct hwpstate_setting *hwpstate_set;
1146 	uint64_t state_settings[AMD_10H_11H_MAX_STATES], msr;
1147 	int family, i, fid, did;
1148 
1149 	family = CPUID_TO_FAMILY(cpu_id);
1150 	/* Get pstate count */
1151 	hwpstate_pstate_read_limit(sc->cpuid, &msr);
1152 	sc->cfnum = 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr);
1153 	hwpstate_set = sc->hwpstate_settings;
1154 	hwpstate_pstate_read_settings(sc, state_settings);
1155 	for (i = 0; i < sc->cfnum; i++) {
1156 		msr = state_settings[i];
1157 		if ((msr & ((uint64_t)1 << 63)) == 0) {
1158 			HWPSTATE_DEBUG(dev, "msr is not valid.\n");
1159 			return (ENXIO);
1160 		}
1161 		did = AMD_10H_11H_CUR_DID(msr);
1162 		fid = AMD_10H_11H_CUR_FID(msr);
1163 
1164 		hwpstate_set[i].volts = CPUFREQ_VAL_UNKNOWN;
1165 		hwpstate_set[i].power = CPUFREQ_VAL_UNKNOWN;
1166 		hwpstate_set[i].lat = CPUFREQ_VAL_UNKNOWN;
1167 		/* Convert fid/did to frequency. */
1168 		switch (family) {
1169 		case 0x11:
1170 			hwpstate_set[i].freq = (100 * (fid + 0x08)) >> did;
1171 			break;
1172 		case 0x10:
1173 		case 0x12:
1174 		case 0x15:
1175 		case 0x16:
1176 			hwpstate_set[i].freq = (100 * (fid + 0x10)) >> did;
1177 			break;
1178 		case 0x17:
1179 		case 0x18:
1180 		case 0x19:
1181 		case 0x1A:
1182 			/* calculate freq */
1183 			if (family == 0x1A) {
1184 				fid = AMD_1AH_CUR_FID(msr);
1185 				/* 1Ah CPU don't use a divisor */
1186 				hwpstate_set[i].freq = fid;
1187 				if (fid > 0x0f)
1188 					hwpstate_set[i].freq *= 5;
1189 				else {
1190 					HWPSTATE_DEBUG(dev,
1191 					    "unexpected fid: %d\n", fid);
1192 					return (ENXIO);
1193 				}
1194 			} else {
1195 				did = AMD_17H_CUR_DID(msr);
1196 				if (did == 0) {
1197 					HWPSTATE_DEBUG(dev,
1198 					    "unexpected did: 0\n");
1199 					did = 1;
1200 				}
1201 				fid = AMD_17H_CUR_FID(msr);
1202 				hwpstate_set[i].freq = (200 * fid) / did;
1203 			}
1204 
1205 			/* Vid step is 6.25mV, so scale by 100. */
1206 			hwpstate_set[i].volts =
1207 			    (155000 - (625 * AMD_17H_CUR_VID(msr))) / 100;
1208 			/*
1209 			 * Calculate current first.
1210 			 * This equation is mentioned in
1211 			 * "BKDG for AMD Family 15h Models 70h-7fh Processors",
1212 			 * section 2.5.2.1.6.
1213 			 */
1214 			hwpstate_set[i].power = AMD_17H_CUR_IDD(msr) * 1000;
1215 			hwpstate_set[i].power = hwpstate_amd_iscale(
1216 			    hwpstate_set[i].power, AMD_17H_CUR_IDIV(msr));
1217 			hwpstate_set[i].power *= hwpstate_set[i].volts;
1218 			/* Milli amps * milli volts to milli watts. */
1219 			hwpstate_set[i].power /= 1000;
1220 			break;
1221 		default:
1222 			HWPSTATE_DEBUG(dev, "get_info_from_msr: %s family"
1223 			    " 0x%02x CPUs are not supported yet\n",
1224 			    cpu_vendor_id == CPU_VENDOR_HYGON ? "Hygon" : "AMD",
1225 			    family);
1226 			return (ENXIO);
1227 		}
1228 		hwpstate_set[i].pstate_id = i;
1229 	}
1230 	return (0);
1231 }
1232 
1233 static int
hwpstate_get_info_from_acpi_perf(device_t dev,device_t perf_dev)1234 hwpstate_get_info_from_acpi_perf(device_t dev, device_t perf_dev)
1235 {
1236 	struct hwpstate_softc *sc;
1237 	struct cf_setting *perf_set;
1238 	struct hwpstate_setting *hwpstate_set;
1239 	int count, error, i;
1240 
1241 	perf_set = malloc(MAX_SETTINGS * sizeof(*perf_set), M_TEMP, M_NOWAIT);
1242 	if (perf_set == NULL) {
1243 		HWPSTATE_DEBUG(dev, "nomem\n");
1244 		return (ENOMEM);
1245 	}
1246 	/*
1247 	 * Fetch settings from acpi_perf.
1248 	 * Now it is attached, and has info only flag.
1249 	 */
1250 	count = MAX_SETTINGS;
1251 	error = CPUFREQ_DRV_SETTINGS(perf_dev, perf_set, &count);
1252 	if (error) {
1253 		HWPSTATE_DEBUG(dev, "error: CPUFREQ_DRV_SETTINGS.\n");
1254 		goto out;
1255 	}
1256 	sc = device_get_softc(dev);
1257 	sc->cfnum = count;
1258 	hwpstate_set = sc->hwpstate_settings;
1259 	for (i = 0; i < count; i++) {
1260 		if (i == perf_set[i].spec[0]) {
1261 			hwpstate_set[i].pstate_id = i;
1262 			hwpstate_set[i].freq = perf_set[i].freq;
1263 			hwpstate_set[i].volts = perf_set[i].volts;
1264 			hwpstate_set[i].power = perf_set[i].power;
1265 			hwpstate_set[i].lat = perf_set[i].lat;
1266 		} else {
1267 			HWPSTATE_DEBUG(dev, "ACPI _PSS object mismatch.\n");
1268 			error = ENXIO;
1269 			goto out;
1270 		}
1271 	}
1272 out:
1273 	if (perf_set)
1274 		free(perf_set, M_TEMP);
1275 	return (error);
1276 }
1277 
1278 static int
hwpstate_detach(device_t dev)1279 hwpstate_detach(device_t dev)
1280 {
1281 	struct hwpstate_softc *sc;
1282 
1283 	sc = device_get_softc(dev);
1284 	if ((sc->flags & HWPFL_USE_CPPC) == 0)
1285 		hwpstate_goto_pstate(dev, 0);
1286 	return (cpufreq_unregister(dev));
1287 }
1288 
1289 static int
hwpstate_shutdown(device_t dev)1290 hwpstate_shutdown(device_t dev)
1291 {
1292 
1293 	/* hwpstate_goto_pstate(dev, 0); */
1294 	return (0);
1295 }
1296 
1297 static int
hwpstate_features(driver_t * driver,u_int * features)1298 hwpstate_features(driver_t *driver, u_int *features)
1299 {
1300 
1301 	/* Notify the ACPI CPU that we support direct access to MSRs */
1302 	*features = ACPI_CAP_PERF_MSRS;
1303 	return (0);
1304 }
1305