Skip to content

Commit e697c0f

Browse files
committed
Fix alignment issues
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent afd8964 commit e697c0f

File tree

2 files changed

+65
-21
lines changed

2 files changed

+65
-21
lines changed

src/hyperlight_host/src/hypervisor/regs/special_regs.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ extern crate mshv_ioctls3 as mshv_ioctls;
1010

1111
#[cfg(target_os = "windows")]
1212
use std::collections::HashSet;
13+
#[cfg(target_os = "windows")]
14+
use std::mem::offset_of;
1315

1416
#[cfg(kvm)]
1517
use kvm_bindings::{kvm_dtable, kvm_segment, kvm_sregs};
@@ -20,6 +22,8 @@ use windows::Win32::System::Hypervisor::*;
2022

2123
#[cfg(target_os = "windows")]
2224
use super::FromWhpRegisterError;
25+
#[cfg(target_os = "windows")]
26+
use crate::hypervisor::regs::{WHP_FPU_NAMES_LEN, WHP_REGS_NAMES_LEN};
2327

2428
#[derive(Debug, Default, Copy, Clone, PartialEq)]
2529
pub(crate) struct CommonSpecialRegisters {
@@ -147,6 +151,23 @@ impl From<&CommonSpecialRegisters> for kvm_sregs {
147151
}
148152
}
149153

154+
#[repr(C, align(16))]
155+
#[cfg(target_os = "windows")]
156+
pub(crate) struct AlignedRegisterValues<const N: usize>(pub(crate) [WHV_REGISTER_VALUE; N]);
157+
158+
#[cfg(target_os = "windows")]
159+
const _: () = {
160+
// WHP_SREGS_NAMES_LEN
161+
assert!(std::mem::align_of::<AlignedRegisterValues<WHP_SREGS_NAMES_LEN>>() % 16 == 0);
162+
assert!(offset_of!(AlignedRegisterValues<WHP_SREGS_NAMES_LEN>, 0) % 16 == 0);
163+
// WHP_REGS_NAMES_LEN
164+
assert!(std::mem::align_of::<AlignedRegisterValues<WHP_REGS_NAMES_LEN>>() % 16 == 0,);
165+
assert!(offset_of!(AlignedRegisterValues<WHP_REGS_NAMES_LEN>, 0) % 16 == 0);
166+
// WHP_FPU_NAMES_LEN
167+
assert!(std::mem::align_of::<AlignedRegisterValues<WHP_FPU_NAMES_LEN>>() % 16 == 0,);
168+
assert!(offset_of!(AlignedRegisterValues<WHP_FPU_NAMES_LEN>, 0) % 16 == 0);
169+
};
170+
150171
#[cfg(target_os = "windows")]
151172
pub(crate) const WHP_SREGS_NAMES_LEN: usize = 17;
152173
#[cfg(target_os = "windows")]

