@@ -60,6 +60,7 @@ use virt_support_x86emu::emulate::EmuCheckVtlAccessError;
60
60
use virt_support_x86emu:: emulate:: EmuTranslateError ;
61
61
use virt_support_x86emu:: emulate:: EmuTranslateResult ;
62
62
use virt_support_x86emu:: emulate:: EmulatorSupport ;
63
+ use vtl_array:: VtlArray ;
63
64
use vtl_array:: VtlSet ;
64
65
use x86defs:: xsave:: Fxsave ;
65
66
use x86defs:: xsave:: XsaveHeader ;
@@ -74,7 +75,11 @@ use zerocopy::FromZeroes;
74
75
#[ derive( InspectMut ) ]
75
76
pub struct HypervisorBackedX86 {
76
77
/// Underhill APIC state
77
- pub ( super ) lapic : Option < apic:: UhApicState > ,
78
+ pub ( super ) lapics : Option < VtlArray < apic:: UhApicState , 2 > > ,
79
+ // TODO WHP GUEST VSM: To be completely correct here, when emulating the APICs
80
+ // we would need two sets of deliverability notifications too. However currently
81
+ // we don't support VTL 1 on WHP, and on the hypervisor we don't emulate the APIC,
82
+ // so this can wait.
78
83
#[ inspect( with = "|x| inspect::AsHex(u64::from(*x))" ) ]
79
84
deliverability_notifications : HvDeliverabilityNotificationsRegister ,
80
85
/// Next set of deliverability notifications. See register definition for details.
@@ -124,21 +129,27 @@ impl BackingPrivate for HypervisorBackedX86 {
124
129
reserved : [ 0 ; 384 ] ,
125
130
} ;
126
131
127
- let lapic = params. partition . lapic . as_ref ( ) . map ( |arr| {
128
- let lapic_set = & arr[ Vtl :: Vtl0 ] ;
132
+ let lapics = params. partition . lapic . as_ref ( ) . map ( |arr| {
129
133
// Initialize APIC base to match the current VM state.
130
134
let apic_base = params
131
135
. runner
132
136
. get_vp_register ( HvX64RegisterName :: ApicBase )
133
137
. unwrap ( )
134
138
. as_u64 ( ) ;
135
- let mut lapic = lapic_set. add_apic ( params. vp_info ) ;
136
- lapic. set_apic_base ( apic_base) . unwrap ( ) ;
137
- apic:: UhApicState :: new ( lapic, & params. vp_info . base )
139
+ let mut lapic0 = arr[ Vtl :: Vtl0 ] . add_apic ( params. vp_info ) ;
140
+ lapic0. set_apic_base ( apic_base) . unwrap ( ) ;
141
+ let mut lapic1 = arr[ Vtl :: Vtl1 ] . add_apic ( params. vp_info ) ;
142
+ lapic1. set_apic_base ( apic_base) . unwrap ( ) ;
143
+
144
+ [
145
+ apic:: UhApicState :: new ( lapic0, Vtl :: Vtl0 , & params. vp_info . base ) ,
146
+ apic:: UhApicState :: new ( lapic1, Vtl :: Vtl1 , & params. vp_info . base ) ,
147
+ ]
148
+ . into ( )
138
149
} ) ;
139
150
140
151
Ok ( Self {
141
- lapic ,
152
+ lapics ,
142
153
deliverability_notifications : Default :: default ( ) ,
143
154
next_deliverability_notifications : Default :: default ( ) ,
144
155
stats : Default :: default ( ) ,
@@ -275,8 +286,12 @@ impl BackingPrivate for HypervisorBackedX86 {
275
286
Ok ( ( ) )
276
287
}
277
288
278
- fn poll_apic ( this : & mut UhProcessor < ' _ , Self > , scan_irr : bool ) -> Result < bool , UhRunVpError > {
279
- this. poll_apic ( scan_irr)
289
+ fn poll_apic (
290
+ this : & mut UhProcessor < ' _ , Self > ,
291
+ vtl : Vtl ,
292
+ scan_irr : bool ,
293
+ ) -> Result < bool , UhRunVpError > {
294
+ this. poll_apic ( vtl, scan_irr)
280
295
}
281
296
282
297
fn request_extint_readiness ( this : & mut UhProcessor < ' _ , Self > ) {
@@ -591,14 +606,21 @@ impl UhProcessor<'_, HypervisorBackedX86> {
591
606
hvdef:: HvX64MsrInterceptMessage :: ref_from_prefix ( self . runner . exit_message ( ) . payload ( ) )
592
607
. unwrap ( ) ;
593
608
let rip = next_rip ( & message. header ) ;
609
+ let last_vtl = self . last_vtl ( ) ;
594
610
595
611
tracing:: trace!( msg = %format_args!( "{:x?}" , message) , "msr" ) ;
596
612
597
613
let msr = message. msr_number ;
598
614
match message. header . intercept_access_type {
599
615
HvInterceptAccessType :: READ => {
600
- let r = if let Some ( lapic) = & mut self . backing . lapic {
601
- lapic. msr_read ( self . partition , & mut self . runner , & self . vmtime , dev, msr)
616
+ let r = if let Some ( lapics) = & mut self . backing . lapics {
617
+ lapics[ last_vtl] . msr_read (
618
+ self . partition ,
619
+ & mut self . runner ,
620
+ & self . vmtime ,
621
+ dev,
622
+ msr,
623
+ )
602
624
} else {
603
625
Err ( MsrError :: Unknown )
604
626
} ;
@@ -622,8 +644,8 @@ impl UhProcessor<'_, HypervisorBackedX86> {
622
644
}
623
645
HvInterceptAccessType :: WRITE => {
624
646
let value = ( message. rax & 0xffff_ffff ) | ( message. rdx << 32 ) ;
625
- let r = if let Some ( lapic) = & mut self . backing . lapic {
626
- lapic. msr_write (
647
+ let r = if let Some ( lapic) = & mut self . backing . lapics {
648
+ lapic[ last_vtl ] . msr_write (
627
649
self . partition ,
628
650
& mut self . runner ,
629
651
& self . vmtime ,
@@ -687,7 +709,8 @@ impl UhProcessor<'_, HypervisorBackedX86> {
687
709
}
688
710
689
711
fn handle_halt ( & mut self ) -> Result < ( ) , VpHaltReason < UhRunVpError > > {
690
- self . backing . lapic . as_mut ( ) . unwrap ( ) . halt ( ) ;
712
+ let last_vtl = self . last_vtl ( ) ;
713
+ self . backing . lapics . as_mut ( ) . unwrap ( ) [ last_vtl] . halt ( ) ;
691
714
Ok ( ( ) )
692
715
}
693
716
@@ -1116,15 +1139,17 @@ impl<T: CpuIo> EmulatorSupport for UhEmulationState<'_, '_, T, HypervisorBackedX
1116
1139
}
1117
1140
1118
1141
fn lapic_base_address ( & self ) -> Option < u64 > {
1142
+ let last_vtl = self . vp . last_vtl ( ) ;
1119
1143
self . vp
1120
1144
. backing
1121
- . lapic
1145
+ . lapics
1122
1146
. as_ref ( )
1123
- . and_then ( |lapic| lapic. base_address ( ) )
1147
+ . and_then ( |lapic| lapic[ last_vtl ] . base_address ( ) )
1124
1148
}
1125
1149
1126
1150
fn lapic_read ( & mut self , address : u64 , data : & mut [ u8 ] ) {
1127
- self . vp . backing . lapic . as_mut ( ) . unwrap ( ) . mmio_read (
1151
+ let last_vtl = self . vp . last_vtl ( ) ;
1152
+ self . vp . backing . lapics . as_mut ( ) . unwrap ( ) [ last_vtl] . mmio_read (
1128
1153
self . vp . partition ,
1129
1154
& mut self . vp . runner ,
1130
1155
& self . vp . vmtime ,
@@ -1135,7 +1160,8 @@ impl<T: CpuIo> EmulatorSupport for UhEmulationState<'_, '_, T, HypervisorBackedX
1135
1160
}
1136
1161
1137
1162
fn lapic_write ( & mut self , address : u64 , data : & [ u8 ] ) {
1138
- self . vp . backing . lapic . as_mut ( ) . unwrap ( ) . mmio_write (
1163
+ let last_vtl = self . vp . last_vtl ( ) ;
1164
+ self . vp . backing . lapics . as_mut ( ) . unwrap ( ) [ last_vtl] . mmio_write (
1139
1165
self . vp . partition ,
1140
1166
& mut self . vp . runner ,
1141
1167
& self . vp . vmtime ,
0 commit comments