diff mbox series

[v2] cpupower: add a systemd service to run cpupower

Message ID 20250425151024.121630-1-invernomuto@paranoici.org
State New
Headers show
Series [v2] cpupower: add a systemd service to run cpupower | expand

Commit Message

Francesco Poli April 25, 2025, 3:07 p.m. UTC
One of the most typical use cases of the 'cpupower' utility works as
follows: run 'cpupower' at boot with the desired command-line options
and then forget about it.

Add a systemd service (disabled by default) that automates this use
case (for environments where the initialization system is 'systemd'),
by running 'cpupower' at boot with the settings read from a default
configuration file.

The systemd service, the associated support script and the
corresponding default configuration file are derived from what is
provided by the Arch Linux package (under "GPL-2.0-or-later" terms),
modernized and enhanced in various ways (the script has also been
checked with 'shellcheck').

Link: https://gitlab.archlinux.org/archlinux/packaging/packages/linux-tools/-/tree/dd2e2a311e05413d0d87a0346ffce8c7e98d6d2b

Signed-off-by: Francesco Poli (wintermute) <invernomuto@paranoici.org>
---
 tools/power/cpupower/Makefile            | 15 +++++++++++++
 tools/power/cpupower/README              | 19 ++++++++++++++++
 tools/power/cpupower/cpupower.default    | 28 ++++++++++++++++++++++++
 tools/power/cpupower/cpupower.service.in | 16 ++++++++++++++
 tools/power/cpupower/cpupower.sh         | 26 ++++++++++++++++++++++
 5 files changed, 104 insertions(+)
 create mode 100644 tools/power/cpupower/cpupower.default
 create mode 100644 tools/power/cpupower/cpupower.service.in
 create mode 100644 tools/power/cpupower/cpupower.sh

Patch changelog:
 * Clarified documentation (what should be edited in the default file)
 * Enhanced the comments in the default file
 * Added 'systemctl daemon-reload' to make uninstall, as well
 * Rebased on the tip of the master branch


base-commit: 0af2f6be1b4281385b618cb86ad946eded089ac8

Comments

John B. Wyatt IV April 29, 2025, 8:59 p.m. UTC | #1
On Fri, Apr 25, 2025 at 05:07:31PM +0200, Francesco Poli (wintermute) wrote:
> One of the most typical use cases of the 'cpupower' utility works as
> follows: run 'cpupower' at boot with the desired command-line options
> and then forget about it.
> 
> Add a systemd service (disabled by default) that automates this use
> case (for environments where the initialization system is 'systemd'),
> by running 'cpupower' at boot with the settings read from a default
> configuration file.
> 
> The systemd service, the associated support script and the
> corresponding default configuration file are derived from what is
> provided by the Arch Linux package (under "GPL-2.0-or-later" terms),
> modernized and enhanced in various ways (the script has also been
> checked with 'shellcheck').
> 
> Link: https://gitlab.archlinux.org/archlinux/packaging/packages/linux-tools/-/tree/dd2e2a311e05413d0d87a0346ffce8c7e98d6d2b
> 
> Signed-off-by: Francesco Poli (wintermute) <invernomuto@paranoici.org>

Tested by installing the new systemd files, amending the
cpupower.default file and trying out the governor and frequency options.
I did encounter the systemd service exiting on boot after setting
performance options. The service set my options mostly correctly; my
machine has a limited number of cpu governors. This may have been my error and
I will need to test more when I have time.

Adding my tags.

