Skip to content

Commit 37aed29

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

File tree

2 files changed

+57
-21
lines changed

2 files changed

+57
-21
lines changed

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

Lines changed: 22 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,24 @@ 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+
#[allow(clippy::disallowed_macros)] // this is at compile time
160+
const _: () = {
161+
// WHP_SREGS_NAMES_LEN
162+
assert!(std::mem::align_of::<AlignedRegisterValues<WHP_SREGS_NAMES_LEN>>() % 16 == 0);
163+
assert!(offset_of!(AlignedRegisterValues<WHP_SREGS_NAMES_LEN>, 0) % 16 == 0);
164+
// WHP_REGS_NAMES_LEN
165+
assert!(std::mem::align_of::<AlignedRegisterValues<WHP_REGS_NAMES_LEN>>() % 16 == 0,);
166+
assert!(offset_of!(AlignedRegisterValues<WHP_REGS_NAMES_LEN>, 0) % 16 == 0);
167+
// WHP_FPU_NAMES_LEN
168+
assert!(std::mem::align_of::<AlignedRegisterValues<WHP_FPU_NAMES_LEN>>() % 16 == 0,);
169+
assert!(offset_of!(AlignedRegisterValues<WHP_FPU_NAMES_LEN>, 0) % 16 == 0);
170+
};
171+
150172
#[cfg(target_os = "windows")]
151173
pub(crate) const WHP_SREGS_NAMES_LEN: usize = 17;
152174
#[cfg(target_os = "windows")]

src/hyperlight_host/src/hypervisor/whp.rs

Lines changed: 35 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,18 @@ pub(crate) struct WhpVm {
8686
unsafe impl Send for WhpVm {}
8787
unsafe impl Sync for WhpVm {}
8888

89+
/// WHV_REGISTER_VALUE must be 16-byte aligned, but the rust struct is incorrectly generated
90+
/// as 8-byte aligned. This is a workaround to ensure that the array is 16-byte aligned.
91+
#[repr(C, align(16))]
92+
struct Align16<T>(T);
93+
#[allow(clippy::disallowed_macros)] // compile time
94+
const _: () = {
95+
assert!(
96+
std::mem::size_of::<Align16<WHV_REGISTER_VALUE>>()
97+
== std::mem::size_of::<WHV_REGISTER_VALUE>()
98+
);
99+
};
100+
89101
impl WhpVm {
90102
pub(crate) fn new(mmap_file_handle: HandleWrapper) -> Result<Self> {
91103
const NUM_CPU: u32 = 1;
@@ -112,12 +124,14 @@ impl WhpVm {
112124
/// Helper for setting arbitrary registers.
113125
fn set_registers(&self, registers: &[(WHV_REGISTER_NAME, WHV_REGISTER_VALUE)]) -> Result<()> {
114126
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![];
127+
128+
// Prepare register names (no special alignment needed)
129+
let mut register_names = Vec::with_capacity(register_count);
130+
let mut register_values = Vec::with_capacity(register_count);
117131

118132
for (key, value) in registers.iter() {
119133
register_names.push(*key);
120-
register_values.push(*value);
134+
register_values.push(Align16(*value));
121135
}
122136

123137
unsafe {
@@ -126,7 +140,7 @@ impl WhpVm {
126140
0,
127141
register_names.as_ptr(),
128142
register_count as u32,
129-
register_values.as_ptr(),
143+
register_values.as_ptr() as *const WHV_REGISTER_VALUE,
130144
)?;
131145
}
132146

@@ -136,22 +150,22 @@ impl WhpVm {
136150

137151
impl Vm for WhpVm {
138152
fn get_regs(&self) -> Result<CommonRegisters> {
139-
let mut whv_regs_values: [WHV_REGISTER_VALUE; WHP_REGS_NAMES_LEN] =
140-
unsafe { std::mem::zeroed() };
153+
let mut whv_regs_values =
154+
AlignedRegisterValues::<WHP_REGS_NAMES_LEN>(unsafe { std::mem::zeroed() });
141155

142156
unsafe {
143157
WHvGetVirtualProcessorRegisters(
144158
self.partition,
145159
0,
146160
WHP_REGS_NAMES.as_ptr(),
147-
WHP_REGS_NAMES_LEN as u32,
148-
whv_regs_values.as_mut_ptr(),
161+
whv_regs_values.0.len() as u32,
162+
whv_regs_values.0.as_mut_ptr(),
149163
)?;
150164
}
151165

152166
WHP_REGS_NAMES
153167
.into_iter()
154-
.zip(whv_regs_values)
168+
.zip(whv_regs_values.0)
155169
.collect::<Vec<(WHV_REGISTER_NAME, WHV_REGISTER_VALUE)>>()
156170
.as_slice()
157171
.try_into()
@@ -170,22 +184,22 @@ impl Vm for WhpVm {
170184
}
171185

172186
fn get_sregs(&self) -> Result<CommonSpecialRegisters> {
173-
let mut whp_sregs_values: [WHV_REGISTER_VALUE; WHP_SREGS_NAMES_LEN] =
174-
unsafe { std::mem::zeroed() };
187+
let mut whp_sregs_values =
188+
AlignedRegisterValues::<WHP_SREGS_NAMES_LEN>(unsafe { std::mem::zeroed() });
175189

176190
unsafe {
177191
WHvGetVirtualProcessorRegisters(
178192
self.partition,
179193
0,
180194
WHP_SREGS_NAMES.as_ptr(),
181-
whp_sregs_values.len() as u32,
182-
whp_sregs_values.as_mut_ptr(),
195+
whp_sregs_values.0.len() as u32,
196+
whp_sregs_values.0.as_mut_ptr(),
183197
)?;
184198
}
185199

186200
WHP_SREGS_NAMES
187201
.into_iter()
188-
.zip(whp_sregs_values)
202+
.zip(whp_sregs_values.0)
189203
.collect::<Vec<(WHV_REGISTER_NAME, WHV_REGISTER_VALUE)>>()
190204
.as_slice()
191205
.try_into()
@@ -204,22 +218,22 @@ impl Vm for WhpVm {
204218
}
205219

206220
fn get_fpu(&self) -> Result<CommonFpu> {
207-
let mut whp_fpu_values: [WHV_REGISTER_VALUE; WHP_FPU_NAMES_LEN] =
208-
unsafe { std::mem::zeroed() };
221+
let mut whp_fpu_values =
222+
AlignedRegisterValues::<WHP_FPU_NAMES_LEN>(unsafe { std::mem::zeroed() });
209223

210224
unsafe {
211225
WHvGetVirtualProcessorRegisters(
212226
self.partition,
213227
0,
214228
WHP_FPU_NAMES.as_ptr(),
215-
whp_fpu_values.len() as u32,
216-
whp_fpu_values.as_mut_ptr(),
229+
whp_fpu_values.0.len() as u32,
230+
whp_fpu_values.0.as_mut_ptr(),
217231
)?;
218232
}
219233

220234
WHP_FPU_NAMES
221235
.into_iter()
222-
.zip(whp_fpu_values)
236+
.zip(whp_fpu_values.0)
223237
.collect::<Vec<(WHV_REGISTER_NAME, WHV_REGISTER_VALUE)>>()
224238
.as_slice()
225239
.try_into()

0 commit comments

Comments
 (0)