Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/cpufreq/hwpstate_amd.c
| Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
| #include <sys/module.h> | #include <sys/module.h> | ||||
| #include <sys/malloc.h> | #include <sys/malloc.h> | ||||
| #include <sys/proc.h> | #include <sys/proc.h> | ||||
| #include <sys/pcpu.h> | #include <sys/pcpu.h> | ||||
| #include <sys/sbuf.h> | #include <sys/sbuf.h> | ||||
| #include <sys/smp.h> | #include <sys/smp.h> | ||||
| #include <sys/sched.h> | #include <sys/sched.h> | ||||
| #include <machine/_inttypes.h> | |||||
aokblast: Should we include this? | |||||
Done Inline ActionsYes, that's necessary for format specifiers such as PRIx64. olce: Yes, that's necessary for format specifiers such as `PRIx64`. | |||||
| #include <machine/md_var.h> | #include <machine/md_var.h> | ||||
| #include <machine/cputypes.h> | #include <machine/cputypes.h> | ||||
| #include <machine/specialreg.h> | #include <machine/specialreg.h> | ||||
| #include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
| #include <dev/acpica/acpivar.h> | #include <dev/acpica/acpivar.h> | ||||
| #include <x86/cpufreq/hwpstate_common.h> | #include <x86/cpufreq/hwpstate_common.h> | ||||
| #include "acpi_if.h" | #include "acpi_if.h" | ||||
| #include "cpufreq_if.h" | #include "cpufreq_if.h" | ||||
| #define MSR_AMD_10H_11H_LIMIT 0xc0010061 | #define MSR_AMD_10H_11H_LIMIT 0xc0010061 | ||||
| #define MSR_AMD_10H_11H_CONTROL 0xc0010062 | #define MSR_AMD_10H_11H_CONTROL 0xc0010062 | ||||
| #define MSR_AMD_10H_11H_STATUS 0xc0010063 | #define MSR_AMD_10H_11H_STATUS 0xc0010063 | ||||
| #define MSR_AMD_10H_11H_CONFIG 0xc0010064 | #define MSR_AMD_10H_11H_CONFIG 0xc0010064 | ||||
| #define MSR_AMD_CPPC_CAPS_1 0xc00102b0 | #define MSR_AMD_CPPC_CAPS_1 0xc00102b0 | ||||
| #define MSR_AMD_CPPC_ENABLE 0xc00102b1 | #define MSR_AMD_CPPC_ENABLE 0xc00102b1 | ||||
| #define MSR_AMD_CPPC_CAPS_2 0xc00102b2 | #define MSR_AMD_CPPC_CAPS_2 0xc00102b2 | ||||
| #define MSR_AMD_CPPC_REQUEST 0xc00102b3 | #define MSR_AMD_CPPC_REQUEST 0xc00102b3 | ||||
| #define MSR_AMD_CPPC_STATUS 0xc00102b4 | #define MSR_AMD_CPPC_STATUS 0xc00102b4 | ||||
| #define MSR_AMD_CPPC_CAPS_1_NAME "CPPC_CAPABILITY_1" | |||||
| #define MSR_AMD_CPPC_REQUEST_NAME "CPPC_REQUEST" | |||||
| #define MSR_AMD_PWR_ACC 0xc001007a | #define MSR_AMD_PWR_ACC 0xc001007a | ||||
| #define MSR_AMD_PWR_ACC_MX 0xc001007b | #define MSR_AMD_PWR_ACC_MX 0xc001007b | ||||
| #define AMD_10H_11H_MAX_STATES 16 | #define AMD_10H_11H_MAX_STATES 16 | ||||
| /* for MSR_AMD_10H_11H_LIMIT C001_0061 */ | /* for MSR_AMD_10H_11H_LIMIT C001_0061 */ | ||||
| #define AMD_10H_11H_GET_PSTATE_MAX_VAL(msr) (((msr) >> 4) & 0x7) | #define AMD_10H_11H_GET_PSTATE_MAX_VAL(msr) (((msr) >> 4) & 0x7) | ||||
| #define AMD_10H_11H_GET_PSTATE_LIMIT(msr) (((msr)) & 0x7) | #define AMD_10H_11H_GET_PSTATE_LIMIT(msr) (((msr)) & 0x7) | ||||
| ▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | |||||
| struct amdhwp_dump_sysctl_handler_request { | struct amdhwp_dump_sysctl_handler_request { | ||||
| uint64_t enable; | uint64_t enable; | ||||
| uint64_t caps; | uint64_t caps; | ||||
| uint64_t req; | uint64_t req; | ||||
| int res; | int res; | ||||
| }; | }; | ||||
| static void | static void | ||||
| print_msr_bits(struct sbuf *const sb, const char *const legend, | |||||
| const uint64_t bits, const uint64_t msr_value) | |||||
| { | |||||
| sbuf_printf(sb, "\t%s: %" PRIu64 "\n", legend, | |||||
| BITS_VALUE(bits, msr_value)); | |||||
| } | |||||
| static void | |||||
| print_cppc_caps_1(struct sbuf *const sb, const uint64_t caps) | |||||
| { | |||||
| sbuf_printf(sb, MSR_AMD_CPPC_CAPS_1_NAME ": %#016" PRIx64 "\n", caps); | |||||
| print_msr_bits(sb, "Highest Performance", | |||||
| AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, caps); | |||||
| print_msr_bits(sb, "Guaranteed Performance", | |||||
| AMD_CPPC_CAPS_1_NOMINAL_PERF_BITS, caps); | |||||
| print_msr_bits(sb, "Efficient Performance", | |||||
| AMD_CPPC_CAPS_1_EFFICIENT_PERF_BITS, caps); | |||||
| print_msr_bits(sb, "Lowest Performance", | |||||
| AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, caps); | |||||
| } | |||||
| static void | |||||
| print_cppc_request(struct sbuf *const sb, const uint64_t request) | |||||
| { | |||||
| sbuf_printf(sb, MSR_AMD_CPPC_REQUEST_NAME ": %#016" PRIx64 "\n", | |||||
| request); | |||||
| print_msr_bits(sb, "Efficiency / Energy Preference", | |||||
| AMD_CPPC_REQUEST_EPP_BITS, request); | |||||
| print_msr_bits(sb, "Desired Performance", | |||||
| AMD_CPPC_REQUEST_DES_PERF_BITS, request); | |||||
| print_msr_bits(sb, "Minimum Performance", | |||||
| AMD_CPPC_REQUEST_MIN_PERF_BITS, request); | |||||
| print_msr_bits(sb, "Maximum Performance", | |||||
| AMD_CPPC_REQUEST_MAX_PERF_BITS, request); | |||||
| } | |||||
| static void | |||||
| amdhwp_dump_sysctl_handler_cb(void *args) | amdhwp_dump_sysctl_handler_cb(void *args) | ||||
| { | { | ||||
| struct amdhwp_dump_sysctl_handler_request *req = | struct amdhwp_dump_sysctl_handler_request *req = | ||||
| (struct amdhwp_dump_sysctl_handler_request *)args; | (struct amdhwp_dump_sysctl_handler_request *)args; | ||||
| req->res = rdmsr_safe(MSR_AMD_CPPC_ENABLE, &req->enable); | req->res = rdmsr_safe(MSR_AMD_CPPC_ENABLE, &req->enable); | ||||
| if (req->res == 0) | if (req->res == 0) | ||||
| req->res = rdmsr_safe(MSR_AMD_CPPC_CAPS_1, &req->caps); | req->res = rdmsr_safe(MSR_AMD_CPPC_CAPS_1, &req->caps); | ||||
| Show All 29 Lines | amdhwp_dump_sysctl_handler(SYSCTL_HANDLER_ARGS) | ||||
| data = request.enable; | data = request.enable; | ||||
| sbuf_printf(sb, "CPU%d: HWP %sabled\n", pc->pc_cpuid, | sbuf_printf(sb, "CPU%d: HWP %sabled\n", pc->pc_cpuid, | ||||
| ((data & 1) ? "En" : "Dis")); | ((data & 1) ? "En" : "Dis")); | ||||
| if (data == 0) | if (data == 0) | ||||
| goto out; | goto out; | ||||
| data = request.caps; | data = request.caps; | ||||
| sbuf_printf(sb, "\tHighest Performance: %03ju\n", | print_cppc_caps_1(sb, data); | ||||
| BITS_VALUE(AMD_CPPC_CAPS_1_HIGHEST_PERF_BITS, data)); | |||||
| sbuf_printf(sb, "\tGuaranteed Performance: %03ju\n", | |||||
| BITS_VALUE(AMD_CPPC_CAPS_1_NOMINAL_PERF_BITS, data)); | |||||
| sbuf_printf(sb, "\tEfficient Performance: %03ju\n", | |||||
| BITS_VALUE(AMD_CPPC_CAPS_1_EFFICIENT_PERF_BITS, data)); | |||||
| sbuf_printf(sb, "\tLowest Performance: %03ju\n", | |||||
| BITS_VALUE(AMD_CPPC_CAPS_1_LOWEST_PERF_BITS, data)); | |||||
| sbuf_putc(sb, '\n'); | |||||
| data = request.req; | data = request.req; | ||||
| #define pkg_print(name, offset) \ | print_cppc_request(sb, data); | ||||
| do { \ | |||||
| sbuf_printf(sb, "\t%s: %03u\n", name, \ | |||||
| (unsigned)(data >> offset) & 0xff); \ | |||||
| } while (0) | |||||
| pkg_print("Requested Efficiency Performance Preference", 24); | |||||
| pkg_print("Requested Desired Performance", 16); | |||||
| pkg_print("Requested Maximum Performance", 8); | |||||
| pkg_print("Requested Minimum Performance", 0); | |||||
| #undef pkg_print | |||||
| sbuf_putc(sb, '\n'); | |||||
| out: | out: | ||||
| if (ret == 0) | if (ret == 0) | ||||
| ret = sbuf_finish(sb); | ret = sbuf_finish(sb); | ||||
| if (ret == 0) | if (ret == 0) | ||||
| ret = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb)); | ret = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb)); | ||||
| sbuf_delete(sb); | sbuf_delete(sb); | ||||
| ▲ Show 20 Lines • Show All 646 Lines • Show Last 20 Lines | |||||
Should we include this?