Reviewed-by: John B. Wyatt IV <jwyatt@redhat.com>
Reviewed-by: John B. Wyatt IV <sageofredondo@gmail.com>
Tested-by: John B. Wyatt IV <jwyatt@redhat.com>
Tested-by: John B. Wyatt IV <sageofredondo@gmail.com>
Shuah Khan May 2, 2025, 7:55 p.m. UTC | #2
On 5/2/25 10:41, Shuah Khan wrote:
> On 5/2/25 09:53, Francesco Poli wrote:
>> On Tue, 29 Apr 2025 16:59:03 -0400 John B. Wyatt IV wrote:
>>
>> [...]
>>> Adding my tags.
>>>
>>> Reviewed-by: John B. Wyatt IV <jwyatt@redhat.com>
>>> Reviewed-by: John B. Wyatt IV <sageofredondo@gmail.com>
>>> Tested-by: John B. Wyatt IV <jwyatt@redhat.com>
>>> Tested-by: John B. Wyatt IV <sageofredondo@gmail.com>
>>
>> Thanks a lot for reviewing and testing my patch!
>>
>> Do I need to resend the patch (without any change) with these tags
>> added to the commit message?
>> Or is it pointless?
>>
>>
> 
> No need to resend. I will apply this later on today.
> 
> thanks,
> -- Shuah

Applied now for Linux 6.16-rc1 - will be included in pull request to
PM maintainer.

https://web.git.kernel.org/pub/scm/linux/kernel/git/shuah/linux.git/log/?h=cpupower

thanks,
-- Shuah
Francesco Poli May 5, 2025, 8:55 p.m. UTC | #3
On Mon, 5 May 2025 18:06:30 +0200 Thorsten Leemhuis wrote:

[...]
> On 25.04.25 17:07, Francesco Poli (wintermute) wrote:
[...]
> > Signed-off-by: Francesco Poli (wintermute) <invernomuto@paranoici.org>
> 
> Lo! I'm wondering if the the DESTDIR usage in this patch is wrong, as it
> caused trouble for me today when it showed up in -next. During debugging
> I furthermore found a related problem.

Hello Thorsten!

I am sorry for the trouble that my patch caused, while you were testing
the build of RPM packages for Fedora.
Thanks a lot for taking a deeper look at the issue!

> 
> > diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
> > index 835123add0ed..9c2b5f71fee1 100644
> > --- a/tools/power/cpupower/Makefile
> > +++ b/tools/power/cpupower/Makefile
> > @@ -2,6 +2,7 @@
> >  # Makefile for cpupower
[...]
> > +	sed 's|___CDIR___|$(DESTDIR)${confdir}|; s|___LDIR___|$(DESTDIR)${libexecdir}|' cpupower.service.in > '$(DESTDIR)${libdir}/systemd/system/cpupower.service'
> 
> While building -next kernel RPMS for Fedora the above line lead to the
> this build error today:
> 
> """
> /builddir/build/BUILD/kernel-6.15.0-build/BUILDROOT/usr/lib64/systemd/system/cpupower.service
> Found '/builddir/build/BUILD/kernel-6.15.0-build/BUILDROOT' in installed
> files; aborting
> """
> 
> This somewhat cryptic error message means that the path
> "/builddir/build/BUILD/kernel-6.15.0-build/BUILDROOT/" ended up in the
> file "cpupower.service"; RPM noticed that and rightfully aborts the
> build, as that path should not end up there. It's inserted by the sed
> call in the last line quoted above.

Yes, that seems to be exactly what happened.

> 
> I could easily fix this up in the RPM spec file with another sed call,
> but wonder if that path should end up there in the first place. Not
> quite sure, but I guess it should not (removing the first two
> "$(DESTDIR)" in the line with the quoted sed call would fix that).

I probably misunderstood the purpose of DESTDIR.

I thought it was intended to define a custom final destination for the
installed files (as in "I want the whole thing to be installed there!").

