1+ //! Benchmarks for protocol handling.
2+ //!
3+ //! Copyright (c) Microsoft Corporation.
4+ //!
5+ //! SPDX-License-Identifier: Apache-2.0
6+ //!
7+
18use core:: ffi:: c_void;
29
310use mu_rust_helpers:: perf_timer:: { Arch , ArchFunctionality as _} ;
@@ -53,6 +60,7 @@ pub(crate) fn bench_open_protocol(_handle: efi::Handle, num_calls: usize) -> Res
5360 let mut stats: Stats < f64 > = Stats :: new ( ) ;
5461 for _ in 0 ..num_calls {
5562 let start = Arch :: cpu_count ( ) ;
63+ // SAFETY: The resulting interface reference is not used at all during the test.
5664 ( unsafe {
5765 BOOT_SERVICES
5866 . open_protocol :: < TestProtocol1 > (
@@ -99,6 +107,7 @@ pub(crate) fn bench_close_protocol(_handle: efi::Handle, num_calls: usize) -> Re
99107 . map_err ( |e| BenchError :: BenchSetup ( "Failed to install protocol handle" , e) ) ?;
100108 let mut stats: Stats < f64 > = Stats :: new ( ) ;
101109 for _ in 0 ..num_calls {
110+ // SAFETY: The resulting interface reference is not used at all during the test.
102111 unsafe {
103112 BOOT_SERVICES
104113 . open_protocol :: < TestProtocol1 > (
@@ -117,40 +126,58 @@ pub(crate) fn bench_close_protocol(_handle: efi::Handle, num_calls: usize) -> Re
117126 let end = Arch :: cpu_count ( ) ;
118127 stats. update ( ( end - start) as f64 ) ;
119128 }
129+
130+ // Uninstall mock protocols after benchmarking.
131+ BOOT_SERVICES
132+ . uninstall_protocol_interface ( protocol_install. 0 , protocol_install. 1 )
133+ . map_err ( |e| BenchError :: BenchCleanup ( "Failed to uninstall protocol" , e) ) ?;
134+ BOOT_SERVICES
135+ . uninstall_protocol_interface ( agent_install. 0 , agent_install. 1 )
136+ . map_err ( |e| BenchError :: BenchCleanup ( "Failed to uninstall agent protocol" , e) ) ?;
137+ BOOT_SERVICES
138+ . uninstall_protocol_interface ( controller_install. 0 , controller_install. 1 )
139+ . map_err ( |e| BenchError :: BenchCleanup ( "Failed to uninstall controller protocol" , e) ) ?;
140+
120141 Ok ( stats)
121142}
122143
123144/// Benchmarks protocol handling performance.
124145/// This is a legacy method but is still included due to needing to support legacy UEFI (1.0).
125146pub ( crate ) fn bench_handle_protocol ( _handle : efi:: Handle , num_calls : usize ) -> Result < Stats < f64 > , BenchError > {
126147 // Set up and install the protocol to be accessed.
127- let protocol_handle = BOOT_SERVICES
148+ let protocol_install = BOOT_SERVICES
128149 . install_protocol_interface ( None , Box :: new ( TestProtocol1 { } ) )
129- . map_err ( |e| BenchError :: BenchSetup ( "Failed to install protocol" , e) ) ?
130- . 0 ;
150+ . map_err ( |e| BenchError :: BenchSetup ( "Failed to install protocol" , e) ) ?;
131151 let mut stats: Stats < f64 > = Stats :: new ( ) ;
132152 for _ in 0 ..num_calls {
133153 let start = Arch :: cpu_count ( ) ;
154+ // SAFETY: The resulting interface reference is not used at all during the test.
134155 ( unsafe {
135156 BOOT_SERVICES
136- . handle_protocol :: < TestProtocol1 > ( protocol_handle )
157+ . handle_protocol :: < TestProtocol1 > ( protocol_install . 0 )
137158 . map_err ( |e| BenchError :: BenchTest ( "Failed to handle protocol" , e) )
138159 } ) ?;
139160
140161 let end = Arch :: cpu_count ( ) ;
141162 stats. update ( ( end - start) as f64 ) ;
142163 }
164+ // Uninstall mock protocol after benchmarking.
165+ BOOT_SERVICES
166+ . uninstall_protocol_interface ( protocol_install. 0 , protocol_install. 1 )
167+ . map_err ( |e| BenchError :: BenchCleanup ( "Failed to uninstall protocol" , e) ) ?;
143168 Ok ( stats)
144169}
145170
146171/// Benchmarks device path resolution.
147172pub ( crate ) fn bench_locate_device_path ( handle : efi:: Handle , num_calls : usize ) -> Result < Stats < f64 > , BenchError > {
148- // Install a protocol on the current image to get a valid device handle.
173+ // Find existing protocol handles to locate device path.
174+ // SAFETY: There is only one reference to the `loaded_image_protocol` interface.
149175 let loaded_image_protocol = unsafe {
150176 BOOT_SERVICES
151177 . handle_protocol :: < efi:: protocols:: loaded_image:: Protocol > ( handle)
152178 . map_err ( |e| BenchError :: BenchSetup ( "Failed to get loaded image protocol." , e) ) ?
153179 } ;
180+ // SAFETY: There is only one reference to the `device_path_protocol` interface.
154181 let device_path_protocol = unsafe {
155182 BOOT_SERVICES
156183 . handle_protocol :: < efi:: protocols:: device_path:: Protocol > ( loaded_image_protocol. device_handle )
@@ -161,6 +188,7 @@ pub(crate) fn bench_locate_device_path(handle: efi::Handle, num_calls: usize) ->
161188 for _ in 0 ..num_calls {
162189 let mut device_path_ptr = device_path_protocol as * mut efi:: protocols:: device_path:: Protocol ;
163190 let start = Arch :: cpu_count ( ) ;
191+ // SAFETY: The device path has been constructed above as a valid pointer.
164192 unsafe {
165193 BOOT_SERVICES
166194 . locate_device_path ( & efi:: protocols:: device_path:: PROTOCOL_GUID , & mut device_path_ptr as * mut _ )
@@ -240,13 +268,19 @@ pub(crate) fn bench_reinstall_protocol_interface(
240268 . map_err ( |e| BenchError :: BenchSetup ( "Failed to install dummy protocol" , e) ) ?;
241269
242270 let start = Arch :: cpu_count ( ) ;
243- BOOT_SERVICES
271+ let reinstall = BOOT_SERVICES
244272 . reinstall_protocol_interface ( protocol_install. 0 , protocol_install. 1 , new_interface)
245273 . map_err ( |e| BenchError :: BenchTest ( "Failed to reinstall protocol interface" , e) ) ?;
246274
247275 let end = Arch :: cpu_count ( ) ;
248276 stats. update ( ( end - start) as f64 ) ;
277+
278+ // Cleanup: Uninstall the protocol after benchmarking. (It will be installed and reinstalled in the next iteration.)
279+ BOOT_SERVICES
280+ . uninstall_protocol_interface ( protocol_install. 0 , reinstall. 0 )
281+ . map_err ( |e| BenchError :: BenchCleanup ( "Failed to uninstall protocol interface" , e) ) ?;
249282 }
283+
250284 Ok ( stats)
251285}
252286
@@ -272,5 +306,11 @@ pub(crate) fn bench_uninstall_protocol_interface(
272306 . install_protocol_interface ( None , Box :: new ( TestProtocol1 { } ) )
273307 . map_err ( |e| BenchError :: BenchCleanup ( "Failed to install a new dummy protocol" , e) ) ?;
274308 }
309+
310+ // Installation from last iteration cleanup.
311+ BOOT_SERVICES
312+ . uninstall_protocol_interface ( protocol_install. 0 , protocol_install. 1 )
313+ . map_err ( |e| BenchError :: BenchCleanup ( "Failed to uninstall protocol interface" , e) ) ?;
314+
275315 Ok ( stats)
276316}
0 commit comments