KernelValue

Enum KernelValue 

Source
#[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
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

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::OrU32struct 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

Source

pub const fn u32(val: u32) -> Self

32-bit unsigned value.

Source

pub const fn u64(val: u64) -> Self

64-bit unsigned value.

Source

pub fn bytes(data: impl Into<Vec<u8>>) -> Self

Variable-length byte payload.

Source

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

Source§

fn clone(&self) -> KernelValue

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for KernelValue

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<&KernelValue> for KernelOpValue

Source§

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

Source§

fn eq(&self, other: &KernelValue) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for KernelValue

Source§

impl StructuralPartialEq for KernelValue

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> MaybeSend for T
where T: Send,

§

impl<T> MaybeSend for T
where T: Send,