src/hyperlight_host/src/hypervisor/whp.rs

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use windows_result::HRESULT;
2626
#[cfg(gdb)]
2727
use super::handlers::DbgMemAccessHandlerWrapper;
2828
use super::regs::{
29-
WHP_FPU_NAMES, WHP_FPU_NAMES_LEN, WHP_REGS_NAMES, WHP_REGS_NAMES_LEN, WHP_SREGS_NAMES,
30-
WHP_SREGS_NAMES_LEN,
29+
AlignedRegisterValues, WHP_FPU_NAMES, WHP_FPU_NAMES_LEN, WHP_REGS_NAMES, WHP_REGS_NAMES_LEN,
30+
WHP_SREGS_NAMES, WHP_SREGS_NAMES_LEN,
3131
};
3232
use super::vm::HyperlightExit;
3333
use super::wrappers::HandleWrapper;
@@ -86,6 +86,15 @@ pub(crate) struct WhpVm {
8686
unsafe impl Send for WhpVm {}
8787
unsafe impl Sync for WhpVm {}
8888

89+
#[repr(C, align(16))]
90+
struct Align16<T>(T);
91+
const _: () = {
92+
assert!(
93+
std::mem::size_of::<Align16<WHV_REGISTER_VALUE>>()
94+
== std::mem::size_of::<WHV_REGISTER_VALUE>()
95+
);
96+
};
97+
8998
impl WhpVm {
9099
pub(crate) fn new(mmap_file_handle: HandleWrapper) -> Result<Self> {
91100
const NUM_CPU: u32 = 1;
@@ -112,21 +121,29 @@ impl WhpVm {
112121
/// Helper for setting arbitrary registers.
113122
fn set_registers(&self, registers: &[(WHV_REGISTER_NAME, WHV_REGISTER_VALUE)]) -> Result<()> {
114123
let register_count = registers.len();
115-
let mut register_names: Vec<WHV_REGISTER_NAME> = vec![];
116-
let mut register_values: Vec<WHV_REGISTER_VALUE> = vec![];
124+
125+
// Prepare register names (no special alignment needed)
126+
let mut register_names = Vec::with_capacity(register_count);
127+
let mut register_values = Vec::with_capacity(register_count);
117128

118129
for (key, value) in registers.iter() {
119130
register_names.push(*key);
120-
register_values.push(*value);
131+
register_values.push(Align16(*value));
121132
}
122133

134+
assert_eq!(
135+
(register_values.as_ptr() as usize) % 16,
136+
0,
137+
"register_values is not 16-byte aligned"
138+
);
139+
123140
unsafe {
124141
WHvSetVirtualProcessorRegisters(
125142
self.partition,
126143
0,
127144
register_names.as_ptr(),
128145
register_count as u32,
129-
register_values.as_ptr(),
146+
register_values.as_ptr() as *const WHV_REGISTER_VALUE,
130147
)?;
131148
}
132149

@@ -136,22 +153,24 @@ impl WhpVm {
136153

137154
impl Vm for WhpVm {
138155
fn get_regs(&self) -> Result<CommonRegisters> {
139-
let mut whv_regs_values: [WHV_REGISTER_VALUE; WHP_REGS_NAMES_LEN] =
140-
unsafe { std::mem::zeroed() };
156+
let mut whv_regs_values =
157+
AlignedRegisterValues::<WHP_REGS_NAMES_LEN>(unsafe { std::mem::zeroed() });
158+
159+
assert_eq!((whv_regs_values.0.as_ptr() as usize) % 16, 0);
141160

142161
unsafe {
143162
WHvGetVirtualProcessorRegisters(
144163
self.partition,
145164
0,
146165
WHP_REGS_NAMES.as_ptr(),
147-
WHP_REGS_NAMES_LEN as u32,
148-
whv_regs_values.as_mut_ptr(),
166+
whv_regs_values.0.len() as u32,
167+
whv_regs_values.0.as_mut_ptr(),
149168
)?;
150169
}
151170

152171
WHP_REGS_NAMES
153172
.into_iter()
154-
.zip(whv_regs_values)
173+
.zip(whv_regs_values.0)
155174
.collect::<Vec<(WHV_REGISTER_NAME, WHV_REGISTER_VALUE)>>()
156175
.as_slice()
157176
.try_into()
@@ -170,22 +189,24 @@ impl Vm for WhpVm {
170189
}
171190

172191
fn get_sregs(&self) -> Result<CommonSpecialRegisters> {
173-
let mut whp_sregs_values: [WHV_REGISTER_VALUE; WHP_SREGS_NAMES_LEN] =
174-
unsafe { std::mem::zeroed() };
192+
let mut whp_sregs_values =
193+
AlignedRegisterValues::<WHP_SREGS_NAMES_LEN>(unsafe { std::mem::zeroed() });
194+
195+
assert_eq!((whp_sregs_values.0.as_ptr() as usize) % 16, 0);
175196

176197
unsafe {
177198
WHvGetVirtualProcessorRegisters(
178199
self.partition,
179200
0,
180201
WHP_SREGS_NAMES.as_ptr(),
181-
whp_sregs_values.len() as u32,
182-
whp_sregs_values.as_mut_ptr(),
202+
whp_sregs_values.0.len() as u32,
203+
whp_sregs_values.0.as_mut_ptr(),
183204
)?;
184205
}
185206

186207
WHP_SREGS_NAMES
187208
.into_iter()
188-
.zip(whp_sregs_values)
209+
.zip(whp_sregs_values.0)
189210
.collect::<Vec<(WHV_REGISTER_NAME, WHV_REGISTER_VALUE)>>()
190211
.as_slice()
191212
.try_into()
@@ -204,22 +225,24 @@ impl Vm for WhpVm {
204225
}
205226

206227
fn get_fpu(&self) -> Result<CommonFpu> {
207-
let mut whp_fpu_values: [WHV_REGISTER_VALUE; WHP_FPU_NAMES_LEN] =
208-
unsafe { std::mem::zeroed() };
228+
let mut whp_fpu_values =
229+
AlignedRegisterValues::<WHP_FPU_NAMES_LEN>(unsafe { std::mem::zeroed() });
230+
231+
assert_eq!((whp_fpu_values.0.as_ptr() as usize) % 16, 0);
209232

210233
unsafe {
211234
WHvGetVirtualProcessorRegisters(
212235
self.partition,
213236
0,
214237
WHP_FPU_NAMES.as_ptr(),
215-
whp_fpu_values.len() as u32,
216-
whp_fpu_values.as_mut_ptr(),
238+
whp_fpu_values.0.len() as u32,
239+
whp_fpu_values.0.as_mut_ptr(),
217240
)?;
218241
}
219242

220243
WHP_FPU_NAMES
221244
.into_iter()
222-
.zip(whp_fpu_values)
245+
.zip(whp_fpu_values.0)
223246
.collect::<Vec<(WHV_REGISTER_NAME, WHV_REGISTER_VALUE)>>()
224247
.as_slice()
225248
.try_into()

0 commit comments

Comments
 (0)