Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pm-6.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
"These fix the cpupower utility installation, fix up the recently added
Rust abstractions for cpufreq and OPP, restore the x86 update
eliminating mwait_play_dead_cpuid_hint() that has been reverted during
the 6.16 merge window along with preventing the failure caused by it
from happening, and clean up mwait_idle_with_hints() usage in
intel_idle:

- Implement CpuId Rust abstraction and use it to fix doctest failure
related to the recently introduced cpumask abstraction (Viresh
Kumar)

- Do minor cleanups in the `# Safety` sections for cpufreq
abstractions added recently (Viresh Kumar)

- Unbreak cpupower systemd service units installation on some systems
by adding a unitdir variable for specifying the location to install
them (Francesco Poli)

- Eliminate mwait_play_dead_cpuid_hint() again after reverting its
elimination during the 6.16 merge window due to a problem with
handling "dead" SMT siblings, but this time prevent leaving them in
C1 after initialization by taking them online and back offline when
a proper cpuidle driver for the platform has been registered
(Rafael Wysocki)

- Update data types of variables passed as arguments to
mwait_idle_with_hints() to match the function definition after
recent changes (Uros Bizjak)"

* tag 'pm-6.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
rust: cpu: Add CpuId::current() to retrieve current CPU ID
rust: Use CpuId in place of raw CPU numbers
rust: cpu: Introduce CpuId abstraction
intel_idle: Update arguments of mwait_idle_with_hints()
cpufreq: Convert `/// SAFETY` lines to `# Safety` sections
cpupower: split unitdir from libdir in Makefile
Reapply "x86/smp: Eliminate mwait_play_dead_cpuid_hint()"
ACPI: processor: Rescan "dead" SMT siblings during initialization
intel_idle: Rescan "dead" SMT siblings during initialization
x86/smp: PM/hibernate: Split arch_resume_nosmt()
intel_idle: Use subsys_initcall_sync() for initialization