But maybe it is instead intended to define a custom temporary
destination for the installed files, which will be later relocated to
the root directory / (as in "I want the installation to end up there,
because I am building a distribution package, but the files that are
placed there, will eventually end up under / , once the package is
actually installed on an actual system!").

If the main purpose of DESTDIR is to define a temporary install
directory for (RPM/DEB/...) package builds, then I agree that the sed
call should not have those two "$(DESTDIR)" in the regular expressions.

I can prepare a fix for this issue, if others confirm that the intended
purpose of DESTDIR is to help package builds.

By the way, should I prepare a v3 patch, or a new patch on top of the
origin/cpupower git branch?

[...]
> > +	$(SETPERM_DATA) '$(DESTDIR)${libdir}/systemd/system/cpupower.service'
> > +	if test -d /run/systemd/system; then systemctl daemon-reload; fi
> 
> While investigating the issue I did a manual local build using
> "make DESTDIR=~/tmp/out libdir=/usr/lib64 CPUFREQ_BENCH=false install"
> to take a closer look. That make call then made systemd ask me for the
> root password, which I found odd. Turns out that happens due to that "if
> test -d" command quoted above.

Yes, this is another aspect that seemed tricky to me.

I thought that the "systemctl daemon-reload" should be automated
through the Makefile, but I agree that issuing this command is not
always useful or desired.

If the "make install" call writes the 'cpupower.service' file to a
location where systemd does not look at all, then reloading the systemd
daemon is pointless. Also, if the EUID is not root, reloading the
systemd daemon is probably not what you want to (or can) do.

I could add other conditions to the "if", but maybe we should not
complicate things too much.
Maybe it's better if I drop the "systemd daemon-reload" command
entirely, and add something to the 'README' file (a suggestion to issue
this command manually, if one wants to let systemd see the new service
immediately, without waiting for the next reboot).
After all, distribution packages have automation for systemd service
unit installation anyway...

What do others think?

> 
> I'd say that should not have happened this case (or maybe in general?).
> The service afterwards would not have been available in systemd anyway,
> as the service file was as instructed installed to
> ~/tmp/out/usr/lib64/systemd/system/cpupower.service -- but there systemd
> would never have found it own it's own, so reloading the daemon is
> meaningless in this case anyway.

Yes.
As I said above, you are probably right that there are a good number of
cases, where one does not want or need to reload the systemd daemon...

> 
> Ciao, Thorsten

Bye.
And thank you again for reviewing these aspects of my patch!   :-)
Thorsten Leemhuis May 7, 2025, 8:07 a.m. UTC | #4
Lo, me again. Sorry, found a minor aspect I wanted to bring up for
discussion:

On 25.04.25 17:07, Francesco Poli (wintermute) wrote:
> One of the most typical use cases of the 'cpupower' utility works as
> follows: run 'cpupower' at boot with the desired command-line options
> and then forget about it.
> [...]
>  tools/power/cpupower/cpupower.default    | 28 ++++++++++++++++++++++++
> [...]
> +	$(INSTALL) -d $(DESTDIR)${confdir}default
> +	$(INSTALL_DATA) cpupower.default '$(DESTDIR)${confdir}default/cpupower'

/etc/default/ is to the best of my knowledge (everyone: please correct
me if I'm wrong!) a Debianism and on rarely used (or maybe not at all,
not sure) in distros unrelated to Debian. So I'd say it's a bad choice
to place that file. Why not put it simply straight into /etc/ ?

Side node: the config file is also basically a template, which makes me
wonder if it should land in /usr/share/doc or something like that anyway
so users take a look at adjust it to their needs. But it's just a
thought, I have no strong opinions with regards to this.

Ciao, Thorsten
Francesco Poli May 7, 2025, 10:18 p.m. UTC | #5
On Wed, 7 May 2025 10:07:33 +0200 Thorsten Leemhuis wrote:

[...]
> On 25.04.25 17:07, Francesco Poli (wintermute) wrote:
> > One of the most typical use cases of the 'cpupower' utility works as
> > follows: run 'cpupower' at boot with the desired command-line options
> > and then forget about it.
> > [...]
> >  tools/power/cpupower/cpupower.default    | 28 ++++++++++++++++++++++++
> > [...]
> > +	$(INSTALL) -d $(DESTDIR)${confdir}default
> > +	$(INSTALL_DATA) cpupower.default '$(DESTDIR)${confdir}default/cpupower'
> 
> /etc/default/ is to the best of my knowledge (everyone: please correct
> me if I'm wrong!) a Debianism and on rarely used (or maybe not at all,
> not sure) in distros unrelated to Debian.

