diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-06-11 23:14:04 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-06-11 23:14:04 +0000 |
commit | df748b6fb99607e4efede023d477f325f300d557 (patch) | |
tree | 99bfd8028072b55eb00c53b2ecb1196a770ab441 | |
parent | 1e156af2fd18080b53d748d706d0050a4544dbf6 (diff) | |
parent | 37a3fb637b6c5b296d843e1c96e7918a96ae9fd0 (diff) | |
download | virtio-drivers-sdk-release.tar.gz |
Snap for 11955768 from 37a3fb637b6c5b296d843e1c96e7918a96ae9fd0 to sdk-releasesdk-release
Change-Id: I159dc92fdbb314b6972280914f68b3f2c8656169
-rw-r--r-- | patches/Android.bp.patch | 27 | ||||
-rw-r--r-- | patches/mmio.patch | 231 | ||||
-rw-r--r-- | src/device/net.rs | 2 | ||||
-rw-r--r-- | src/transport/pci/bus.rs | 14 | ||||
-rw-r--r-- | src/volatile.rs | 157 |
5 files changed, 426 insertions, 5 deletions
diff --git a/patches/Android.bp.patch b/patches/Android.bp.patch index 2a063c6..d2c3c5b 100644 --- a/patches/Android.bp.patch +++ b/patches/Android.bp.patch @@ -1,8 +1,15 @@ diff --git a/Android.bp b/Android.bp -index e2b5dd5..6132b98 100644 +index 81021c8..916b74c 100644 --- a/Android.bp +++ b/Android.bp -@@ -30,8 +30,8 @@ rust_library_rlib { +@@ -25,22 +25,22 @@ license { + rust_library_rlib { + name: "libvirtio_drivers", + crate_name: "virtio_drivers", + cargo_env_compat: true, + cargo_pkg_version: "0.7.1", + crate_root: "src/lib.rs", + edition: "2018", features: ["alloc"], rustlibs: [ "libbitflags", @@ -13,7 +20,21 @@ index e2b5dd5..6132b98 100644 ], apex_available: [ "//apex_available:platform", -@@ -58,6 +58,6 @@ rust_test { + "//apex_available:anyapex", + ], + prefer_rlib: true, + no_stdlibs: true, + stdlibs: [ + "libcompiler_builtins.rust_sysroot", + "libcore.rust_sysroot", +@@ -53,13 +53,13 @@ rust_test { + cargo_env_compat: true, + cargo_pkg_version: "0.7.1", + crate_root: "src/lib.rs", + test_suites: ["general-tests"], + auto_gen_config: true, + edition: "2018", + features: ["alloc"], rustlibs: [ "libbitflags", "liblog_rust", diff --git a/patches/mmio.patch b/patches/mmio.patch new file mode 100644 index 0000000..8e684f6 --- /dev/null +++ b/patches/mmio.patch @@ -0,0 +1,231 @@ +diff --git a/src/device/net.rs b/src/device/net.rs +index b32cd72..c7732a4 100644 +--- a/src/device/net.rs ++++ b/src/device/net.rs +@@ -340,7 +340,7 @@ bitflags! { + + bitflags! { + #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +- struct Status: u16 { ++ pub(crate) struct Status: u16 { + const LINK_UP = 1; + const ANNOUNCE = 2; + } +diff --git a/src/transport/pci/bus.rs b/src/transport/pci/bus.rs +index 0a3014b..52f861e 100644 +--- a/src/transport/pci/bus.rs ++++ b/src/transport/pci/bus.rs +@@ -202,7 +202,19 @@ impl PciRoot { + // resulting pointer is within the MMIO range of the CAM. + unsafe { + // Right shift to convert from byte offset to word offset. +- (self.mmio_base.add((address >> 2) as usize)).write_volatile(data) ++ let ptr = self.mmio_base.add((address >> 2) as usize); ++ #[cfg(not(target_arch = "aarch64"))] ++ { ++ ptr.write_volatile(data) ++ } ++ #[cfg(target_arch = "aarch64")] ++ { ++ core::arch::asm!( ++ "str {value:w}, [{ptr}]", ++ value = in(reg) data, ++ ptr = in(reg) ptr, ++ ) ++ } + } + } + +diff --git a/src/volatile.rs b/src/volatile.rs +index b7059d1..af7ef27 100644 +--- a/src/volatile.rs ++++ b/src/volatile.rs +@@ -33,12 +33,14 @@ pub trait VolatileReadable<T> { + unsafe fn vread(self) -> T; + } + ++#[cfg(not(target_arch = "aarch64"))] + impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> { + unsafe fn vread(self) -> T { + self.read_volatile().0 + } + } + ++#[cfg(not(target_arch = "aarch64"))] + impl<T: Copy> VolatileReadable<T> for *const Volatile<T> { + unsafe fn vread(self) -> T { + self.read_volatile().0 +@@ -51,18 +53,173 @@ pub trait VolatileWritable<T> { + unsafe fn vwrite(self, value: T); + } + ++#[cfg(not(target_arch = "aarch64"))] + impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> { + unsafe fn vwrite(self, value: T) { + (self as *mut T).write_volatile(value) + } + } + ++#[cfg(not(target_arch = "aarch64"))] + impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> { + unsafe fn vwrite(self, value: T) { + (self as *mut T).write_volatile(value) + } + } + ++#[cfg(target_arch = "aarch64")] ++mod aarch64_mmio { ++ use super::{ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly}; ++ use crate::{device::net::Status, transport::DeviceStatus}; ++ use core::arch::asm; ++ ++ macro_rules! asm_mmio_write { ++ ($t:ty, $assembly:literal) => { ++ impl VolatileWritable<$t> for *mut WriteOnly<$t> { ++ unsafe fn vwrite(self, value: $t) { ++ asm!( ++ $assembly, ++ value = in(reg) value, ++ ptr = in(reg) (self as *mut $t), ++ ); ++ } ++ } ++ ++ impl VolatileWritable<$t> for *mut Volatile<$t> { ++ unsafe fn vwrite(self, value: $t) { ++ asm!( ++ $assembly, ++ value = in(reg) value, ++ ptr = in(reg) (self as *mut $t), ++ ); ++ } ++ } ++ }; ++ } ++ ++ macro_rules! asm_mmio_read { ++ ($t:ty, $assembly:literal) => { ++ impl VolatileReadable<$t> for *const ReadOnly<$t> { ++ unsafe fn vread(self) -> $t { ++ let value; ++ asm!( ++ $assembly, ++ value = out(reg) value, ++ ptr = in(reg) (self as *const $t), ++ ); ++ value ++ } ++ } ++ ++ impl VolatileReadable<$t> for *const Volatile<$t> { ++ unsafe fn vread(self) -> $t { ++ let value; ++ asm!( ++ $assembly, ++ value = out(reg) value, ++ ptr = in(reg) (self as *const $t), ++ ); ++ value ++ } ++ } ++ }; ++ } ++ ++ asm_mmio_write!(u8, "strb {value:w}, [{ptr}]"); ++ asm_mmio_write!(u16, "strh {value:w}, [{ptr}]"); ++ asm_mmio_write!(u32, "str {value:w}, [{ptr}]"); ++ asm_mmio_write!(u64, "str {value:x}, [{ptr}]"); ++ ++ impl VolatileWritable<DeviceStatus> for *mut WriteOnly<DeviceStatus> { ++ unsafe fn vwrite(self, value: DeviceStatus) { ++ let value: u32 = value.bits(); ++ asm!( ++ "str {value:w}, [{ptr}]", ++ value = in(reg) value, ++ ptr = in(reg) (self as *mut u32), ++ ); ++ } ++ } ++ ++ impl VolatileWritable<DeviceStatus> for *mut Volatile<DeviceStatus> { ++ unsafe fn vwrite(self, value: DeviceStatus) { ++ let value: u32 = value.bits(); ++ asm!( ++ "str {value:w}, [{ptr}]", ++ value = in(reg) value, ++ ptr = in(reg) (self as *mut u32), ++ ); ++ } ++ } ++ ++ asm_mmio_read!(u8, "ldrb {value:w}, [{ptr}]"); ++ asm_mmio_read!(u16, "ldrh {value:w}, [{ptr}]"); ++ asm_mmio_read!(u32, "ldr {value:w}, [{ptr}]"); ++ asm_mmio_read!(u64, "ldr {value:x}, [{ptr}]"); ++ ++ impl VolatileReadable<DeviceStatus> for *const ReadOnly<DeviceStatus> { ++ unsafe fn vread(self) -> DeviceStatus { ++ let value: u32; ++ asm!( ++ "ldr {value:w}, [{ptr}]", ++ value = out(reg) value, ++ ptr = in(reg) (self as *const u32), ++ ); ++ DeviceStatus::from_bits_retain(value) ++ } ++ } ++ ++ impl VolatileReadable<DeviceStatus> for *const Volatile<DeviceStatus> { ++ unsafe fn vread(self) -> DeviceStatus { ++ let value: u32; ++ asm!( ++ "ldr {value:w}, [{ptr}]", ++ value = out(reg) value, ++ ptr = in(reg) (self as *const u32), ++ ); ++ DeviceStatus::from_bits_retain(value) ++ } ++ } ++ ++ impl VolatileReadable<Status> for *const ReadOnly<Status> { ++ unsafe fn vread(self) -> Status { ++ let value: u16; ++ asm!( ++ "ldrh {value:w}, [{ptr}]", ++ value = out(reg) value, ++ ptr = in(reg) (self as *const u16), ++ ); ++ Status::from_bits_retain(value) ++ } ++ } ++ ++ impl VolatileReadable<Status> for *const Volatile<Status> { ++ unsafe fn vread(self) -> Status { ++ let value: u16; ++ asm!( ++ "ldrh {value:w}, [{ptr}]", ++ value = out(reg) value, ++ ptr = in(reg) (self as *const u16), ++ ); ++ Status::from_bits_retain(value) ++ } ++ } ++ ++ impl<const SIZE: usize> VolatileReadable<[u8; SIZE]> for *const ReadOnly<[u8; SIZE]> { ++ unsafe fn vread(self) -> [u8; SIZE] { ++ let mut value = [0; SIZE]; ++ for i in 0..SIZE { ++ asm!( ++ "ldrb {value:w}, [{ptr}]", ++ value = out(reg) value[i], ++ ptr = in(reg) (self as *const u8), ++ ); ++ } ++ value ++ } ++ } ++} ++ + /// Performs a volatile read from the given field of pointer to a struct representing an MMIO region. + /// + /// # Usage diff --git a/src/device/net.rs b/src/device/net.rs index b32cd72..c7732a4 100644 --- a/src/device/net.rs +++ b/src/device/net.rs @@ -340,7 +340,7 @@ bitflags! { bitflags! { #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] - struct Status: u16 { + pub(crate) struct Status: u16 { const LINK_UP = 1; const ANNOUNCE = 2; } diff --git a/src/transport/pci/bus.rs b/src/transport/pci/bus.rs index 0a3014b..52f861e 100644 --- a/src/transport/pci/bus.rs +++ b/src/transport/pci/bus.rs @@ -202,7 +202,19 @@ impl PciRoot { // resulting pointer is within the MMIO range of the CAM. unsafe { // Right shift to convert from byte offset to word offset. - (self.mmio_base.add((address >> 2) as usize)).write_volatile(data) + let ptr = self.mmio_base.add((address >> 2) as usize); + #[cfg(not(target_arch = "aarch64"))] + { + ptr.write_volatile(data) + } + #[cfg(target_arch = "aarch64")] + { + core::arch::asm!( + "str {value:w}, [{ptr}]", + value = in(reg) data, + ptr = in(reg) ptr, + ) + } } } diff --git a/src/volatile.rs b/src/volatile.rs index b7059d1..af7ef27 100644 --- a/src/volatile.rs +++ b/src/volatile.rs @@ -33,12 +33,14 @@ pub trait VolatileReadable<T> { unsafe fn vread(self) -> T; } +#[cfg(not(target_arch = "aarch64"))] impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> { unsafe fn vread(self) -> T { self.read_volatile().0 } } +#[cfg(not(target_arch = "aarch64"))] impl<T: Copy> VolatileReadable<T> for *const Volatile<T> { unsafe fn vread(self) -> T { self.read_volatile().0 @@ -51,18 +53,173 @@ pub trait VolatileWritable<T> { unsafe fn vwrite(self, value: T); } +#[cfg(not(target_arch = "aarch64"))] impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> { unsafe fn vwrite(self, value: T) { (self as *mut T).write_volatile(value) } } +#[cfg(not(target_arch = "aarch64"))] impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> { unsafe fn vwrite(self, value: T) { (self as *mut T).write_volatile(value) } } +#[cfg(target_arch = "aarch64")] +mod aarch64_mmio { + use super::{ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly}; + use crate::{device::net::Status, transport::DeviceStatus}; + use core::arch::asm; + + macro_rules! asm_mmio_write { + ($t:ty, $assembly:literal) => { + impl VolatileWritable<$t> for *mut WriteOnly<$t> { + unsafe fn vwrite(self, value: $t) { + asm!( + $assembly, + value = in(reg) value, + ptr = in(reg) (self as *mut $t), + ); + } + } + + impl VolatileWritable<$t> for *mut Volatile<$t> { + unsafe fn vwrite(self, value: $t) { + asm!( + $assembly, + value = in(reg) value, + ptr = in(reg) (self as *mut $t), + ); + } + } + }; + } + + macro_rules! asm_mmio_read { + ($t:ty, $assembly:literal) => { + impl VolatileReadable<$t> for *const ReadOnly<$t> { + unsafe fn vread(self) -> $t { + let value; + asm!( + $assembly, + value = out(reg) value, + ptr = in(reg) (self as *const $t), + ); + value + } + } + + impl VolatileReadable<$t> for *const Volatile<$t> { + unsafe fn vread(self) -> $t { + let value; + asm!( + $assembly, + value = out(reg) value, + ptr = in(reg) (self as *const $t), + ); + value + } + } + }; + } + + asm_mmio_write!(u8, "strb {value:w}, [{ptr}]"); + asm_mmio_write!(u16, "strh {value:w}, [{ptr}]"); + asm_mmio_write!(u32, "str {value:w}, [{ptr}]"); + asm_mmio_write!(u64, "str {value:x}, [{ptr}]"); + + impl VolatileWritable<DeviceStatus> for *mut WriteOnly<DeviceStatus> { + unsafe fn vwrite(self, value: DeviceStatus) { + let value: u32 = value.bits(); + asm!( + "str {value:w}, [{ptr}]", + value = in(reg) value, + ptr = in(reg) (self as *mut u32), + ); + } + } + + impl VolatileWritable<DeviceStatus> for *mut Volatile<DeviceStatus> { + unsafe fn vwrite(self, value: DeviceStatus) { + let value: u32 = value.bits(); + asm!( + "str {value:w}, [{ptr}]", + value = in(reg) value, + ptr = in(reg) (self as *mut u32), + ); + } + } + + asm_mmio_read!(u8, "ldrb {value:w}, [{ptr}]"); + asm_mmio_read!(u16, "ldrh {value:w}, [{ptr}]"); + asm_mmio_read!(u32, "ldr {value:w}, [{ptr}]"); + asm_mmio_read!(u64, "ldr {value:x}, [{ptr}]"); + + impl VolatileReadable<DeviceStatus> for *const ReadOnly<DeviceStatus> { + unsafe fn vread(self) -> DeviceStatus { + let value: u32; + asm!( + "ldr {value:w}, [{ptr}]", + value = out(reg) value, + ptr = in(reg) (self as *const u32), + ); + DeviceStatus::from_bits_retain(value) + } + } + + impl VolatileReadable<DeviceStatus> for *const Volatile<DeviceStatus> { + unsafe fn vread(self) -> DeviceStatus { + let value: u32; + asm!( + "ldr {value:w}, [{ptr}]", + value = out(reg) value, + ptr = in(reg) (self as *const u32), + ); + DeviceStatus::from_bits_retain(value) + } + } + + impl VolatileReadable<Status> for *const ReadOnly<Status> { + unsafe fn vread(self) -> Status { + let value: u16; + asm!( + "ldrh {value:w}, [{ptr}]", + value = out(reg) value, + ptr = in(reg) (self as *const u16), + ); + Status::from_bits_retain(value) + } + } + + impl VolatileReadable<Status> for *const Volatile<Status> { + unsafe fn vread(self) -> Status { + let value: u16; + asm!( + "ldrh {value:w}, [{ptr}]", + value = out(reg) value, + ptr = in(reg) (self as *const u16), + ); + Status::from_bits_retain(value) + } + } + + impl<const SIZE: usize> VolatileReadable<[u8; SIZE]> for *const ReadOnly<[u8; SIZE]> { + unsafe fn vread(self) -> [u8; SIZE] { + let mut value = [0; SIZE]; + for i in 0..SIZE { + asm!( + "ldrb {value:w}, [{ptr}]", + value = out(reg) value[i], + ptr = in(reg) (self as *const u8), + ); + } + value + } + } +} + /// Performs a volatile read from the given field of pointer to a struct representing an MMIO region. /// /// # Usage |