Skip to content

Commit fe1a687

Browse files
committed
Add the xmm registers to hyperv
Signed-off-by: James Sturtevant <[email protected]>
1 parent b419bde commit fe1a687

File tree

6 files changed

+156
-0
lines changed

6 files changed

+156
-0
lines changed

src/hyperlight_host/src/hypervisor/gdb/hyperv_debug.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,17 @@ impl GuestDebug for HypervDebug {
211211
regs.rip = vcpu_regs.rip;
212212
regs.rflags = vcpu_regs.rflags;
213213

214+
// Fetch XMM from WHVP
215+
if let Ok(fpu) = vcpu_fd.get_fpu() {
216+
regs.xmm = [
217+
fpu.xmm0, fpu.xmm1, fpu.xmm2, fpu.xmm3, fpu.xmm4, fpu.xmm5, fpu.xmm6, fpu.xmm7,
218+
fpu.xmm8, fpu.xmm9, fpu.xmm10, fpu.xmm11, fpu.xmm12, fpu.xmm13, fpu.xmm14,
219+
fpu.xmm15,
220+
];
221+
} else {
222+
log::warn!("Failed to read FPU/XMM via WHVP for debug registers");
223+
}
224+
214225
Ok(())
215226
}
216227

src/hyperlight_host/src/hypervisor/gdb/kvm_debug.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,17 @@ impl GuestDebug for KvmDebug {
193193
regs.rip = vcpu_regs.rip;
194194
regs.rflags = vcpu_regs.rflags;
195195

196+
// Read XMM registers from FPU state
197+
match vcpu_fd.get_fpu() {
198+
Ok(fpu) => {
199+
// Convert KVM XMM registers ([u8; 16] x 16) to [u128; 16]
200+
regs.xmm = fpu.xmm.map(u128::from_le_bytes);;
201+
},
202+
Err(e) => {
203+
log::warn!("Failed to read FPU state for XMM registers: {:?}", e);
204+
}
205+
}
206+
196207
Ok(())
197208
}
198209

src/hyperlight_host/src/hypervisor/gdb/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ pub(crate) struct X86_64Regs {
109109
pub(crate) r15: u64,
110110
pub(crate) rip: u64,
111111
pub(crate) rflags: u64,
112+
pub(crate) xmm: [u128; 16],
112113
}
113114

114115
/// Defines the possible reasons for which a vCPU can be stopped when debugging

src/hyperlight_host/src/hypervisor/gdb/mshv_debug.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,17 @@ impl GuestDebug for MshvDebug {
220220
regs.rip = vcpu_regs.rip;
221221
regs.rflags = vcpu_regs.rflags;
222222

223+
// Try to read XMM from the FPU state
224+
match vcpu_fd.get_fpu() {
225+
Ok(fpu) => {
226+
// MSHV exposes XMM as [[u8; 16]; 16]. Convert to [u128; 16]
227+
regs.xmm = fpu.xmm.map(u128::from_le_bytes);
228+
}
229+
Err(e) => {
230+
log::warn!("Failed to read FPU state for XMM registers (MSHV): {:?}", e);
231+
}
232+
}
233+
223234
Ok(())
224235
}
225236

@@ -258,6 +269,8 @@ impl GuestDebug for MshvDebug {
258269

259270
rip: regs.rip,
260271
rflags: regs.rflags,
272+
273+
261274
};
262275

263276
vcpu_fd

src/hyperlight_host/src/hypervisor/gdb/x86_64_target.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ impl SingleThreadBase for HyperlightSandboxTarget {
227227
regs.regs[15] = read_regs.r15;
228228
regs.rip = read_regs.rip;
229229
regs.eflags = read_regs.rflags as u32;
230+
regs.xmm = read_regs.xmm;
230231

231232
Ok(())
232233
}
@@ -267,6 +268,7 @@ impl SingleThreadBase for HyperlightSandboxTarget {
267268
r15: regs.regs[15],
268269
rip: regs.rip,
269270
rflags: u64::from(regs.eflags),
271+
xmm: regs.xmm,
270272
};
271273

