vmbase: Move Trng internals to arch::aarch64

This commit moves trng implementation from common rand module to a
aarch64 arch module. This is at the moment purely cosmetic change,
however the purpose is move all aarch64 specific code away from common
modules to enable bringup of x86_64 support.

Bug: 362733888
Test: m pvmfw
Test: pVM boots with pvmfw
Change-Id: I5ac315ed38491de8b66f07a5df703cb50786c8bb
diff --git a/libs/libvmbase/src/arch.rs b/libs/libvmbase/src/arch.rs
index 49978d5..cc42939 100644
--- a/libs/libvmbase/src/arch.rs
+++ b/libs/libvmbase/src/arch.rs
@@ -30,6 +30,9 @@
 pub use aarch64::dbm;
 
 #[cfg(target_arch = "aarch64")]
+pub use aarch64::rand;
+
+#[cfg(target_arch = "aarch64")]
 pub use aarch64::uart;
 
 #[cfg(target_arch = "aarch64")]
diff --git a/libs/libvmbase/src/arch/aarch64.rs b/libs/libvmbase/src/arch/aarch64.rs
index 05b5566..9c4d256 100644
--- a/libs/libvmbase/src/arch/aarch64.rs
+++ b/libs/libvmbase/src/arch/aarch64.rs
@@ -21,6 +21,7 @@
 pub mod linker;
 pub mod page_table;
 pub mod platform;
+pub mod rand;
 pub mod uart;
 
 /// Reads a value from a system register.
diff --git a/libs/libvmbase/src/arch/aarch64/rand.rs b/libs/libvmbase/src/arch/aarch64/rand.rs
new file mode 100644
index 0000000..4fd1905
--- /dev/null
+++ b/libs/libvmbase/src/arch/aarch64/rand.rs
@@ -0,0 +1,131 @@
+// Copyright 2025, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Random number generator implementation for aarch64 platforms using TRNG
+
+use crate::arch::aarch64::hvc;
+use crate::rand::{Entropy, Error, Result};
+use core::fmt;
+use core::mem::size_of;
+use smccc::{self, Hvc};
+use zerocopy::IntoBytes as _;
+
+/// Error type for rand operations.
+pub enum PlatformError {
+    /// Error during architectural SMCCC call.
+    Smccc(smccc::arch::Error),
+    /// Error during SMCCC TRNG call.
+    Trng(hvc::trng::Error),
+    /// Unsupported SMCCC version.
+    UnsupportedSmcccVersion(smccc::arch::Version),
+    /// Unsupported SMCCC TRNG version.
+    UnsupportedTrngVersion(hvc::trng::Version),
+}
+
+impl From<smccc::arch::Error> for Error {
+    fn from(e: smccc::arch::Error) -> Self {
+        Self::Platform(PlatformError::Smccc(e))
+    }
+}
+
+impl From<hvc::trng::Error> for Error {
+    fn from(e: hvc::trng::Error) -> Self {
+        Self::Platform(PlatformError::Trng(e))
+    }
+}
+
+impl fmt::Display for PlatformError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Self::Smccc(e) => write!(f, "Architectural SMCCC error: {e}"),
+            Self::Trng(e) => write!(f, "SMCCC TRNG error: {e}"),
+            Self::UnsupportedSmcccVersion(v) => write!(f, "Unsupported SMCCC version {v}"),
+            Self::UnsupportedTrngVersion(v) => write!(f, "Unsupported SMCCC TRNG version {v}"),
+        }
+    }
+}
+
+impl fmt::Debug for PlatformError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{self}")
+    }
+}
+
+pub(crate) const MAX_BYTES_PER_CALL: usize = size_of::<u64>() * 3;
+
+/// Configure the source of entropy.
+pub(crate) fn init() -> Result<()> {
+    // SMCCC TRNG requires SMCCC v1.1.
+    match smccc::arch::version::<Hvc>()? {
+        smccc::arch::Version { major: 1, minor } if minor >= 1 => (),
+        version => return Err(PlatformError::UnsupportedSmcccVersion(version).into()),
+    }
+
+    // TRNG_RND requires SMCCC TRNG v1.0.
+    match hvc::trng_version()? {
+        hvc::trng::Version { major: 1, minor: _ } => (),
+        version => return Err(PlatformError::UnsupportedTrngVersion(version).into()),
+    }
+
+    // TRNG_RND64 doesn't define any special capabilities so ignore the successful result.
+    let _ = hvc::trng_features(hvc::ARM_SMCCC_TRNG_RND64).map_err(|e| {
+        if e == hvc::trng::Error::NotSupported {
+            // SMCCC TRNG is currently our only source of entropy.
+            Error::NoEntropySource
+        } else {
+            e.into()
+        }
+    })?;
+
+    Ok(())
+}
+
+/// Returns an array where the first `n_bytes` bytes hold entropy.
+///
+/// The rest of the array should be ignored.
+pub(crate) fn platform_entropy(n_bytes: usize) -> Result<Entropy> {
+    loop {
+        if let Some(entropy) = rnd64(n_bytes)? {
+            return Ok(entropy);
+        }
+    }
+}
+
+/// Returns an array where the first `n_bytes` bytes hold entropy, if available.
+///
+/// The rest of the array should be ignored.
+fn rnd64(n_bytes: usize) -> Result<Option<Entropy>> {
+    let bits = usize::try_from(u8::BITS).unwrap();
+    let result = hvc::trng_rnd64((n_bytes * bits).try_into().unwrap());
+    let entropy = if matches!(result, Err(hvc::trng::Error::NoEntropy)) {
+        None
+    } else {
+        let r = result?;
+        // From the SMCCC TRNG:
+        //
+        //     A MAX_BITS-bits wide value (Entropy) is returned across X1 to X3.
+        //     The requested conditioned entropy is returned in Entropy[N-1:0].
+        //
+        //             X1     Entropy[191:128]
+        //             X2     Entropy[127:64]
+        //             X3     Entropy[63:0]
+        //
+        //     The bits in Entropy[MAX_BITS-1:N] are 0.
+        let reordered = [r[2].to_le(), r[1].to_le(), r[0].to_le()];
+
+        Some(reordered.as_bytes().try_into().unwrap())
+    };
+
+    Ok(entropy)
+}
diff --git a/libs/libvmbase/src/entry.rs b/libs/libvmbase/src/entry.rs
index 5db0f25..5c74753 100644
--- a/libs/libvmbase/src/entry.rs
+++ b/libs/libvmbase/src/entry.rs
@@ -38,7 +38,7 @@
     // We keep a null byte at the top of the stack guard to act as a string terminator.
     let random_guard = &mut stack_guard[..(SIZE_OF_STACK_GUARD - 1)];
 
