@@ -33,6 +33,8 @@ use hvdef::HvVtlEntryReason;
33
33
use hvdef:: HvX64PendingExceptionEvent ;
34
34
use hvdef:: HvX64RegisterName ;
35
35
use hvdef:: Vtl ;
36
+ use hvdef:: hypercall:: HV_INTERCEPT_ACCESS_MASK_READ ;
37
+ use hvdef:: hypercall:: HV_INTERCEPT_ACCESS_MASK_WRITE ;
36
38
use hvdef:: hypercall:: HostVisibilityType ;
37
39
use hvdef:: hypercall:: HvFlushFlags ;
38
40
use hvdef:: hypercall:: TranslateGvaResultCode ;
@@ -1230,10 +1232,7 @@ impl<T, B: HardwareIsolatedBacking> hv1_hypercall::EnablePartitionVtl
1230
1232
) ?;
1231
1233
1232
1234
* gvsm_state = GuestVsmState :: Enabled {
1233
- vtl1 : CvmVtl1State {
1234
- mbec_enabled : flags. enable_mbec ( ) ,
1235
- ..Default :: default ( )
1236
- } ,
1235
+ vtl1 : CvmVtl1State :: new ( flags. enable_mbec ( ) ) ,
1237
1236
} ;
1238
1237
1239
1238
let protector = & self . vp . cvm_partition ( ) . isolated_memory_protector ;
@@ -2049,12 +2048,12 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
2049
2048
) -> bool {
2050
2049
let send_intercept = self . cvm_is_protected_register_write ( vtl, reg, value) ;
2051
2050
if send_intercept {
2052
- let message_state = B :: intercept_message_state ( self , vtl) ;
2051
+ let message_state = B :: intercept_message_state ( self , vtl, false ) ;
2053
2052
2054
2053
self . send_intercept_message (
2055
2054
GuestVtl :: Vtl1 ,
2056
2055
& 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 ) ,
2058
2057
) ;
2059
2058
}
2060
2059
@@ -2083,7 +2082,7 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
2083
2082
// Note: writes to X86X_IA32_MSR_MISC_ENABLE are dropped, so don't
2084
2083
// need to check the mask.
2085
2084
2086
- let generate_intercept = match msr {
2085
+ let send_intercept = match msr {
2087
2086
x86defs:: X86X_MSR_LSTAR => configured_intercepts. msr_lstar_write ( ) ,
2088
2087
x86defs:: X86X_MSR_STAR => configured_intercepts. msr_star_write ( ) ,
2089
2088
x86defs:: X86X_MSR_CSTAR => configured_intercepts. msr_cstar_write ( ) ,
@@ -2105,15 +2104,16 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
2105
2104
_ => false ,
2106
2105
} ;
2107
2106
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 ) ;
2110
2109
2111
2110
self . send_intercept_message (
2112
2111
GuestVtl :: Vtl1 ,
2113
2112
& crate :: processor:: InterceptMessageType :: Msr { msr } . generate_hv_message (
2114
2113
self . vp_index ( ) ,
2115
2114
vtl,
2116
2115
message_state,
2116
+ false ,
2117
2117
) ,
2118
2118
) ;
2119
2119
@@ -2123,6 +2123,61 @@ impl<B: HardwareIsolatedBacking> UhProcessor<'_, B> {
2123
2123
false
2124
2124
}
2125
2125
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
+
2126
2181
fn cvm_send_synthetic_cluster_ipi (
2127
2182
& mut self ,
2128
2183
vtl : GuestVtl ,
@@ -2354,3 +2409,66 @@ impl<T, B: HardwareIsolatedBacking> hv1_hypercall::SendSyntheticClusterIpiEx
2354
2409
. cvm_send_synthetic_cluster_ipi ( target_vtl, vector, processor_set)
2355
2410
}
2356
2411
}
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