272274
match self.send_command(DebugMsg::WriteRegisters(regs))? {

src/hyperlight_host/src/hypervisor/windows_hypervisor_platform.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,124 @@ impl VMProcessor {
696696
Ok(())
697697
}
698698

699+
pub(super) fn get_fpu(&self) -> Result<WHvFPURegisters> {
700+
use windows::Win32::System::Hypervisor::*;
701+
702+
const LEN: usize = 26;
703+
let names: [WHV_REGISTER_NAME; LEN] = [
704+
WHvX64RegisterXmm0,
705+
WHvX64RegisterXmm1,
706+
WHvX64RegisterXmm2,
707+
WHvX64RegisterXmm3,
708+
WHvX64RegisterXmm4,
709+
WHvX64RegisterXmm5,
710+
WHvX64RegisterXmm6,
711+
WHvX64RegisterXmm7,
712+
WHvX64RegisterXmm8,
713+
WHvX64RegisterXmm9,
714+
WHvX64RegisterXmm10,
715+
WHvX64RegisterXmm11,
716+
WHvX64RegisterXmm12,
717+
WHvX64RegisterXmm13,
718+
WHvX64RegisterXmm14,
719+
WHvX64RegisterXmm15,
720+
WHvX64RegisterFpMmx0,
721+
WHvX64RegisterFpMmx1,
722+
WHvX64RegisterFpMmx2,
723+
WHvX64RegisterFpMmx3,
724+
WHvX64RegisterFpMmx4,
725+
WHvX64RegisterFpMmx5,
726+
WHvX64RegisterFpMmx6,
727+
WHvX64RegisterFpMmx7,
728+
WHvX64RegisterFpControlStatus,
729+
WHvX64RegisterXmmControlStatus,
730+
];
731+
732+
let mut out: [WHV_REGISTER_VALUE; LEN] = unsafe { std::mem::zeroed() };
733+
unsafe {
734+
WHvGetVirtualProcessorRegisters(
735+
self.get_partition_hdl(),
736+
0,
737+
names.as_ptr(),
738+
LEN as u32,
739+
out.as_mut_ptr(),
740+
)?;
741+
}
742+
743+
// Helper to read a WHV_UINT128 -> u128
744+
fn u128_from_whv(fp: WHV_REGISTER_VALUE) -> u128 {
745+
unsafe {
746+
let low = fp.Fp.AsUINT128.Anonymous.Low64 as u128;
747+
let high = fp.Fp.AsUINT128.Anonymous.High64 as u128;
748+
(high << 64) | low
749+
}
750+
}
751+
752+
let xmm = [
753+
u128_from_whv(out[0]),
754+
u128_from_whv(out[1]),
755+
u128_from_whv(out[2]),
756+
u128_from_whv(out[3]),
757+
u128_from_whv(out[4]),
758+
u128_from_whv(out[5]),
759+
u128_from_whv(out[6]),
760+
u128_from_whv(out[7]),
761+
u128_from_whv(out[8]),
762+
u128_from_whv(out[9]),
763+
u128_from_whv(out[10]),
764+
u128_from_whv(out[11]),
765+
u128_from_whv(out[12]),
766+
u128_from_whv(out[13]),
767+
u128_from_whv(out[14]),
768+
u128_from_whv(out[15]),
769+
];
770+
771+
let mmx = [
772+
out[16].Reg64,
773+
out[17].Reg64,
774+
out[18].Reg64,
775+
out[19].Reg64,
776+
out[20].Reg64,
777+
out[21].Reg64,
778+
out[22].Reg64,
779+
out[23].Reg64,
780+
];
781+
782+
let fp_control_word = unsafe { out[24].FpControlStatus.Anonymous.FpControl };
783+
let fp_tag_word = unsafe { out[24].FpControlStatus.Anonymous.FpTag };
784+
let mxcsr = unsafe { out[25].XmmControlStatus.Anonymous.XmmStatusControl };
785+
786+
Ok(WHvFPURegisters {
787+
xmm0: xmm[0],
788+
xmm1: xmm[1],
789+
xmm2: xmm[2],
790+
xmm3: xmm[3],
791+
xmm4: xmm[4],
792+
xmm5: xmm[5],
793+
xmm6: xmm[6],
794+
xmm7: xmm[7],
795+
xmm8: xmm[8],
796+
xmm9: xmm[9],
797+
xmm10: xmm[10],
798+
xmm11: xmm[11],
799+
xmm12: xmm[12],
800+
xmm13: xmm[13],
801+
xmm14: xmm[14],
802+
xmm15: xmm[15],
803+
mmx0: mmx[0],
804+
mmx1: mmx[1],
805+
mmx2: mmx[2],
806+
mmx3: mmx[3],
807+
mmx4: mmx[4],
808+
mmx5: mmx[5],
809+
mmx6: mmx[6],
810+
mmx7: mmx[7],
811+
fp_control_word,
812+
fp_tag_word,
813+
mxcsr,
814+
})
815+
}
816+
699817
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
700818
pub(super) fn run(&mut self) -> Result<WHV_RUN_VP_EXIT_CONTEXT> {
701819
let partition_handle = self.get_partition_hdl();

0 commit comments

Comments
 (0)