-    if let Err(e) = rand::init() {
+    if let Err(e) = crate::arch::rand::init() {
         panic!("Failed to initialize a source of entropy: {e}");
     }
 
diff --git a/libs/libvmbase/src/rand.rs b/libs/libvmbase/src/rand.rs
index e4623b7..e4b8c63 100644
--- a/libs/libvmbase/src/rand.rs
+++ b/libs/libvmbase/src/rand.rs
@@ -14,37 +14,23 @@
 
 //! Functions and drivers for obtaining true entropy.
 
-use crate::arch::aarch64::hvc;
+use crate::arch::rand::{platform_entropy, PlatformError, MAX_BYTES_PER_CALL};
 use core::fmt;
-use core::mem::size_of;
-use smccc::{self, Hvc};
-use zerocopy::IntoBytes as _;
 
-type Entropy = [u8; size_of::<u64>() * 3];
+pub(crate) type Entropy = [u8; MAX_BYTES_PER_CALL];
 
 /// Error type for rand operations.
 pub enum Error {
     /// No source of entropy found.
     NoEntropySource,
-    /// Error during architectural SMCCC call.
-    Smccc(smccc::arch::Error),
-    /// Error during SMCCC TRNG call.
-    Trng(hvc::trng::Error),
-    /// Unsupported SMCCC version.
-    UnsupportedSmcccVersion(smccc::arch::Version),
-    /// Unsupported SMCCC TRNG version.
-    UnsupportedTrngVersion(hvc::trng::Version),
+
+    /// Platform specific error
+    Platform(PlatformError),
 }
 
-impl From<smccc::arch::Error> for Error {
-    fn from(e: smccc::arch::Error) -> Self {
-        Self::Smccc(e)
-    }
-}
-
-impl From<hvc::trng::Error> for Error {
-    fn from(e: hvc::trng::Error) -> Self {
-        Self::Trng(e)
+impl From<PlatformError> for Error {
+    fn from(e: PlatformError) -> Self {
+        Error::Platform(e)
     }
 }
 
@@ -55,10 +41,7 @@
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Self::NoEntropySource => write!(f, "No source of entropy available"),
-            Self::Smccc(e) => write!(f, "Architectural SMCCC error: {e}"),
-            Self::Trng(e) => write!(f, "SMCCC TRNG error: {e}"),
-            Self::UnsupportedSmcccVersion(v) => write!(f, "Unsupported SMCCC version {v}"),
-            Self::UnsupportedTrngVersion(v) => write!(f, "Unsupported SMCCC TRNG version {v}"),
+            Self::Platform(e) => write!(f, "Platform error: {e}"),
         }
     }
 }