I thought that /etc/default was used in other distros, as well, not
only on Debian-derivatives...

For instance on [RedHat] Enterprise Linux and (consequently) on [Rocky]
Linux for [GRUB], for [useradd], and so forth...

[RedHat]: <https://access.redhat.com/solutions/3185891>
[GRUB]: <https://docs.rockylinux.org/books/admin_guide/10-boot/#the-grub2-bootloader>
[useradd]: <https://docs.rockylinux.org/books/admin_guide/06-users/#default-value-for-user-creation>

What do others think?

> So I'd say it's a bad choice
> to place that file. Why not put it simply straight into /etc/ ?

Because /etc/cpupower.conf makes me think it's a configuration file for
cpupower, rather than for the cpupower.service that runs cpupower at
boot.

> Side node: the config file is also basically a template, which makes me
> wonder if it should land in /usr/share/doc or something like that anyway
> so users take a look at adjust it to their needs. But it's just a
> thought, I have no strong opinions with regards to this.

Well, I would prefer to have a configuration file in the right
location, ready to be edited by the sysadmin.

This way distros (at least Debian and Debian-derivatives) can mark it
as a conffile, so that the package manager handles its update, when the
copy shipped by the package changes, but there are local modifications
by the sysadmin to be migrated to the new structure.
The Debian package manager (dpkg) has ways to cope with this scenario,
I am not sure about other (non Debian-derivative) distros...
Thorsten Leemhuis May 8, 2025, 8:02 a.m. UTC | #6
On 08.05.25 00:18, Francesco Poli wrote:
> On Wed, 7 May 2025 10:07:33 +0200 Thorsten Leemhuis wrote:
> 
> [...]
>> On 25.04.25 17:07, Francesco Poli (wintermute) wrote:
>>> One of the most typical use cases of the 'cpupower' utility works as
>>> follows: run 'cpupower' at boot with the desired command-line options
>>> and then forget about it.
>>> [...]
>>>  tools/power/cpupower/cpupower.default    | 28 ++++++++++++++++++++++++
>>> [...]
>>> +	$(INSTALL) -d $(DESTDIR)${confdir}default
>>> +	$(INSTALL_DATA) cpupower.default '$(DESTDIR)${confdir}default/cpupower'
>>
>> /etc/default/ is to the best of my knowledge (everyone: please correct
>> me if I'm wrong!) a Debianism and on rarely used (or maybe not at all,
>> not sure) in distros unrelated to Debian.
> 
> I thought that /etc/default was used in other distros, [...]

Well, sure, as I tried to express with "rarely".

But it becomes a big mess if some of us put files in /etc/default,
others in /etc/sysconfig (the equivalent in the RH universe where I
live), and others in
/etc/some_other_dir_another_distro_chose_wisely_for_this_purpose/.

So I'd say it's best to not introduce any new files in such directories,
unless of course in packages meant for exactly that distro.

See also: https://0pointer.de/blog/projects/on-etc-sysinit.html

