Skip to content

Add Dynamic Voltage and Frequency Scaling Driver Class - #567

Closed
Cheng-Li1 wants to merge 18 commits into
mainfrom
freq-scaling-example
Closed

Add Dynamic Voltage and Frequency Scaling Driver Class#567
Cheng-Li1 wants to merge 18 commits into
mainfrom
freq-scaling-example

Conversation

@Cheng-Li1

@Cheng-Li1 Cheng-Li1 commented Nov 19, 2025

Copy link
Copy Markdown

Add the DVFS(Dynamic Voltage and Frequency Scaling) driver class and associated interfaces, and the implementation of the DVFS driver for the ZCU102 platform.

Cheng-Li1 and others added 11 commits November 18, 2025 14:56
Signed-off-by: Cheng <lichengchaoreng@gmail.com>
Signed-off-by: Cheng <lichengchaoreng@gmail.com>
Signed-off-by: Cheng <lichengchaoreng@gmail.com>
Signed-off-by: Cheng <lichengchaoreng@gmail.com>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
@midnightveil

Copy link
Copy Markdown
Contributor

Same comment as previous: is there a design written up for this that we can look at?

@Cheng-Li1

Copy link
Copy Markdown
Author

Same comment as previous: is there a design written up for this that we can look at?

Writing the doc now. Should be available soon.

Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
@Cheng-Li1
Cheng-Li1 force-pushed the freq-scaling-example branch from 884d1cb to 50a87d3 Compare November 19, 2025 04:09
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
@Cheng-Li1

Copy link
Copy Markdown
Author

I have added a section about DVFS in the design doc.

@Cheng-Li1
Cheng-Li1 marked this pull request as ready for review November 26, 2025 05:34
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
Signed-off-by: Cheng Li <cheng.li10@unsw.edu.au>
@omeh-a

omeh-a commented Feb 25, 2026

Copy link
Copy Markdown
Member

The description of what DVFS in the design doc could use a prune. Dynamic and static power (static in particular) aren't super important and things like defining CMOS seem totally irrelevant (all semiconductors have dynamic and static power usage!). I would drop the static power bits and just go straight into "The dynamic power of a computer is roughly given by ...."

The equation for dynamic power is also wrong as it omits the activity factor, but tbh I think that doesn't really matter. I would reword the description below however as it is misleading

The power scales linearly with the frequency and quadratically with voltage. Lowering the frequency, which usually allows a lower supply voltage, can dramatically lower the power consumption as well as the generated heat.

Power itself has a quadratic relationship to voltage when current is omitted (P=V^2/R), but crucially the voltage doesn't "scale" in the same way frequency does. There simply needs to be sufficient voltage for all transistors to switch at a given frequency (as you already point out).

I think you should just omit mentioning the linear vs exponential scaling because this might cause a reader to falsely conclude that these are independent quantities, when in reality a truer expression of dynamic power should express voltage as a function of frequency since it should be minimised.

Comment thread docs/design/design.tex

\paragraph{Direct interact with the clock/regulator:} The DVFS driver directly interacts
with the clock and the regulator that control the frequency and the voltage the processing
units are operating on. This approach is used on most of the ARM or RISC-V platforms.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How else would it work?

Comment thread docs/design/design.tex
procedures that can be called:
\begin{description}
\item[\texttt{get\_freq(core\_identifier)}]
Retrieves the current actual frequency of a specific processing unit.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove "actual"

Comment thread docs/design/design.tex
\item[\texttt{get\_freq(core\_identifier)}]
Retrieves the current actual frequency of a specific processing unit.
\item[\texttt{set\_freq(core\_identifier, frequency)}]
Sets the designated processing unit to a specific target frequency. The frequency

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove "specific"

@omeh-a

omeh-a commented Feb 26, 2026

Copy link
Copy Markdown
Member

This driver also doesn't match the form of the sDDF's directory structure, you should move all current work to drivers/dvfs/{platform}/

I see that cpufreq implements this internally ... still seems clumsy this way though. Maybe it should be in drivers/dvfs/rust? @Ivan-Velickovic maybe you have thoughts. It certainly needs to move anyway to have the C driver coexist.

Third note ... I see that this driver actually hardcodes Xilinx things so just making it rust would also be wrong. I will just make it zcu102 in my branch based on this.