@@ -69,84 +52,16 @@
     }
 }
 
-/// Configure the source of entropy.
-pub(crate) fn init() -> Result<()> {
-    // SMCCC TRNG requires SMCCC v1.1.
-    match smccc::arch::version::<Hvc>()? {
-        smccc::arch::Version { major: 1, minor } if minor >= 1 => (),
-        version => return Err(Error::UnsupportedSmcccVersion(version)),
-    }
-
-    // TRNG_RND requires SMCCC TRNG v1.0.
-    match hvc::trng_version()? {
-        hvc::trng::Version { major: 1, minor: _ } => (),
-        version => return Err(Error::UnsupportedTrngVersion(version)),
-    }
-
-    // TRNG_RND64 doesn't define any special capabilities so ignore the successful result.
-    let _ = hvc::trng_features(hvc::ARM_SMCCC_TRNG_RND64).map_err(|e| {
-        if e == hvc::trng::Error::NotSupported {
-            // SMCCC TRNG is currently our only source of entropy.
-            Error::NoEntropySource
-        } else {
-            e.into()
-        }
-    })?;
-
-    Ok(())
-}
-
 /// Fills a slice of bytes with true entropy.
 pub fn fill_with_entropy(s: &mut [u8]) -> Result<()> {
-    const MAX_BYTES_PER_CALL: usize = size_of::<Entropy>();
-
     for chunk in s.chunks_mut(MAX_BYTES_PER_CALL) {
-        let entropy = repeat_trng_rnd(chunk.len())?;
+        let entropy = platform_entropy(chunk.len())?;
         chunk.clone_from_slice(&entropy[..chunk.len()]);
     }
 
     Ok(())
 }
 
-/// Returns an array where the first `n_bytes` bytes hold entropy.
-///
-/// The rest of the array should be ignored.
-fn repeat_trng_rnd(n_bytes: usize) -> Result<Entropy> {
-    loop {
-        if let Some(entropy) = rnd64(n_bytes)? {
-            return Ok(entropy);
-        }
-    }
-}
-
-/// Returns an array where the first `n_bytes` bytes hold entropy, if available.
-///
-/// The rest of the array should be ignored.
-fn rnd64(n_bytes: usize) -> Result<Option<Entropy>> {
-    let bits = usize::try_from(u8::BITS).unwrap();
-    let result = hvc::trng_rnd64((n_bytes * bits).try_into().unwrap());
-    let entropy = if matches!(result, Err(hvc::trng::Error::NoEntropy)) {
-        None
-    } else {
-        let r = result?;
-        // From the SMCCC TRNG:
-        //
-        //     A MAX_BITS-bits wide value (Entropy) is returned across X1 to X3.
-        //     The requested conditioned entropy is returned in Entropy[N-1:0].
-        //
-        //             X1     Entropy[191:128]
-        //             X2     Entropy[127:64]
-        //             X3     Entropy[63:0]
-        //
-        //     The bits in Entropy[MAX_BITS-1:N] are 0.
-        let reordered = [r[2].to_le(), r[1].to_le(), r[0].to_le()];
-
-        Some(reordered.as_bytes().try_into().unwrap())
-    };
-
-    Ok(entropy)
-}
-
 /// Generate an array of fixed-size initialized with true-random bytes.
 pub fn random_array<const N: usize>() -> Result<[u8; N]> {
     let mut arr = [0; N];