#[non_exhaustive]pub enum KernelValue {
U32(u32),
U64(u64),
Bytes(Vec<u8>),
OrU32(u32),
}Expand description
Value payload for the kernel-memory write ops, and the result shape for the read ops.
The variant tag picks both the width (u32 vs u64 vs a byte
slice) and the underlying crate::monitor::guest::GuestKernel
write helper the host coordinator will invoke (write_*_u32,
write_*_u64, write_*_bytes per the KernelTarget class).
§#[non_exhaustive]
KernelValue is #[non_exhaustive] so new value widths can be
added without breaking external pattern-matchers. Prefer the
per-variant constructors over naming variant literals.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
U32(u32)
32-bit unsigned little-endian write. Atomic when the
resolved host PA is 4-byte aligned. Misaligned PAs fall
through to a per-byte volatile loop in
crate::monitor::reader::GuestMem
write_volatile_bytes (the 4-byte fast path branches on
ptr.align_offset(align_of::<u32>()) == 0 and only emits
a single write_volatile when alignment holds); torn
intermediate state is observable to concurrent guest readers
in the fallback case.
For setting individual bits without disturbing the
surrounding value, use Self::OrU32 instead — that
variant performs read-modify-write OR semantics under the
freeze rendezvous (e.g. setting SCX_RQ_CLK_VALID in
rq.scx.flags without clobbering the other 31 flag bits).
A plain U32(value) write replaces every bit; OrU32 sets
only the bits in the mask.
U64(u64)
64-bit unsigned little-endian write. Atomic when the
resolved host PA is 8-byte aligned. See the alignment note
on Self::U32 for the misaligned fall-through behaviour.
No OrU64 sibling exists by design. The canonical
scheduler-flags use case (KernelValue::OrU32 →
struct scx_rq.flags) is on a u32 field per
kernel/sched/sched.h:803; a 64-bit RMW at that address
would corrupt the adjacent u32 nr_immed field at
kernel/sched/sched.h:804. If a future u64 RMW use case
emerges with a verified width, add the variant then.
Bytes(Vec<u8>)
Variable-length byte payload. Written non-atomically; the
GuestKernel::write_*_bytes helpers emit a Release fence
after the copy so a weakly-ordered guest’s
smp_load_acquire observes the bytes in write order — the
fence orders the stores but does NOT atomicize the
multi-byte write versus a concurrent guest reader.
OrU32(u32)
32-bit unsigned read-modify-write OR. The dispatcher reads
the live u32 at the resolved host PA, ORs the carried mask
into it, and writes the new value back. Width is u32 — the
canonical use case is OR-ing a single-bit kernel flag (e.g.
SCX_RQ_CLK_VALID = 1 << 5) into struct scx_rq.flags,
declared u32 at kernel/sched/sched.h:803 inside the
struct opened at L793. A 64-bit RMW at a u32 field address
would either silently truncate the upper 32 bits or
corrupt the adjacent u32 nr_immed field at
kernel/sched/sched.h:804, so the variant tag itself
picks the width and rules out width mismatch at the call
site.
Atomicity (cold-path dispatcher): the host coordinator
holds the freeze rendezvous for the duration of the RMW —
every guest vCPU is parked on a futex inside handle_freeze
(no kernel-side writer is scheduled), and the host
coordinator is the only writer of guest memory in scope.
read_u32 → OR mask → write_u32 therefore runs atomic
by quiesce: no concurrent kernel writer can interleave
between the load and the store. No compare_exchange loop
is required for cold-path dispatch.
At the host CPU level the read and write are separate
(non-instruction-atomic) operations: a hypothetical
concurrent host writer of guest memory would be a race.
The freeze coordinator is the sole such writer by design
(per the cold-path threat model documented at
super::Op::WriteKernelCold), so the parked-vCPU
contract is sufficient.
Alignment: the dispatcher delegates u32 reads/writes
to crate::monitor::guest::GuestKernel’s
read_*_u32 / write_*_u32 helpers, which use a
single-instruction write_volatile at 4-byte-aligned host
PAs and fall through to a per-byte volatile loop on
misalignment. Under the freeze rendezvous the per-byte
fallback is safe (no concurrent kernel writer), so
misaligned PAs do not produce a torn-RMW race —
but kernel ABI alignment for u32 fields is enforced by
the compiler at the kernel side regardless, so misaligned
PAs for legitimate symbol/field writes do not arise in
practice.
Hot-path future (when super::Op::WriteKernelHot
gains OrU32 support — currently rejected per the
super::Op::WriteKernelHot doc): the live-guest race
model requires a compare_exchange loop over
core::sync::atomic::AtomicU32::from_ptr (Rust 1.75+) at
4-byte alignment, with explicit rejection of misaligned
PAs (per-byte fallback cannot be made atomic vs. a live
kernel writer).
Ordering: cold-path dispatch happens while every vCPU
is parked at the freeze rendezvous, so no concurrent
guest write races our RMW for single-op use cases. The
SCX_RQ_CLK_VALID case specifically requires
write-clock-BEFORE-OR-flag ordering per the kernel’s
own scx_rq_clock_update at kernel/sched/sched.h:1848-1854
(which does WRITE_ONCE(rq->scx.clock, val) then
smp_store_release(&rq->scx.flags, flags | SCX_RQ_CLK_VALID)); a host-side caller that wants the
same observable invariant must batch the clock write +
the OR-flag in the same Op::WriteKernelCold batch and
rely on the freeze rendezvous’s vCPU-pause to serialise
against guest readers.
Implementations§
Source§impl KernelValue
impl KernelValue
Sourcepub const fn or_u32(mask: u32) -> Self
pub const fn or_u32(mask: u32) -> Self
32-bit unsigned read-modify-write OR mask. See
Self::OrU32 for the width-, atomicity-, and ordering-
contract. The canonical use case is OR-ing a single-bit
kernel flag like SCX_RQ_CLK_VALID into struct scx_rq.flags.
Trait Implementations§
Source§impl Clone for KernelValue
impl Clone for KernelValue
Source§fn clone(&self) -> KernelValue
fn clone(&self) -> KernelValue
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for KernelValue
impl Debug for KernelValue
Source§impl From<&KernelValue> for KernelOpValue
impl From<&KernelValue> for KernelOpValue
Source§fn from(value: &KernelValue) -> Self
fn from(value: &KernelValue) -> Self
1:1 mapping of every Op-side KernelValue variant to its
wire-side peer. The Bytes arm clones the inner Vec<u8>
so the source variant remains usable after dispatch (large
payloads pay the clone cost — see
crate::vmm::wire::KernelOpValue::Bytes for the wire
representation).
Source§impl PartialEq for KernelValue
impl PartialEq for KernelValue
impl Eq for KernelValue
impl StructuralPartialEq for KernelValue
Auto Trait Implementations§
impl Freeze for KernelValue
impl RefUnwindSafe for KernelValue
impl Send for KernelValue
impl Sync for KernelValue
impl Unpin for KernelValue
impl UnwindSafe for KernelValue
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more