| 245 | } |
| 246 | |
| 247 | static int |
| 248 | sysctl_epp_select(SYSCTL_HANDLER_ARGS) |
| 249 | { |
| 250 | struct hwp_softc *sc; |
| 251 | device_t dev; |
| 252 | struct pcpu *pc; |
| 253 | uint64_t epb; |
| 254 | uint32_t val; |
| 255 | int ret; |
| 256 | |
| 257 | dev = oidp->oid_arg1; |
| 258 | sc = device_get_softc(dev); |
| 259 | if (!sc->hwp_pref_ctrl && !sc->hwp_perf_bias) |
| 260 | return (ENODEV); |
| 261 | |
| 262 | pc = cpu_get_pcpu(dev); |
| 263 | if (pc == NULL) |
| 264 | return (ENXIO); |
| 265 | |
| 266 | thread_lock(curthread); |
| 267 | sched_bind(curthread, pc->pc_cpuid); |
| 268 | thread_unlock(curthread); |
| 269 | |
| 270 | if (sc->hwp_pref_ctrl) { |
| 271 | val = (sc->req & IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE) >> 24; |
| 272 | val = raw_to_percent(val); |
| 273 | } else { |
| 274 | /* |
| 275 | * If cpuid indicates EPP is not supported, the HWP controller |
| 276 | * uses MSR_IA32_ENERGY_PERF_BIAS instead (Intel SDM §14.4.4). |
| 277 | * This register is per-core (but not HT). |
| 278 | */ |
| 279 | if (!sc->hwp_perf_bias_cached) { |
| 280 | ret = rdmsr_safe(MSR_IA32_ENERGY_PERF_BIAS, &epb); |
| 281 | if (ret) |
| 282 | goto out; |
| 283 | sc->hwp_energy_perf_bias = epb; |
| 284 | sc->hwp_perf_bias_cached = true; |
| 285 | } |
| 286 | val = sc->hwp_energy_perf_bias & |
| 287 | IA32_ENERGY_PERF_BIAS_POLICY_HINT_MASK; |
| 288 | val = raw_to_percent_perf_bias(val); |
| 289 | } |
| 290 | |
| 291 | MPASS(val >= 0 && val <= 100); |
| 292 | |
| 293 | ret = sysctl_handle_int(oidp, &val, 0, req); |
| 294 | if (ret || req->newptr == NULL) |
| 295 | goto out; |
| 296 | |
| 297 | if (val > 100) { |
| 298 | ret = EINVAL; |
| 299 | goto out; |
| 300 | } |
| 301 | |
| 302 | if (sc->hwp_pref_ctrl) { |
| 303 | val = percent_to_raw(val); |
| 304 |
nothing calls this directly
no test coverage detected