Ciao, Thorsten
John B. Wyatt IV May 14, 2025, 5:53 p.m. UTC | #7
On Wed, May 14, 2025 at 02:41:35PM +0200, Thorsten Leemhuis wrote:
> Hi Francesco! Many thx for addressing the issues I brought up earlier
> which now landed in -next, much appreciated.
> 
> Sadly with those fixes in I noticed another issue I missed earlier. One
> from the "small differences between different Linux distributions that
> make all our lives hard". :-/media/
> 
> On 25.04.25 17:07, Francesco Poli (wintermute) wrote:
> > One of the most typical use cases of the 'cpupower' utility works as
> > follows: run 'cpupower' at boot with the desired command-line options
> > and then forget about it.
> 
> > diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
> > index 835123add0ed..9c2b5f71fee1 100644
> > [...]
> > @@ -302,6 +305,14 @@ install-tools: $(OUTPUT)cpupower
> >  	$(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir}
> >  	$(INSTALL) -d $(DESTDIR)${bash_completion_dir}
> >  	$(INSTALL_SCRIPT) cpupower-completion.sh '$(DESTDIR)${bash_completion_dir}/cpupower'
> > +	$(INSTALL) -d $(DESTDIR)${confdir}default
> > +	$(INSTALL_DATA) cpupower.default '$(DESTDIR)${confdir}default/cpupower'
> > +	$(INSTALL) -d $(DESTDIR)${libexecdir}
> > +	$(INSTALL_PROGRAM) cpupower.sh '$(DESTDIR)${libexecdir}/cpupower'
> > +	$(INSTALL) -d $(DESTDIR)${libdir}/systemd/system
> 
> That last line to the best of my knowledge is wrong on distributions
> like Fedora, where ${libdir} expands to /usr/lib64/ -- which is the
> right path for libraries, but the wrong one for systemd units, as they
> are always stored in /usr/lib/systemd/system (at least on Fedora). Not
> sure what the right fix it, it might be something like defining
> 
> unitdir ?= /usr/lib/systemd/system
> 
> earlier in the Makefile and then using it in the last quoted line above.
> 
> Ciao, Thorsten
> 

Checked the Arch pkgs and my Ubuntu 22.04 install.

Both of them copy service files to that folder as well. The Debian package
is difficult to read at a glance.

The problem is that Fedora installs libraries to lib64; Arch and Ubuntu
(22.04 & likely Debian) do not from what I can tell. This likely is the
reason for that issue I had-I thought I misconfigured something or it
was a bug in cpupower logic.

That unitdir looks like it would be a good suggestion as a quick fix,
but Shuah, how are you feeling about these patches?

I am on mobile data right now due to an internet issue so my ability to
test is limited right now.
Francesco Poli May 14, 2025, 8:23 p.m. UTC | #8
On Wed, 14 May 2025 14:41:35 +0200 Thorsten Leemhuis wrote:

> Hi Francesco!

Hello Thorsten!

> Many thx for addressing the issues I brought up earlier
> which now landed in -next, much appreciated.

You're welcome, I am glad you appreciated it.

> 
> Sadly with those fixes in I noticed another issue I missed earlier. One
> from the "small differences between different Linux distributions that
> make all our lives hard". :-/

OK, the fix is simple: all other distros should be more similar to
Debian!   ;-)

...just kidding, of course!   :p

> 
> On 25.04.25 17:07, Francesco Poli (wintermute) wrote:
> > One of the most typical use cases of the 'cpupower' utility works as
> > follows: run 'cpupower' at boot with the desired command-line options
> > and then forget about it.
> 
> > diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
> > index 835123add0ed..9c2b5f71fee1 100644
> > [...]
> > @@ -302,6 +305,14 @@ install-tools: $(OUTPUT)cpupower
> >  	$(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir}
> >  	$(INSTALL) -d $(DESTDIR)${bash_completion_dir}
> >  	$(INSTALL_SCRIPT) cpupower-completion.sh '$(DESTDIR)${bash_completion_dir}/cpupower'
> > +	$(INSTALL) -d $(DESTDIR)${confdir}default
> > +	$(INSTALL_DATA) cpupower.default '$(DESTDIR)${confdir}default/cpupower'
> > +	$(INSTALL) -d $(DESTDIR)${libexecdir}
> > +	$(INSTALL_PROGRAM) cpupower.sh '$(DESTDIR)${libexecdir}/cpupower'
> > +	$(INSTALL) -d $(DESTDIR)${libdir}/systemd/system
> 
> That last line to the best of my knowledge is wrong on distributions
> like Fedora, where ${libdir} expands to /usr/lib64/ -- which is the
> right path for libraries, but the wrong one for systemd units, as they
> are always stored in /usr/lib/systemd/system (at least on Fedora). Not
> sure what the right fix it, it might be something like defining
> 
> unitdir ?= /usr/lib/systemd/system
> 
> earlier in the Makefile and then using it in the last quoted line above.

