2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER );
24 * Real mode transition self-tests
26 * This file allows for easy measurement of the time taken to perform
27 * real mode transitions, which may have a substantial overhead when
28 * running under a hypervisor.
32 /* Forcibly enable assertions */
35 #include <ipxe/test.h>
36 #include <ipxe/profile.h>
39 /** Number of sample iterations for profiling */
40 #define PROFILE_COUNT 4096
42 /** Protected-to-real mode transition profiler */
43 static struct profiler p2r_profiler __profiler = { .name = "p2r" };
45 /** Real-to-protected mode transition profiler */
46 static struct profiler r2p_profiler __profiler = { .name = "r2p" };
48 /** Real-mode call profiler */
49 static struct profiler real_call_profiler __profiler = { .name = "real_call" };
51 /** Protected-mode call profiler */
52 static struct profiler prot_call_profiler __profiler = { .name = "prot_call" };
55 * Dummy protected-mode function
57 static void librm_test_prot_call ( void ) {
62 * Perform real mode transition self-tests
65 static void librm_test_exec ( void ) {
67 unsigned long timestamp;
68 unsigned long started;
69 unsigned long stopped;
70 unsigned int discard_d;
72 /* Profile mode transitions. We want to profile each
73 * direction of the transition separately, so perform an RDTSC
74 * while in real mode and tweak the profilers' start/stop
75 * times appropriately.
77 for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
78 profile_start ( &p2r_profiler );
79 __asm__ __volatile__ ( REAL_CODE ( "rdtsc\n\t" )
80 : "=a" ( timestamp ), "=d" ( discard_d )
82 profile_start_at ( &r2p_profiler, timestamp );
83 profile_stop ( &r2p_profiler );
84 profile_stop_at ( &p2r_profiler, timestamp );
87 /* Profile complete real-mode call cycle */
88 for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
89 profile_start ( &real_call_profiler );
90 __asm__ __volatile__ ( REAL_CODE ( "" ) : : );
91 profile_stop ( &real_call_profiler );
94 /* Profile complete protected-mode call cycle */
95 for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
96 __asm__ __volatile__ ( REAL_CODE ( "rdtsc\n\t"
103 : "=a" ( stopped ), "=d" ( discard_d ),
105 : "i" ( librm_test_prot_call ) );
106 profile_start_at ( &prot_call_profiler, started );
107 profile_stop_at ( &prot_call_profiler, stopped );
111 /** Real mode transition self-test */
112 struct self_test librm_test __self_test = {
114 .exec = librm_test_exec,
117 REQUIRE_OBJECT ( test );