@@ -33,6 +33,8 @@ use hvdef::HvVtlEntryReason;
3333use hvdef:: HvX64PendingExceptionEvent ;
3434use hvdef:: HvX64RegisterName ;
3535use hvdef:: Vtl ;
36+ use hvdef:: hypercall:: HV_INTERCEPT_ACCESS_MASK_READ ;
37+ use hvdef:: hypercall:: HV_INTERCEPT_ACCESS_MASK_WRITE ;
3638use hvdef:: hypercall:: HostVisibilityType ;
3739use hvdef:: hypercall:: HvFlushFlags ;
3840use hvdef:: hypercall:: TranslateGvaResultCode ;
@@ -1230,10 +1232,7 @@ impl<T, B: HardwareIsolatedBacking> hv1_hypercall::EnablePartitionVtl
12301232 ) ?;
12311233
12321234 * gvsm_state = GuestVsmState :: Enabled {
1233- vtl1 : CvmVtl1State {
1234- mbec_enabled : flags. enable_mbec ( ) ,
1235- ..Default :: default ( )
1236- } ,
1235+ vtl1 : CvmVtl1State :: new ( flags. enable_mbec ( ) ) ,
12371236 } ;
12381237
12391238 let protector = & self . vp . cvm_partition ( ) . isolated_memory_protector ;
@@ -2049,12 +2048,12 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
20492048 ) -> bool {
20502049 let send_intercept = self . cvm_is_protected_register_write ( vtl, reg, value) ;
20512050 if send_intercept {
2052- let message_state = B :: intercept_message_state ( self , vtl) ;
2051+ let message_state = B :: intercept_message_state ( self , vtl, false ) ;
20532052
20542053 self . send_intercept_message (
20552054 GuestVtl :: Vtl1 ,
20562055 & crate :: processor:: InterceptMessageType :: Register { reg, value }
2057- . generate_hv_message ( self . vp_index ( ) , vtl, message_state) ,
2056+ . generate_hv_message ( self . vp_index ( ) , vtl, message_state, false ) ,
20582057 ) ;
20592058 }
20602059
@@ -2083,7 +2082,7 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
20832082 // Note: writes to X86X_IA32_MSR_MISC_ENABLE are dropped, so don't
20842083 // need to check the mask.
20852084
2086- let generate_intercept = match msr {
2085+ let send_intercept = match msr {
20872086 x86defs:: X86X_MSR_LSTAR => configured_intercepts. msr_lstar_write ( ) ,
20882087 x86defs:: X86X_MSR_STAR => configured_intercepts. msr_star_write ( ) ,
20892088 x86defs:: X86X_MSR_CSTAR => configured_intercepts. msr_cstar_write ( ) ,
@@ -2105,15 +2104,16 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
21052104 _ => false ,
21062105 } ;
21072106
2108- if generate_intercept {
2109- let message_state = B :: intercept_message_state ( self , vtl) ;
2107+ if send_intercept {
2108+ let message_state = B :: intercept_message_state ( self , vtl, false ) ;
21102109
21112110 self . send_intercept_message (
21122111 GuestVtl :: Vtl1 ,
21132112 & crate :: processor:: InterceptMessageType :: Msr { msr } . generate_hv_message (
21142113 self . vp_index ( ) ,
21152114 vtl,
21162115 message_state,
2116+ false ,
21172117 ) ,
21182118 ) ;
21192119
@@ -2123,6 +2123,61 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
21232123 false
21242124 }
21252125
2126+ /// Checks if a higher VTL registered for intercepts on io port and sends
2127+ /// the intercept as required.
2128+ ///
2129+ /// If an intercept message is posted then no further processing is
2130+ /// required. The instruction pointer should not be advanced, since the
2131+ /// instruction pointer must continue to point to the instruction that
2132+ /// generated the intercept.
2133+ pub ( crate ) fn cvm_try_protect_io_port_access (
2134+ & mut self ,
2135+ vtl : GuestVtl ,
2136+ port_number : u16 ,
2137+ is_read : bool ,
2138+ access_size : u8 ,
2139+ string_access : bool ,
2140+ rep_access : bool ,
2141+ ) -> bool {
2142+ if vtl == GuestVtl :: Vtl0 {
2143+ let send_intercept = {
2144+ if let GuestVsmState :: Enabled { vtl1 } = & * self . cvm_partition ( ) . guest_vsm . read ( ) {
2145+ if is_read {
2146+ vtl1. io_read_intercepts [ port_number as usize ]
2147+ } else {
2148+ vtl1. io_write_intercepts [ port_number as usize ]
2149+ }
2150+ } else {
2151+ false
2152+ }
2153+ } ;
2154+
2155+ if send_intercept {
2156+ let message_state = B :: intercept_message_state ( self , vtl, true ) ;
2157+
2158+ self . send_intercept_message (
2159+ GuestVtl :: Vtl1 ,
2160+ & crate :: processor:: InterceptMessageType :: IoPort {
2161+ port_number,
2162+ access_size,
2163+ string_access,
2164+ rep_access,
2165+ }
2166+ . generate_hv_message (
2167+ self . vp_index ( ) ,
2168+ vtl,
2169+ message_state,
2170+ is_read,
2171+ ) ,
2172+ ) ;
2173+
2174+ return true ;
2175+ }
2176+ }
2177+
2178+ false
2179+ }
2180+
21262181 fn cvm_send_synthetic_cluster_ipi (
21272182 & mut self ,
21282183 vtl : GuestVtl ,
@@ -2354,3 +2409,66 @@ impl<T, B: HardwareIsolatedBacking> hv1_hypercall::SendSyntheticClusterIpiEx
23542409 . cvm_send_synthetic_cluster_ipi ( target_vtl, vector, processor_set)
23552410 }
23562411}
2412+
2413+ impl < T , B : HardwareIsolatedBacking > hv1_hypercall:: InstallIntercept
2414+ for UhHypercallHandler < ' _ , ' _ , T , B >
2415+ {
2416+ fn install_intercept (
2417+ & mut self ,
2418+ partition_id : u64 ,
2419+ access_type_mask : u32 ,
2420+ intercept_type : hvdef:: hypercall:: HvInterceptType ,
2421+ intercept_parameters : hvdef:: hypercall:: HvInterceptParameters ,
2422+ ) -> HvResult < ( ) > {
2423+ tracing:: debug!(
2424+ vp_index = self . vp. vp_index( ) . index( ) ,
2425+ ?access_type_mask,
2426+ ?intercept_type,
2427+ ?intercept_parameters,
2428+ "HvInstallIntercept"
2429+ ) ;
2430+
2431+ if partition_id != hvdef:: HV_PARTITION_ID_SELF {
2432+ return Err ( HvError :: AccessDenied ) ;
2433+ }
2434+
2435+ if self . intercepted_vtl == GuestVtl :: Vtl0 {
2436+ return Err ( HvError :: AccessDenied ) ;
2437+ }
2438+
2439+ match intercept_type {
2440+ hvdef:: hypercall:: HvInterceptType :: HvInterceptTypeX64IoPort => {
2441+ if access_type_mask
2442+ & !( HV_INTERCEPT_ACCESS_MASK_READ | HV_INTERCEPT_ACCESS_MASK_WRITE )
2443+ != 0
2444+ {
2445+ return Err ( HvError :: InvalidParameter ) ;
2446+ }
2447+
2448+ let mut gvsm_lock = self . vp . cvm_partition ( ) . guest_vsm . write ( ) ;
2449+
2450+ let GuestVsmState :: Enabled { vtl1, .. } = & mut * gvsm_lock else {
2451+ return Err ( HvError :: InvalidVtlState ) ;
2452+ } ;
2453+
2454+ let io_port = intercept_parameters. io_port ( ) as usize ;
2455+
2456+ vtl1. io_read_intercepts . set (
2457+ io_port,
2458+ access_type_mask & HV_INTERCEPT_ACCESS_MASK_READ != 0 ,
2459+ ) ;
2460+
2461+ vtl1. io_write_intercepts . set (
2462+ io_port,
2463+ access_type_mask & HV_INTERCEPT_ACCESS_MASK_WRITE != 0 ,
2464+ ) ;
2465+
2466+ // TODO GUEST VSM: flush io port accesses on other VPs before
2467+ // returning back to VTL 0
2468+ }
2469+ _ => return Err ( HvError :: InvalidParameter ) ,
2470+ }
2471+
2472+ Ok ( ( ) )
2473+ }
2474+ }
0 commit comments