This could be the right fix, I think.
And it would improve the flexibility of the Makefile, as well.

If nobody raises objections, I will prepare another patch to address
this issue.

> 
> Ciao, Thorsten

Tschüss!
Francesco Poli May 14, 2025, 8:39 p.m. UTC | #9
On Wed, 14 May 2025 13:53:11 -0400 John B. Wyatt IV wrote:

[...]
> Checked the Arch pkgs and my Ubuntu 22.04 install.
> 
> Both of them copy service files to that folder as well.

Yes, systemd.unit(5) man page (on my Debian trixie installation) says
that

  /usr/lib/systemd/system/*

is on the System Unit Search Path.

> The Debian package
> is difficult to read at a glance.
> 
> The problem is that Fedora installs libraries to lib64; Arch and Ubuntu
> (22.04 & likely Debian) do not from what I can tell.

I confirm that, on Debian, the libraries do not go to lib64 .
The following is the list of files shipped by the 'libcpupower1' binary
package (on my Debian trixie installation):

  $ dpkg -L libcpupower1
  /.
  /usr
  /usr/lib
  /usr/lib/x86_64-linux-gnu
  /usr/lib/x86_64-linux-gnu/libcpupower.so.0.0.1
  /usr/share
  /usr/share/doc
  /usr/share/doc/libcpupower1
  /usr/share/doc/libcpupower1/changelog.Debian.gz
  /usr/share/doc/libcpupower1/copyright
  /usr/share/lintian
  /usr/share/lintian/overrides
  /usr/share/lintian/overrides/libcpupower1
  /usr/lib/x86_64-linux-gnu/libcpupower.so.1
Thorsten Leemhuis May 15, 2025, 6:12 a.m. UTC | #10
On 14.05.25 22:23, Francesco Poli wrote:
> On Wed, 14 May 2025 14:41:35 +0200 Thorsten Leemhuis wrote:
>> Sadly with those fixes in I noticed another issue I missed earlier. One
>> from the "small differences between different Linux distributions that
>> make all our lives hard". :-/
>
> OK, the fix is simple: all other distros should be more similar to
> Debian!   ;-)
> 
> ...just kidding, of course!   :p

:-D

>> On 25.04.25 17:07, Francesco Poli (wintermute) wrote:
> [...]
>>> +	$(INSTALL) -d $(DESTDIR)${libdir}/systemd/system
>>
>> That last line to the best of my knowledge is wrong on distributions
>> like Fedora, where ${libdir} expands to /usr/lib64/ -- which is the
>> right path for libraries, but the wrong one for systemd units, as they
>> are always stored in /usr/lib/systemd/system (at least on Fedora). Not
>> sure what the right fix it, it might be something like defining
>>
>> unitdir ?= /usr/lib/systemd/system
>>
>> earlier in the Makefile and then using it in the last quoted line above.
> 
> This could be the right fix, I think.
> And it would improve the flexibility of the Makefile, as well.
> 
> If nobody raises objections, I will prepare another patch to address
> this issue.

Thx!

FWIW, after sending my mail my brain worked out that there is another
problem. One that was there before your patches. One someone here might
be interested to address. That

libdir ?=       /usr/lib

in tools/power/cpupower/Makefile will obviously do the wrong thing on
distros that use /usr/lib64/ for 64bit libs (like Fedora and iirc
openSUSE, too -- and all their derivatives of course). From a quick look
other Makefiles we ship handle that fine by default, as during a quick
grep I spotted code to handle the right lib/lib64 placement in Makefiles
like tools/lib/bpf/Makefile, tools/net/ynl/Makefile, or
tools/lib/perf/Makefile.

Ciao, Thorsten
diff mbox series

Patch

diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index 835123add0ed..9c2b5f71fee1 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -2,6 +2,7 @@ 
 # Makefile for cpupower
 #
 # Copyright (C) 2005,2006 Dominik Brodowski <linux@dominikbrodowski.net>
+# Copyright (C) 2025      Francesco Poli <invernomuto@paranoici.org>
 #
 # Based largely on the Makefile for udev by:
 #
@@ -71,6 +72,7 @@  bindir ?=	/usr/bin
 sbindir ?=	/usr/sbin
 mandir ?=	/usr/man
 libdir ?=	/usr/lib
+libexecdir ?=	/usr/libexec
 includedir ?=	/usr/include
 localedir ?=	/usr/share/locale
 docdir ?=       /usr/share/doc/packages/cpupower
@@ -83,6 +85,7 @@  CP = cp -fpR
 INSTALL = /usr/bin/install -c
 INSTALL_PROGRAM = ${INSTALL}
 INSTALL_DATA  = ${INSTALL} -m 644
+SETPERM_DATA  = chmod 644
 #bash completion scripts get sourced and so they should be rw only.
 INSTALL_SCRIPT = ${INSTALL} -m 644
 
@@ -302,6 +305,14 @@  install-tools: $(OUTPUT)cpupower
 	$(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir}
 	$(INSTALL) -d $(DESTDIR)${bash_completion_dir}
 	$(INSTALL_SCRIPT) cpupower-completion.sh '$(DESTDIR)${bash_completion_dir}/cpupower'
+	$(INSTALL) -d $(DESTDIR)${confdir}default
+	$(INSTALL_DATA) cpupower.default '$(DESTDIR)${confdir}default/cpupower'
+	$(INSTALL) -d $(DESTDIR)${libexecdir}
+	$(INSTALL_PROGRAM) cpupower.sh '$(DESTDIR)${libexecdir}/cpupower'
+	$(INSTALL) -d $(DESTDIR)${libdir}/systemd/system
+	sed 's|___CDIR___|$(DESTDIR)${confdir}|; s|___LDIR___|$(DESTDIR)${libexecdir}|' cpupower.service.in > '$(DESTDIR)${libdir}/systemd/system/cpupower.service'
+	$(SETPERM_DATA) '$(DESTDIR)${libdir}/systemd/system/cpupower.service'
+	if test -d /run/systemd/system; then systemctl daemon-reload; fi
 
 install-man:
 	$(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1
@@ -336,6 +347,9 @@  uninstall:
 	- rm -f $(DESTDIR)${includedir}/cpufreq.h
 	- rm -f $(DESTDIR)${includedir}/cpuidle.h
 	- rm -f $(DESTDIR)${bindir}/utils/cpupower
+	- rm -f $(DESTDIR)${confdir}default/cpupower
+	- rm -f $(DESTDIR)${libexecdir}/cpupower
+	- rm -f $(DESTDIR)${libdir}/systemd/system/cpupower.service
 	- rm -f $(DESTDIR)${mandir}/man1/cpupower.1
 	- rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1
 	- rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1
@@ -346,6 +360,7 @@  uninstall:
 	- for HLANG in $(LANGUAGES); do \
 		rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
 	  done;
+	- if test -d /run/systemd/system; then systemctl daemon-reload; fi
 
 help:
 	@echo  'Building targets:'
diff --git a/tools/power/cpupower/README b/tools/power/cpupower/README
index 2678ed81d311..e6ae7c1e0a0d 100644
--- a/tools/power/cpupower/README
+++ b/tools/power/cpupower/README
@@ -59,6 +59,10 @@  $ sudo make install
 -----------------------------------------------------------------------
 | man pages              | /usr/man                                   |
 -----------------------------------------------------------------------
+| systemd service        | /usr/lib                                   |
+-----------------------------------------------------------------------
+| systemd support script | /usr/libexec                               |
+-----------------------------------------------------------------------
 
 To put it in other words it makes build results available system-wide,
 enabling any user to simply start using it without any additional steps
@@ -109,6 +113,10 @@  The files will be installed to the following dirs:
 -----------------------------------------------------------------------
 | man pages              | ${DESTDIR}/usr/man                         |
 -----------------------------------------------------------------------
+| systemd service        | ${DESTDIR}/usr/lib                         |
+-----------------------------------------------------------------------
+| systemd support script | ${DESTDIR}/usr/libexec                     |
+-----------------------------------------------------------------------
 
 If you look at the table for the default 'make' output dirs you will
 notice that the only difference with the non-default case is the
@@ -173,6 +181,17 @@  The issue is that binary cannot find the 'libcpupower' library. So, we
 shall point to the lib dir:
 sudo LD_LIBRARY_PATH=lib64/ ./bin/cpupower
 
+systemd service
+---------------
+
+A systemd service is also provided to run the cpupower utility at boot with
+settings read from a configuration file. In order to enable this systemd
+service, edit '${DESTDIR}/etc/default/cpupower' (uncommenting at least one of
+the options, depending on your preferences) and then issue the following
+command:
+
+$ sudo systemctl enable --now cpupower.service
+
 
 THANKS
 ------
diff --git a/tools/power/cpupower/cpupower.default b/tools/power/cpupower/cpupower.default
new file mode 100644
index 000000000000..376ca40fe5a6
--- /dev/null
+++ b/tools/power/cpupower/cpupower.default
@@ -0,0 +1,28 @@ 
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2012, Sébastien Luttringer
+# Copyright (C) 2024-2025, Francesco Poli <invernomuto@paranoici.org>
+
+# Default file for linux-cpupower
+
+# --- CPU clock frequency ---
+
+# Define CPU governor
+# Valid governors: ondemand, performance, powersave, conservative, userspace
+#GOVERNOR='ondemand'
+
+# Limit frequency range
+# Valid suffixes: Hz, kHz (default), MHz, GHz, THz
+#MIN_FREQ="2.25GHz"
+#MAX_FREQ="3GHz"
+
+# Specific frequency to be set.
+# Requires userspace governor to be available.
+# If this option is set, all the previous frequency options are ignored
+#FREQ=
+
+# --- CPU policy ---
+
+# Sets a register on supported Intel processore which allows software to convey
+# its policy for the relative importance of performance versus energy savings to
+# the processor. See man CPUPOWER-SET(1) for additional details
+#PERF_BIAS=
diff --git a/tools/power/cpupower/cpupower.service.in b/tools/power/cpupower/cpupower.service.in
new file mode 100644
index 000000000000..f91eaed03872
--- /dev/null
+++ b/tools/power/cpupower/cpupower.service.in
@@ -0,0 +1,16 @@ 
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2012-2020, Sébastien Luttringer
+# Copyright (C) 2024, Francesco Poli <invernomuto@paranoici.org>
+
+[Unit]
+Description=Apply cpupower configuration
+ConditionVirtualization=!container
+
+[Service]
+Type=oneshot
+EnvironmentFile=-___CDIR___default/cpupower
+ExecStart=___LDIR___/cpupower
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/tools/power/cpupower/cpupower.sh b/tools/power/cpupower/cpupower.sh
new file mode 100644
index 000000000000..a37dd4cfdb2b
--- /dev/null
+++ b/tools/power/cpupower/cpupower.sh
@@ -0,0 +1,26 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2012, Sébastien Luttringer
+# Copyright (C) 2024, Francesco Poli <invernomuto@paranoici.org>
+
+ESTATUS=0
+
+# apply CPU clock frequency options
+if test -n "$FREQ"
+then
+    cpupower frequency-set -f "$FREQ" > /dev/null || ESTATUS=1
+elif test -n "${GOVERNOR}${MIN_FREQ}${MAX_FREQ}"
+then
+    cpupower frequency-set \
+      ${GOVERNOR:+ -g "$GOVERNOR"} \
+      ${MIN_FREQ:+ -d "$MIN_FREQ"} ${MAX_FREQ:+ -u "$MAX_FREQ"} \
+      > /dev/null || ESTATUS=1
+fi
+
+# apply CPU policy options
+if test -n "$PERF_BIAS"
+then
+    cpupower set -b "$PERF_BIAS" > /dev/null || ESTATUS=1
+fi
+
+exit $ESTATUS