1use super::{GuestAlign, GuestPtr, GuestReadFail, GuestWriteFail};
2use crate::prelude::*;
3use crate::{enums::Endian, mem::*, GuestType, ARCH_ENDIAN};
4
5use std::alloc::Layout;
6
7macro_rules! impl_for_num {
8 ($($ty:ty),*) => {
9 $(
10 impl GuestType for $ty {
11 fn guest_layout() -> Option<Layout> {
12 Layout::from_size_align(
13 core::mem::size_of::<$ty>(),
14 <$ty as GuestAlign>::ALIGN
15 ).ok()
16 }
17
18 fn read_from_guest(cpu: &mut CPUState, ptr: target_ptr_t) -> Result<Self, GuestReadFail> {
19 let mut bytes = [0u8; core::mem::size_of::<$ty>()];
20 virtual_memory_read_into(cpu, ptr, &mut bytes).or(Err(GuestReadFail))?;
21
22 Ok(match ARCH_ENDIAN {
23 Endian::Big => <$ty>::from_be_bytes(bytes),
24 Endian::Little => <$ty>::from_le_bytes(bytes),
25 })
26 }
27
28 fn read_from_guest_phys(ptr: target_ptr_t) -> Result<Self, GuestReadFail> {
29 let mut bytes = [0u8; core::mem::size_of::<$ty>()];
30 physical_memory_read_into(ptr, &mut bytes).or(Err(GuestReadFail))?;
31
32 Ok(match ARCH_ENDIAN {
33 Endian::Big => <$ty>::from_be_bytes(bytes),
34 Endian::Little => <$ty>::from_le_bytes(bytes),
35 })
36 }
37
38 fn write_to_guest(&self, cpu: &mut CPUState, ptr: target_ptr_t) -> Result<(), GuestWriteFail> {
39 let bytes = match ARCH_ENDIAN {
40 Endian::Big => <$ty>::to_be_bytes(*self),
41 Endian::Little => <$ty>::to_le_bytes(*self),
42 };
43
44 virtual_memory_write(cpu, ptr, &bytes);
45
46 Ok(())
47 }
48
49 fn write_to_guest_phys(&self, ptr: target_ptr_t) -> Result<(), GuestWriteFail> {
50 let bytes = match ARCH_ENDIAN {
51 Endian::Big => <$ty>::to_be_bytes(*self),
52 Endian::Little => <$ty>::to_le_bytes(*self),
53 };
54
55 physical_memory_write(ptr, &bytes);
56
57 Ok(())
58 }
59 }
60 )*
61 };
62}
63
64impl_for_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);
65
66impl<T: GuestType> GuestType for GuestPtr<T> {
67 fn guest_layout() -> Option<Layout> {
68 target_ptr_t::guest_layout()
69 }
70
71 fn read_from_guest(cpu: &mut CPUState, ptr: target_ptr_t) -> Result<Self, GuestReadFail> {
72 target_ptr_t::read_from_guest(cpu, ptr).map(Self::from)
73 }
74
75 fn write_to_guest(&self, cpu: &mut CPUState, ptr: target_ptr_t) -> Result<(), GuestWriteFail> {
76 self.pointer.write_to_guest(cpu, ptr)
77 }
78
79 fn read_from_guest_phys(ptr: target_ptr_t) -> Result<Self, GuestReadFail> {
80 target_ptr_t::read_from_guest_phys(ptr).map(Self::from)
81 }
82
83 fn write_to_guest_phys(&self, ptr: target_ptr_t) -> Result<(), GuestWriteFail> {
84 self.pointer.write_to_guest_phys(ptr)
85 }
86}
87
88fn padding_needed_for(layout: &Layout, align: usize) -> usize {
89 let len = layout.size();
90
91 let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
92 len_rounded_up.wrapping_sub(len)
93}
94
95fn padded_size(layout: &Layout) -> usize {
96 layout.size() + padding_needed_for(&layout, layout.align())
97}
98
99fn repeat(layout: &Layout, n: usize) -> Layout {
100 let alloc_size = padded_size(layout)
101 .checked_mul(n)
102 .expect("Layout of guest array overflow");
103
104 Layout::from_size_align(alloc_size, layout.align()).expect("Layout of guest array invalid")
105}
106
107impl<T: GuestType, const N: usize> GuestType for [T; N] {
108 fn guest_layout() -> Option<Layout> {
109 T::guest_layout().map(|layout| repeat(&layout, N))
110 }
111
112 fn read_from_guest(cpu: &mut CPUState, ptr: target_ptr_t) -> Result<Self, GuestReadFail> {
113 let padded_size = padded_size(
114 &T::guest_layout().expect("Cannot read array of unsized types from guest."),
115 );
116
117 array_init::from_iter(
118 (ptr..)
119 .step_by(padded_size)
120 .take(N)
121 .filter_map(|ptr| T::read_from_guest(cpu, ptr).ok()),
122 )
123 .ok_or(GuestReadFail)
124 }
125
126 fn write_to_guest(&self, cpu: &mut CPUState, ptr: target_ptr_t) -> Result<(), GuestWriteFail> {
127 let padded_size = padded_size(
128 &T::guest_layout().expect("Cannot write array of unsized types to the guest."),
129 );
130
131 for (ptr, item) in (ptr..).step_by(padded_size).zip(self.iter()) {
132 item.write_to_guest(cpu, ptr)?;
133 }
134
135 Ok(())
136 }
137
138 fn read_from_guest_phys(ptr: target_ptr_t) -> Result<Self, GuestReadFail> {
139 let padded_size = padded_size(
140 &T::guest_layout().expect("Cannot read array of unsized types from guest."),
141 );
142
143 array_init::from_iter(
144 (ptr..)
145 .step_by(padded_size)
146 .take(N)
147 .filter_map(|ptr| T::read_from_guest_phys(ptr).ok()),
148 )
149 .ok_or(GuestReadFail)
150 }
151
152 fn write_to_guest_phys(&self, ptr: target_ptr_t) -> Result<(), GuestWriteFail> {
153 let padded_size = padded_size(
154 &T::guest_layout().expect("Cannot write array of unsized types to the guest."),
155 );
156
157 for (ptr, item) in (ptr..).step_by(padded_size).zip(self.iter()) {
158 item.write_to_guest_phys(ptr)?;
159 }
160
161 Ok(())
162 }
163}