+367 -132
+1
MAINTAINERS
··· 6255 6255 F: include/linux/smpboot.h 6256 6256 F: kernel/cpu.c 6257 6257 F: kernel/smpboot.* 6258 + F: rust/helper/cpu.c 6258 6259 F: rust/kernel/cpu.rs 6259 6260 6260 6261 CPU IDLE TIME MANAGEMENT FRAMEWORK
+24
arch/x86/kernel/smp.c
··· 299 299 .send_call_func_single_ipi = native_send_call_func_single_ipi, 300 300 }; 301 301 EXPORT_SYMBOL_GPL(smp_ops); 302 + 303 + int arch_cpu_rescan_dead_smt_siblings(void) 304 + { 305 + enum cpuhp_smt_control old = cpu_smt_control; 306 + int ret; 307 + 308 + /* 309 + * If SMT has been disabled and SMT siblings are in HLT, bring them back 310 + * online and offline them again so that they end up in MWAIT proper. 311 + * 312 + * Called with hotplug enabled. 313 + */ 314 + if (old != CPU_SMT_DISABLED && old != CPU_SMT_FORCE_DISABLED) 315 + return 0; 316 + 317 + ret = cpuhp_smt_enable(); 318 + if (ret) 319 + return ret; 320 + 321 + ret = cpuhp_smt_disable(old); 322 + 323 + return ret; 324 + } 325 + EXPORT_SYMBOL_GPL(arch_cpu_rescan_dead_smt_siblings);
+7 -47
arch/x86/kernel/smpboot.c
··· 1244 1244 local_irq_disable(); 1245 1245 } 1246 1246 1247 + /* 1248 + * We need to flush the caches before going to sleep, lest we have 1249 + * dirty data in our caches when we come back up. 1250 + */ 1247 1251 void __noreturn mwait_play_dead(unsigned int eax_hint) 1248 1252 { 1249 1253 struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead); ··· 1291 1287 native_halt(); 1292 1288 } 1293 1289 } 1294 - } 1295 - 1296 - /* 1297 - * We need to flush the caches before going to sleep, lest we have 1298 - * dirty data in our caches when we come back up. 1299 - */ 1300 - static inline void mwait_play_dead_cpuid_hint(void) 1301 - { 1302 - unsigned int eax, ebx, ecx, edx; 1303 - unsigned int highest_cstate = 0; 1304 - unsigned int highest_subcstate = 0; 1305 - int i; 1306 - 1307 - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || 1308 - boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) 1309 - return; 1310 - if (!this_cpu_has(X86_FEATURE_MWAIT)) 1311 - return; 1312 - if (!this_cpu_has(X86_FEATURE_CLFLUSH)) 1313 - return; 1314 - 1315 - eax = CPUID_LEAF_MWAIT; 1316 - ecx = 0; 1317 - native_cpuid(&eax, &ebx, &ecx, &edx); 1318 - 1319 - /* 1320 - * eax will be 0 if EDX enumeration is not valid. 1321 - * Initialized below to cstate, sub_cstate value when EDX is valid. 1322 - */ 1323 - if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) { 1324 - eax = 0; 1325 - } else { 1326 - edx >>= MWAIT_SUBSTATE_SIZE; 1327 - for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) { 1328 - if (edx & MWAIT_SUBSTATE_MASK) { 1329 - highest_cstate = i; 1330 - highest_subcstate = edx & MWAIT_SUBSTATE_MASK; 1331 - } 1332 - } 1333 - eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | 1334 - (highest_subcstate - 1); 1335 - } 1336 - 1337 - mwait_play_dead(eax); 1338 1290 } 1339 1291 1340 1292 /* ··· 1343 1383 play_dead_common(); 1344 1384 tboot_shutdown(TB_SHUTDOWN_WFS); 1345 1385 1346 - mwait_play_dead_cpuid_hint(); 1347 - if (cpuidle_play_dead()) 1348 - hlt_play_dead(); 1386 + /* Below returns only on error. */ 1387 + cpuidle_play_dead(); 1388 + hlt_play_dead(); 1349 1389 } 1350 1390 1351 1391 #else /* ... !CONFIG_HOTPLUG_CPU */
+5 -12
arch/x86/power/hibernate.c
··· 192 192 193 193 int arch_resume_nosmt(void) 194 194 { 195 - int ret = 0; 195 + int ret; 196 + 196 197 /* 197 198 * We reached this while coming out of hibernation. This means 198 199 * that SMT siblings are sleeping in hlt, as mwait is not safe ··· 207 206 * Called with hotplug disabled. 208 207 */ 209 208 cpu_hotplug_enable(); 210 - if (cpu_smt_control == CPU_SMT_DISABLED || 211 - cpu_smt_control == CPU_SMT_FORCE_DISABLED) { 212 - enum cpuhp_smt_control old = cpu_smt_control; 213 209 214 - ret = cpuhp_smt_enable(); 215 - if (ret) 216 - goto out; 217 - ret = cpuhp_smt_disable(old); 218 - if (ret) 219 - goto out; 220 - } 221 - out: 210 + ret = arch_cpu_rescan_dead_smt_siblings(); 211 + 222 212 cpu_hotplug_disable(); 213 + 223 214 return ret; 224 215 }
+6
drivers/acpi/internal.h
··· 175 175 static inline void acpi_early_processor_control_setup(void) {} 176 176 #endif 177 177 178 + #ifdef CONFIG_ACPI_PROCESSOR_CSTATE 179 + void acpi_idle_rescan_dead_smt_siblings(void); 180 + #else 181 + static inline void acpi_idle_rescan_dead_smt_siblings(void) {} 182 + #endif 183 + 178 184 /* -------------------------------------------------------------------------- 179 185 Embedded Controller 180 186 -------------------------------------------------------------------------- */
+3
drivers/acpi/processor_driver.c
··· 279 279 * after acpi_cppc_processor_probe() has been called for all online CPUs 280 280 */ 281 281 acpi_processor_init_invariance_cppc(); 282 + 283 + acpi_idle_rescan_dead_smt_siblings(); 284 + 282 285 return 0; 283 286 err: 284 287 driver_unregister(&acpi_processor_driver);
+8
drivers/acpi/processor_idle.c
··· 24 24 #include <acpi/processor.h> 25 25 #include <linux/context_tracking.h> 26 26 27 + #include "internal.h" 28 + 27 29 /* 28 30 * Include the apic definitions for x86 to have the APIC timer related defines 29 31 * available also for UP (on SMP it gets magically included via linux/smp.h). ··· 57 55 }; 58 56 59 57 #ifdef CONFIG_ACPI_PROCESSOR_CSTATE 58 + void acpi_idle_rescan_dead_smt_siblings(void) 59 + { 60 + if (cpuidle_get_driver() == &acpi_idle_driver) 61 + arch_cpu_rescan_dead_smt_siblings(); 62 + } 63 + 60 64 static 61 65 DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); 62 66
+2 -2
drivers/cpufreq/rcpufreq_dt.rs
··· 26 26 } 27 27 28 28 /// Finds supply name for the CPU from DT. 29 - fn find_supply_names(dev: &Device, cpu: u32) -> Option<KVec<CString>> { 29 + fn find_supply_names(dev: &Device, cpu: cpu::CpuId) -> Option<KVec<CString>> { 30 30 // Try "cpu0" for older DTs, fallback to "cpu". 31 - let name = (cpu == 0) 31 + let name = (cpu.as_u32() == 0) 32 32 .then(|| find_supply_name_exact(dev, "cpu0")) 33 33 .flatten() 34 34 .or_else(|| find_supply_name_exact(dev, "cpu"))?;
+7 -5
drivers/idle/intel_idle.c
··· 152 152 int index, bool irqoff) 153 153 { 154 154 struct cpuidle_state *state = &drv->states[index]; 155 - unsigned long eax = flg2MWAIT(state->flags); 156 - unsigned long ecx = 1*irqoff; /* break on interrupt flag */ 155 + unsigned int eax = flg2MWAIT(state->flags); 156 + unsigned int ecx = 1*irqoff; /* break on interrupt flag */ 157 157 158 158 mwait_idle_with_hints(eax, ecx); 159 159 ··· 226 226 static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev, 227 227 struct cpuidle_driver *drv, int index) 228 228 { 229 - unsigned long ecx = 1; /* break on interrupt flag */ 230 229 struct cpuidle_state *state = &drv->states[index]; 231 - unsigned long eax = flg2MWAIT(state->flags); 230 + unsigned int eax = flg2MWAIT(state->flags); 231 + unsigned int ecx = 1; /* break on interrupt flag */ 232 232 233 233 if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) 234 234 fpu_idle_fpregs(); ··· 2507 2507 pr_debug("Local APIC timer is reliable in %s\n", 2508 2508 boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1"); 2509 2509 2510 + arch_cpu_rescan_dead_smt_siblings(); 2511 + 2510 2512 return 0; 2511 2513 2512 2514 hp_setup_fail: ··· 2520 2518 return retval; 2521 2519 2522 2520 } 2523 - device_initcall(intel_idle_init); 2521 + subsys_initcall_sync(intel_idle_init); 2524 2522 2525 2523 /* 2526 2524 * We are not really modular, but we used to support that. Meaning we also
+3
include/linux/cpu.h
··· 120 120 extern void cpu_maps_update_done(void); 121 121 int bringup_hibernate_cpu(unsigned int sleep_cpu); 122 122 void bringup_nonboot_cpus(unsigned int max_cpus); 123 + int arch_cpu_rescan_dead_smt_siblings(void); 123 124 124 125 #else /* CONFIG_SMP */ 125 126 #define cpuhp_tasks_frozen 0 ··· 134 133 } 135 134 136 135 static inline int add_cpu(unsigned int cpu) { return 0;} 136 + 137 + static inline int arch_cpu_rescan_dead_smt_siblings(void) { return 0; } 137 138 138 139 #endif /* CONFIG_SMP */ 139 140 extern const struct bus_type cpu_subsys;
+8
rust/helpers/cpu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/smp.h> 4 + 5 + unsigned int rust_helper_raw_smp_processor_id(void) 6 + { 7 + return raw_smp_processor_id(); 8 + }
+1
rust/helpers/helpers.c
··· 13 13 #include "build_assert.c" 14 14 #include "build_bug.c" 15 15 #include "clk.c" 16 + #include "cpu.c" 16 17 #include "cpufreq.c" 17 18 #include "cpumask.c" 18 19 #include "cred.c"
+123 -2
rust/kernel/cpu.rs
··· 6 6 7 7 use crate::{bindings, device::Device, error::Result, prelude::ENODEV}; 8 8 9 + /// Returns the maximum number of possible CPUs in the current system configuration. 10 + #[inline] 11 + pub fn nr_cpu_ids() -> u32 { 12 + #[cfg(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS))] 13 + { 14 + bindings::NR_CPUS 15 + } 16 + 17 + #[cfg(not(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS)))] 18 + // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel. 19 + unsafe { 20 + bindings::nr_cpu_ids 21 + } 22 + } 23 + 24 + /// The CPU ID. 25 + /// 26 + /// Represents a CPU identifier as a wrapper around an [`u32`]. 27 + /// 28 + /// # Invariants 29 + /// 30 + /// The CPU ID lies within the range `[0, nr_cpu_ids())`. 31 + /// 32 + /// # Examples 33 + /// 34 + /// ``` 35 + /// use kernel::cpu::CpuId; 36 + /// 37 + /// let cpu = 0; 38 + /// 39 + /// // SAFETY: 0 is always a valid CPU number. 40 + /// let id = unsafe { CpuId::from_u32_unchecked(cpu) }; 41 + /// 42 + /// assert_eq!(id.as_u32(), cpu); 43 + /// assert!(CpuId::from_i32(0).is_some()); 44 + /// assert!(CpuId::from_i32(-1).is_none()); 45 + /// ``` 46 + #[derive(Copy, Clone, PartialEq, Eq, Debug)] 47 + pub struct CpuId(u32); 48 + 49 + impl CpuId { 50 + /// Creates a new [`CpuId`] from the given `id` without checking bounds. 51 + /// 52 + /// # Safety 53 + /// 54 + /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`). 55 + #[inline] 56 + pub unsafe fn from_i32_unchecked(id: i32) -> Self { 57 + debug_assert!(id >= 0); 58 + debug_assert!((id as u32) < nr_cpu_ids()); 59 + 60 + // INVARIANT: The function safety guarantees `id` is a valid CPU id. 61 + Self(id as u32) 62 + } 63 + 64 + /// Creates a new [`CpuId`] from the given `id`, checking that it is valid. 65 + pub fn from_i32(id: i32) -> Option<Self> { 66 + if id < 0 || id as u32 >= nr_cpu_ids() { 67 + None 68 + } else { 69 + // INVARIANT: `id` has just been checked as a valid CPU ID. 70 + Some(Self(id as u32)) 71 + } 72 + } 73 + 74 + /// Creates a new [`CpuId`] from the given `id` without checking bounds. 75 + /// 76 + /// # Safety 77 + /// 78 + /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`). 79 + #[inline] 80 + pub unsafe fn from_u32_unchecked(id: u32) -> Self { 81 + debug_assert!(id < nr_cpu_ids()); 82 + 83 + // Ensure the `id` fits in an [`i32`] as it's also representable that way. 84 + debug_assert!(id <= i32::MAX as u32); 85 + 86 + // INVARIANT: The function safety guarantees `id` is a valid CPU id. 87 + Self(id) 88 + } 89 + 90 + /// Creates a new [`CpuId`] from the given `id`, checking that it is valid. 91 + pub fn from_u32(id: u32) -> Option<Self> { 92 + if id >= nr_cpu_ids() { 93 + None 94 + } else { 95 + // INVARIANT: `id` has just been checked as a valid CPU ID. 96 + Some(Self(id)) 97 + } 98 + } 99 + 100 + /// Returns CPU number. 101 + #[inline] 102 + pub fn as_u32(&self) -> u32 { 103 + self.0 104 + } 105 + 106 + /// Returns the ID of the CPU the code is currently running on. 107 + /// 108 + /// The returned value is considered unstable because it may change 109 + /// unexpectedly due to preemption or CPU migration. It should only be 110 + /// used when the context ensures that the task remains on the same CPU 111 + /// or the users could use a stale (yet valid) CPU ID. 112 + pub fn current() -> Self { 113 + // SAFETY: raw_smp_processor_id() always returns a valid CPU ID. 114 + unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) } 115 + } 116 + } 117 + 118 + impl From<CpuId> for u32 { 119 + fn from(id: CpuId) -> Self { 120 + id.as_u32() 121 + } 122 + } 123 + 124 + impl From<CpuId> for i32 { 125 + fn from(id: CpuId) -> Self { 126 + id.as_u32() as i32 127 + } 128 + } 129 + 9 130 /// Creates a new instance of CPU's device. 10 131 /// 11 132 /// # Safety ··· 138 17 /// Callers must ensure that the CPU device is not used after it has been unregistered. 139 18 /// This can be achieved, for example, by registering a CPU hotplug notifier and removing 140 19 /// any references to the CPU device within the notifier's callback. 141 - pub unsafe fn from_cpu(cpu: u32) -> Result<&'static Device> { 20 + pub unsafe fn from_cpu(cpu: CpuId) -> Result<&'static Device> { 142 21 // SAFETY: It is safe to call `get_cpu_device()` for any CPU. 143 - let ptr = unsafe { bindings::get_cpu_device(cpu) }; 22 + let ptr = unsafe { bindings::get_cpu_device(u32::from(cpu)) }; 144 23 if ptr.is_null() { 145 24 return Err(ENODEV); 146 25 }
+128 -45
rust/kernel/cpufreq.rs
··· 10 10 11 11 use crate::{ 12 12 clk::Hertz, 13 + cpu::CpuId, 13 14 cpumask, 14 15 device::{Bound, Device}, 15 16 devres::Devres, ··· 466 465 467 466 /// Returns the primary CPU for the [`Policy`]. 468 467 #[inline] 469 - pub fn cpu(&self) -> u32 { 470 - self.as_ref().cpu 468 + pub fn cpu(&self) -> CpuId { 469 + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. 470 + unsafe { CpuId::from_u32_unchecked(self.as_ref().cpu) } 471 471 } 472 472 473 473 /// Returns the minimum frequency for the [`Policy`]. ··· 527 525 #[inline] 528 526 pub fn generic_get(&self) -> Result<u32> { 529 527 // SAFETY: By the type invariant, the pointer stored in `self` is valid. 530 - Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) }) 528 + Ok(unsafe { bindings::cpufreq_generic_get(u32::from(self.cpu())) }) 531 529 } 532 530 533 531 /// Provides a wrapper to the register with energy model using the OPP core. ··· 680 678 struct PolicyCpu<'a>(&'a mut Policy); 681 679 682 680 impl<'a> PolicyCpu<'a> { 683 - fn from_cpu(cpu: u32) -> Result<Self> { 681 + fn from_cpu(cpu: CpuId) -> Result<Self> { 684 682 // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU. 685 - let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?; 683 + let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(u32::from(cpu)) })?; 686 684 687 685 Ok(Self( 688 686 // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of ··· 1057 1055 impl<T: Driver> Registration<T> { 1058 1056 /// Driver's `init` callback. 1059 1057 /// 1060 - /// SAFETY: Called from C. Inputs must be valid pointers. 1061 - extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1058 + /// # Safety 1059 + /// 1060 + /// - This function may only be called from the cpufreq C infrastructure. 1061 + /// - The pointer arguments must be valid pointers. 1062 + unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1062 1063 from_result(|| { 1063 1064 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1064 1065 // lifetime of `policy`. ··· 1075 1070 1076 1071 /// Driver's `exit` callback. 1077 1072 /// 1078 - /// SAFETY: Called from C. Inputs must be valid pointers. 1079 - extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) { 1073 + /// # Safety 1074 + /// 1075 + /// - This function may only be called from the cpufreq C infrastructure. 1076 + /// - The pointer arguments must be valid pointers. 1077 + unsafe extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) { 1080 1078 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1081 1079 // lifetime of `policy`. 1082 1080 let policy = unsafe { Policy::from_raw_mut(ptr) }; ··· 1090 1082 1091 1083 /// Driver's `online` callback. 1092 1084 /// 1093 - /// SAFETY: Called from C. Inputs must be valid pointers. 1094 - extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1085 + /// # Safety 1086 + /// 1087 + /// - This function may only be called from the cpufreq C infrastructure. 1088 + /// - The pointer arguments must be valid pointers. 1089 + unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1095 1090 from_result(|| { 1096 1091 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1097 1092 // lifetime of `policy`. ··· 1105 1094 1106 1095 /// Driver's `offline` callback. 1107 1096 /// 1108 - /// SAFETY: Called from C. Inputs must be valid pointers. 1109 - extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1097 + /// # Safety 1098 + /// 1099 + /// - This function may only be called from the cpufreq C infrastructure. 1100 + /// - The pointer arguments must be valid pointers. 1101 + unsafe extern "C" fn offline_callback( 1102 + ptr: *mut bindings::cpufreq_policy, 1103 + ) -> kernel::ffi::c_int { 1110 1104 from_result(|| { 1111 1105 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1112 1106 // lifetime of `policy`. ··· 1122 1106 1123 1107 /// Driver's `suspend` callback. 1124 1108 /// 1125 - /// SAFETY: Called from C. Inputs must be valid pointers. 1126 - extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1109 + /// # Safety 1110 + /// 1111 + /// - This function may only be called from the cpufreq C infrastructure. 1112 + /// - The pointer arguments must be valid pointers. 1113 + unsafe extern "C" fn suspend_callback( 1114 + ptr: *mut bindings::cpufreq_policy, 1115 + ) -> kernel::ffi::c_int { 1127 1116 from_result(|| { 1128 1117 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1129 1118 // lifetime of `policy`. ··· 1139 1118 1140 1119 /// Driver's `resume` callback. 1141 1120 /// 1142 - /// SAFETY: Called from C. Inputs must be valid pointers. 1143 - extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1121 + /// # Safety 1122 + /// 1123 + /// - This function may only be called from the cpufreq C infrastructure. 1124 + /// - The pointer arguments must be valid pointers. 1125 + unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1144 1126 from_result(|| { 1145 1127 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1146 1128 // lifetime of `policy`. ··· 1154 1130 1155 1131 /// Driver's `ready` callback. 1156 1132 /// 1157 - /// SAFETY: Called from C. Inputs must be valid pointers. 1158 - extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) { 1133 + /// # Safety 1134 + /// 1135 + /// - This function may only be called from the cpufreq C infrastructure. 1136 + /// - The pointer arguments must be valid pointers. 1137 + unsafe extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) { 1159 1138 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1160 1139 // lifetime of `policy`. 1161 1140 let policy = unsafe { Policy::from_raw_mut(ptr) }; ··· 1167 1140 1168 1141 /// Driver's `verify` callback. 1169 1142 /// 1170 - /// SAFETY: Called from C. Inputs must be valid pointers. 1171 - extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> kernel::ffi::c_int { 1143 + /// # Safety 1144 + /// 1145 + /// - This function may only be called from the cpufreq C infrastructure. 1146 + /// - The pointer arguments must be valid pointers. 1147 + unsafe extern "C" fn verify_callback( 1148 + ptr: *mut bindings::cpufreq_policy_data, 1149 + ) -> kernel::ffi::c_int { 1172 1150 from_result(|| { 1173 1151 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1174 1152 // lifetime of `policy`. ··· 1184 1152 1185 1153 /// Driver's `setpolicy` callback. 1186 1154 /// 1187 - /// SAFETY: Called from C. Inputs must be valid pointers. 1188 - extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { 1155 + /// # Safety 1156 + /// 1157 + /// - This function may only be called from the cpufreq C infrastructure. 1158 + /// - The pointer arguments must be valid pointers. 1159 + unsafe extern "C" fn setpolicy_callback( 1160 + ptr: *mut bindings::cpufreq_policy, 1161 + ) -> kernel::ffi::c_int { 1189 1162 from_result(|| { 1190 1163 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1191 1164 // lifetime of `policy`. ··· 1201 1164 1202 1165 /// Driver's `target` callback. 1203 1166 /// 1204 - /// SAFETY: Called from C. Inputs must be valid pointers. 1205 - extern "C" fn target_callback( 1167 + /// # Safety 1168 + /// 1169 + /// - This function may only be called from the cpufreq C infrastructure. 1170 + /// - The pointer arguments must be valid pointers. 1171 + unsafe extern "C" fn target_callback( 1206 1172 ptr: *mut bindings::cpufreq_policy, 1207 1173 target_freq: u32, 1208 1174 relation: u32, ··· 1220 1180 1221 1181 /// Driver's `target_index` callback. 1222 1182 /// 1223 - /// SAFETY: Called from C. Inputs must be valid pointers. 1224 - extern "C" fn target_index_callback( 1183 + /// # Safety 1184 + /// 1185 + /// - This function may only be called from the cpufreq C infrastructure. 1186 + /// - The pointer arguments must be valid pointers. 1187 + unsafe extern "C" fn target_index_callback( 1225 1188 ptr: *mut bindings::cpufreq_policy, 1226 1189 index: u32, 1227 1190 ) -> kernel::ffi::c_int { ··· 1243 1200 1244 1201 /// Driver's `fast_switch` callback. 1245 1202 /// 1246 - /// SAFETY: Called from C. Inputs must be valid pointers. 1247 - extern "C" fn fast_switch_callback( 1203 + /// # Safety 1204 + /// 1205 + /// - This function may only be called from the cpufreq C infrastructure. 1206 + /// - The pointer arguments must be valid pointers. 1207 + unsafe extern "C" fn fast_switch_callback( 1248 1208 ptr: *mut bindings::cpufreq_policy, 1249 1209 target_freq: u32, 1250 1210 ) -> kernel::ffi::c_uint { ··· 1258 1212 } 1259 1213 1260 1214 /// Driver's `adjust_perf` callback. 1261 - extern "C" fn adjust_perf_callback( 1215 + /// 1216 + /// # Safety 1217 + /// 1218 + /// - This function may only be called from the cpufreq C infrastructure. 1219 + unsafe extern "C" fn adjust_perf_callback( 1262 1220 cpu: u32, 1263 1221 min_perf: usize, 1264 1222 target_perf: usize, 1265 1223 capacity: usize, 1266 1224 ) { 1267 - if let Ok(mut policy) = PolicyCpu::from_cpu(cpu) { 1225 + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. 1226 + let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) }; 1227 + 1228 + if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) { 1268 1229 T::adjust_perf(&mut policy, min_perf, target_perf, capacity); 1269 1230 } 1270 1231 } 1271 1232 1272 1233 /// Driver's `get_intermediate` callback. 1273 1234 /// 1274 - /// SAFETY: Called from C. Inputs must be valid pointers. 1275 - extern "C" fn get_intermediate_callback( 1235 + /// # Safety 1236 + /// 1237 + /// - This function may only be called from the cpufreq C infrastructure. 1238 + /// - The pointer arguments must be valid pointers. 1239 + unsafe extern "C" fn get_intermediate_callback( 1276 1240 ptr: *mut bindings::cpufreq_policy, 1277 1241 index: u32, 1278 1242 ) -> kernel::ffi::c_uint { ··· 1299 1243 1300 1244 /// Driver's `target_intermediate` callback. 1301 1245 /// 1302 - /// SAFETY: Called from C. Inputs must be valid pointers. 1303 - extern "C" fn target_intermediate_callback( 1246 + /// # Safety 1247 + /// 1248 + /// - This function may only be called from the cpufreq C infrastructure. 1249 + /// - The pointer arguments must be valid pointers. 1250 + unsafe extern "C" fn target_intermediate_callback( 1304 1251 ptr: *mut bindings::cpufreq_policy, 1305 1252 index: u32, 1306 1253 ) -> kernel::ffi::c_int { ··· 1321 1262 } 1322 1263 1323 1264 /// Driver's `get` callback. 1324 - extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint { 1325 - PolicyCpu::from_cpu(cpu).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f)) 1265 + /// 1266 + /// # Safety 1267 + /// 1268 + /// - This function may only be called from the cpufreq C infrastructure. 1269 + unsafe extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint { 1270 + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. 1271 + let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) }; 1272 + 1273 + PolicyCpu::from_cpu(cpu_id).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f)) 1326 1274 } 1327 1275 1328 1276 /// Driver's `update_limit` callback. 1329 - extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) { 1277 + /// 1278 + /// # Safety 1279 + /// 1280 + /// - This function may only be called from the cpufreq C infrastructure. 1281 + /// - The pointer arguments must be valid pointers. 1282 + unsafe extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) { 1330 1283 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1331 1284 // lifetime of `policy`. 1332 1285 let policy = unsafe { Policy::from_raw_mut(ptr) }; ··· 1347 1276 1348 1277 /// Driver's `bios_limit` callback. 1349 1278 /// 1350 - /// SAFETY: Called from C. Inputs must be valid pointers. 1351 - extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int { 1279 + /// # Safety 1280 + /// 1281 + /// - This function may only be called from the cpufreq C infrastructure. 1282 + /// - The pointer arguments must be valid pointers. 1283 + unsafe extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int { 1284 + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. 1285 + let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) }; 1286 + 1352 1287 from_result(|| { 1353 - let mut policy = PolicyCpu::from_cpu(cpu as u32)?; 1288 + let mut policy = PolicyCpu::from_cpu(cpu_id)?; 1354 1289 1355 1290 // SAFETY: `limit` is guaranteed by the C code to be valid. 1356 1291 T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0) ··· 1365 1288 1366 1289 /// Driver's `set_boost` callback. 1367 1290 /// 1368 - /// SAFETY: Called from C. Inputs must be valid pointers. 1369 - extern "C" fn set_boost_callback( 1291 + /// # Safety 1292 + /// 1293 + /// - This function may only be called from the cpufreq C infrastructure. 1294 + /// - The pointer arguments must be valid pointers. 1295 + unsafe extern "C" fn set_boost_callback( 1370 1296 ptr: *mut bindings::cpufreq_policy, 1371 1297 state: i32, 1372 1298 ) -> kernel::ffi::c_int { ··· 1383 1303 1384 1304 /// Driver's `register_em` callback. 1385 1305 /// 1386 - /// SAFETY: Called from C. Inputs must be valid pointers. 1387 - extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) { 1306 + /// # Safety 1307 + /// 1308 + /// - This function may only be called from the cpufreq C infrastructure. 1309 + /// - The pointer arguments must be valid pointers. 1310 + unsafe extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) { 1388 1311 // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the 1389 1312 // lifetime of `policy`. 1390 1313 let policy = unsafe { Policy::from_raw_mut(ptr) };
+36 -15
rust/kernel/cpumask.rs
··· 6 6 7 7 use crate::{ 8 8 alloc::{AllocError, Flags}, 9 + cpu::CpuId, 9 10 prelude::*, 10 11 types::Opaque, 11 12 }; ··· 36 35 /// 37 36 /// ``` 38 37 /// use kernel::bindings; 38 + /// use kernel::cpu::CpuId; 39 39 /// use kernel::cpumask::Cpumask; 40 40 /// 41 - /// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: u32, clear_cpu: i32) { 41 + /// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: CpuId, clear_cpu: CpuId) { 42 42 /// // SAFETY: The `ptr` is valid for writing and remains valid for the lifetime of the 43 43 /// // returned reference. 44 44 /// let mask = unsafe { Cpumask::as_mut_ref(ptr) }; ··· 92 90 /// This mismatches kernel naming convention and corresponds to the C 93 91 /// function `__cpumask_set_cpu()`. 94 92 #[inline] 95 - pub fn set(&mut self, cpu: u32) { 93 + pub fn set(&mut self, cpu: CpuId) { 96 94 // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `__cpumask_set_cpu`. 97 - unsafe { bindings::__cpumask_set_cpu(cpu, self.as_raw()) }; 95 + unsafe { bindings::__cpumask_set_cpu(u32::from(cpu), self.as_raw()) }; 98 96 } 99 97 100 98 /// Clear `cpu` in the cpumask. ··· 103 101 /// This mismatches kernel naming convention and corresponds to the C 104 102 /// function `__cpumask_clear_cpu()`. 105 103 #[inline] 106 - pub fn clear(&mut self, cpu: i32) { 104 + pub fn clear(&mut self, cpu: CpuId) { 107 105 // SAFETY: By the type invariant, `self.as_raw` is a valid argument to 108 106 // `__cpumask_clear_cpu`. 109 - unsafe { bindings::__cpumask_clear_cpu(cpu, self.as_raw()) }; 107 + unsafe { bindings::__cpumask_clear_cpu(i32::from(cpu), self.as_raw()) }; 110 108 } 111 109 112 110 /// Test `cpu` in the cpumask. 113 111 /// 114 112 /// Equivalent to the kernel's `cpumask_test_cpu` API. 115 113 #[inline] 116 - pub fn test(&self, cpu: i32) -> bool { 114 + pub fn test(&self, cpu: CpuId) -> bool { 117 115 // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_test_cpu`. 118 - unsafe { bindings::cpumask_test_cpu(cpu, self.as_raw()) } 116 + unsafe { bindings::cpumask_test_cpu(i32::from(cpu), self.as_raw()) } 119 117 } 120 118 121 119 /// Set all CPUs in the cpumask. ··· 180 178 /// The following example demonstrates how to create and update a [`CpumaskVar`]. 181 179 /// 182 180 /// ``` 181 + /// use kernel::cpu::CpuId; 183 182 /// use kernel::cpumask::CpumaskVar; 184 183 /// 185 184 /// let mut mask = CpumaskVar::new_zero(GFP_KERNEL).unwrap(); 186 185 /// 187 186 /// assert!(mask.empty()); 188 - /// mask.set(2); 189 - /// assert!(mask.test(2)); 190 - /// mask.set(3); 191 - /// assert!(mask.test(3)); 192 - /// assert_eq!(mask.weight(), 2); 187 + /// let mut count = 0; 188 + /// 189 + /// let cpu2 = CpuId::from_u32(2); 190 + /// if let Some(cpu) = cpu2 { 191 + /// mask.set(cpu); 192 + /// assert!(mask.test(cpu)); 193 + /// count += 1; 194 + /// } 195 + /// 196 + /// let cpu3 = CpuId::from_u32(3); 197 + /// if let Some(cpu) = cpu3 { 198 + /// mask.set(cpu); 199 + /// assert!(mask.test(cpu)); 200 + /// count += 1; 201 + /// } 202 + /// 203 + /// assert_eq!(mask.weight(), count); 193 204 /// 194 205 /// let mask2 = CpumaskVar::try_clone(&mask).unwrap(); 195 - /// assert!(mask2.test(2)); 196 - /// assert!(mask2.test(3)); 197 - /// assert_eq!(mask2.weight(), 2); 206 + /// 207 + /// if let Some(cpu) = cpu2 { 208 + /// assert!(mask2.test(cpu)); 209 + /// } 210 + /// 211 + /// if let Some(cpu) = cpu3 { 212 + /// assert!(mask2.test(cpu)); 213 + /// } 214 + /// assert_eq!(mask2.weight(), count); 198 215 /// ``` 199 216 pub struct CpumaskVar { 200 217 #[cfg(CONFIG_CPUMASK_OFFSTACK)]
+5 -4
tools/power/cpupower/Makefile
··· 73 73 mandir ?= /usr/man 74 74 libdir ?= /usr/lib 75 75 libexecdir ?= /usr/libexec 76 + unitdir ?= /usr/lib/systemd/system 76 77 includedir ?= /usr/include 77 78 localedir ?= /usr/share/locale 78 79 docdir ?= /usr/share/doc/packages/cpupower ··· 310 309 $(INSTALL_DATA) cpupower-service.conf '$(DESTDIR)${confdir}' 311 310 $(INSTALL) -d $(DESTDIR)${libexecdir} 312 311 $(INSTALL_PROGRAM) cpupower.sh '$(DESTDIR)${libexecdir}/cpupower' 313 - $(INSTALL) -d $(DESTDIR)${libdir}/systemd/system 314 - sed 's|___CDIR___|${confdir}|; s|___LDIR___|${libexecdir}|' cpupower.service.in > '$(DESTDIR)${libdir}/systemd/system/cpupower.service' 315 - $(SETPERM_DATA) '$(DESTDIR)${libdir}/systemd/system/cpupower.service' 312 + $(INSTALL) -d $(DESTDIR)${unitdir} 313 + sed 's|___CDIR___|${confdir}|; s|___LDIR___|${libexecdir}|' cpupower.service.in > '$(DESTDIR)${unitdir}/cpupower.service' 314 + $(SETPERM_DATA) '$(DESTDIR)${unitdir}/cpupower.service' 316 315 317 316 install-man: 318 317 $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 ··· 349 348 - rm -f $(DESTDIR)${bindir}/utils/cpupower 350 349 - rm -f $(DESTDIR)${confdir}cpupower-service.conf 351 350 - rm -f $(DESTDIR)${libexecdir}/cpupower 352 - - rm -f $(DESTDIR)${libdir}/systemd/system/cpupower.service 351 + - rm -f $(DESTDIR)${unitdir}/cpupower.service 353 352 - rm -f $(DESTDIR)${mandir}/man1/cpupower.1 354 353 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 355 354 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1