#[derive(Debug)]
pub enum Error {
EINVAL = 0,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a rust person ... but what is the point of this error? Isn't it simpler to use a builtin error type given that this enum only has one member?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree that it would be better to use a standardized error type instead of having their own error types in the driver. The thing is that I don't think(I might be wrong) that there is a built-in error enum in Rust, nor is there a universal error enum in our system. I would be more than happy to switch to a universal error enum in our system.

// SPDX-License-Identifier: BSD-2-Clause

#[derive(Debug)]
pub struct OppEntry {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should rename this to OpEntry for clarity, since "Operating point" only has one P :P

@midnightveil midnightveil left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The design notes should be improved.

Comment thread docs/design/design.tex
Comment on lines +2601 to +2615
\paragraph{Core Configuration (CoreInfo)}
Describes the topology of the processor. The configuration describes
the number of the processing units, the clock source they are operating under
(one clock source may provide clock for multiple processing units, which means
changing the frequency for one unit would change the frequency of all the units
which has the same clock source), and the Operating Performance Point table.

\begin{lstlisting}
typedef struct {
uint64_t core_ident; // Logical Core ID
uint64_t clock_source_ident; // ID of the clock source
const OppEntry *opptable; // Pointer to valid OPPs for this core
size_t opptable_len; // Number of OPPs
} CoreInfo;
\end{lstlisting}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Peter cleared this up for me: the reason why we have this structure is because this is how the DTS describes things.

The reason why we have described things in terms of this structure is because this is how the DTS does generically for Linux. I think we should be explicit about this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, Lesley told me that it would be best to read the struct from the dts. For now, I will stress this structure and the info is derived from Linux DTS.

Comment thread docs/design/design.tex
Comment on lines +2582 to +2585
\paragraph{Firmware Abstraction:} For some very new ARM platforms, System Control and
Management Interface (SCMI) is supported, providing a unified framework to manage the
the power state of the processing units. For x86 platforms, ACPI and HWP are the common
framework to provide platform agnostic power management interfaces.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this make any sense to include here if we don't use it at all?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible that we might have a board that actually supports SCMI in the future, though.

EINVAL = 0,
}

pub trait FreqOps {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need to be a trait.

As I've mentioned before, our API is cross-process, not through code.

There's zero reason for a trait here, especially not one with a bunch of helpers that have panic!() for no reason.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trait defines the behaviors of the drivers, and the drivers following the sddf protocol do not necessarily mean that the driver cannot have a set of behaviors that they need to follow internally. I can ask around to see whether others are unsatisfied with the design, and if so, I will change it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trait is unnecessary, though?

Comment thread drivers/dvfs/src/main.rs
Comment on lines +4 to +5
#![no_std] // Don't link the standard library
#![no_main] // Don't use the default entry point

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again as I've mentioned this before you don't need to say what these are.

Comment thread drivers/dvfs/Cargo.toml
Comment on lines +11 to +14
cpufreq = { path = "cpufreq" }
sddf-rust = { path = "../../include/sddf-rust" }
sel4-microkit = { git = "https://github.com/seL4/rust-sel4.git", tag = "v3.0.0" }
sddf-ipc-types = { git = "https://github.com/seL4/rust-sel4.git", tag = "v3.0.0" } No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(code nit) these should be part of workspace dependenies for the whole of seL4, and should not hardcode relative paths.

Comment on lines +7 to +23
[toolchain]
channel = "nightly-2025-10-20"
profile = "default"
components = [
"rust-src",
"rustc-dev",
"llvm-tools-preview",
"rust-analyzer",
]
targets = [
"x86_64-unknown-linux-musl",
"aarch64-unknown-linux-musl",
"armv7-unknown-linux-musleabi",
"riscv64gc-unknown-linux-musl",
# tier 2, not available via rustup
# "riscv32gc-unknown-linux-musl",
] No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

Comment thread examples/dvfs/dvfs.mk
Comment on lines +105 to +106
echo "MICROKIT SDK config directory: $(microkit_sdk_config_dir)" && \
echo "SEl4 include directories: $(sel4_include_dirs)" && \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these echo are unneededed

* @param core_ident The unique identifier of the CPU core.
* @param freq A pointer to a unsighed integer to pass back the returned frequency.
*/
static inline int32_t sddf_dvfs_get_freq(unsigned int channel, uint64_t core_ident, uint64_t *freq)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a critical problem of motivation with this protocol: why are we giving frequencies at all? This driver is meant to change the voltage AND frequency, and more importantly it can only do that for values in the operating point table. Surely we should be setting an operating point index instead right?

@omeh-a omeh-a mentioned this pull request Mar 12, 2026
5 tasks
@omeh-a

omeh-a commented May 21, 2026

Copy link
Copy Markdown
Member

This PR is now redundant due to #667 - this version doesn't have a design that is portable to other platforms and isn't mergable due to the state of our rust support. Given that this PR has remained untouched for months and is replaced, I think we should close this PR

@omeh-a

omeh-a commented Jun 4, 2026

Copy link
Copy Markdown
Member

Closing as this PR is redundant.

@omeh-a omeh-a closed this Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants