vmbase: uart: Move asm block to crate::arch

Move the manual assembly into the vmbase::arch module so that the
vmbase::uart driver remains arch-agnostic, making it easier to port to
other CPU architectures.

Note that the manual assembly is preferred over using the standard
write_volatile() due to b/345658173 and [1] (see also aosp/3125955).

[1]: https://github.com/rust-lang/rust/issues/131894

Test: m pvmfw # Then check disassembly for STRB
Change-Id: I6d404df4c0439b8e208d1ef533b60434d2b2bec8
diff --git a/libs/libvmbase/src/arch.rs b/libs/libvmbase/src/arch.rs
index d8bb8b2..992ab27 100644
--- a/libs/libvmbase/src/arch.rs
+++ b/libs/libvmbase/src/arch.rs
@@ -91,3 +91,22 @@
         }
     }};
 }
+
+/// Write with well-defined compiled behavior.
+///
+/// See https://github.com/rust-lang/rust/issues/131894
+///
+/// # Safety
+///
+/// `dst` must be valid for writes.
+pub unsafe fn write_volatile_u8(dst: *mut u8, src: u8) {
+    // SAFETY: strb only modifies *dst, which must be valid for writes.
+    unsafe {
+        core::arch::asm!(
+            "strb {value:w}, [{ptr}]",
+            value = in(reg) src,
+            ptr = in(reg) dst,
+            options(preserves_flags),
+        );
+    }
+}
diff --git a/libs/libvmbase/src/uart.rs b/libs/libvmbase/src/uart.rs
index e35555d..427499b 100644
--- a/libs/libvmbase/src/uart.rs
+++ b/libs/libvmbase/src/uart.rs
@@ -15,6 +15,7 @@
 //! Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
 //! provided by crosvm, and won't work with real hardware.
 
+use crate::arch::write_volatile_u8;
 use core::fmt::{self, Write};
 
 /// Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
@@ -39,13 +40,7 @@
     pub fn write_byte(&self, byte: u8) {
         // SAFETY: We know that the base address points to the control registers of a UART device
         // which is appropriately mapped.
-        unsafe {
-            core::arch::asm!(
-                "strb {value:w}, [{ptr}]",
-                value = in(reg) byte,
-                ptr = in(reg) self.base_address,
-            );
-        }
+        unsafe { write_volatile_u8(self.base_address, byte) }
     }
 }