iPXE
librm_test.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3 *
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.
8 *
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.
13 *
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
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * Real mode transition self-tests
29 *
30 * This file allows for easy measurement of the time taken to perform
31 * real mode transitions, which may have a substantial overhead when
32 * running under a hypervisor.
33 *
34 */
35
36/* Forcibly enable assertions */
37#undef NDEBUG
38
39#include <ipxe/test.h>
40#include <ipxe/profile.h>
41#include <realmode.h>
42
43/** Number of sample iterations for profiling */
44#define PROFILE_COUNT 4096
45
46/** Protected-to-real mode transition profiler */
47static struct profiler p2r_profiler __profiler = { .name = "p2r" };
48
49/** Real-to-protected mode transition profiler */
50static struct profiler r2p_profiler __profiler = { .name = "r2p" };
51
52/** Real-mode call profiler */
53static struct profiler real_call_profiler __profiler = { .name = "real_call" };
54
55/** Virtual call profiler */
56static struct profiler virt_call_profiler __profiler = { .name = "virt_call" };
57
58/**
59 * Dummy function for profiling tests
60 */
61static __asmcall __used void
63 /* Do nothing */
64}
65
66/**
67 * Perform real mode transition self-tests
68 *
69 */
70static void librm_test_exec ( void ) {
71 unsigned int i;
72 unsigned long timestamp;
73 uint32_t timestamp_lo;
74 uint32_t timestamp_hi;
77 uint32_t discard_d;
78
79 /* Profile mode transitions. We want to profile each
80 * direction of the transition separately, so perform an RDTSC
81 * while in real mode and tweak the profilers' start/stop
82 * times appropriately.
83 */
84 for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
85 profile_start ( &p2r_profiler );
86 __asm__ __volatile__ ( REAL_CODE ( "rdtsc\n\t" )
87 : "=a" ( timestamp_lo ),
88 "=d" ( timestamp_hi )
89 : );
90 timestamp = timestamp_lo;
91 if ( sizeof ( timestamp ) > sizeof ( timestamp_lo ) )
92 timestamp |= ( ( ( uint64_t ) timestamp_hi ) << 32 );
93 profile_start_at ( &r2p_profiler, timestamp );
94 profile_stop ( &r2p_profiler );
95 profile_stop_at ( &p2r_profiler, timestamp );
96 }
97
98 /* Profile complete real-mode call cycle */
99 for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
100 profile_start ( &real_call_profiler );
101 __asm__ __volatile__ ( REAL_CODE ( "" ) : );
102 profile_stop ( &real_call_profiler );
103 }
104
105 /* Profile complete virtual call cycle */
106 for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
107 __asm__ __volatile__ ( REAL_CODE ( "rdtsc\n\t"
108 "movl %k0, %k2\n\t"
110 "rdtsc\n\t" )
111 : "=a" ( stopped ), "=d" ( discard_d ),
112 "=R" ( started ) : );
113 profile_start_at ( &virt_call_profiler, started );
114 profile_stop_at ( &virt_call_profiler, stopped );
115 }
116}
117
118/** Real mode transition self-test */
119struct self_test librm_test __self_test = {
120 .name = "librm",
121 .exec = librm_test_exec,
122};
123
124REQUIRING_SYMBOL ( librm_test );
#define __asmcall
Declare a function with standard calling conventions.
Definition compiler.h:15
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
unsigned int uint32_t
Definition stdint.h:12
unsigned long long uint64_t
Definition stdint.h:13
#define PROFILE_COUNT
Number of sample iterations for profiling.
Definition cipher_test.c:45
uint64_t timestamp
Timestamp.
Definition ena.h:9
static int test
Definition epic100.c:73
#define __used
Declare a function as used.
Definition compiler.h:605
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define REQUIRE_OBJECT(object)
Require an object.
Definition compiler.h:202
#define REQUIRING_SYMBOL(symbol)
Specify the file's requiring symbol.
Definition compiler.h:140
Profiling.
#define __profiler
Declare a profiler.
Definition profile.h:61
static void profile_stop_at(struct profiler *profiler, unsigned long stopped)
Stop profiling.
Definition profile.h:146
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition profile.h:174
static void profile_start_at(struct profiler *profiler, unsigned long started)
Start profiling.
Definition profile.h:132
static void profile_start(struct profiler *profiler)
Start profiling.
Definition profile.h:161
static int started
"startup() has been called" flag
Definition init.c:38
#define REAL_CODE(asm_code_str)
Definition libkir.h:226
#define VIRT_CALL(function)
Call C function from real-mode code.
Definition librm.h:72
static __asmcall __used void librm_test_call(struct i386_all_regs *ix86 __unused)
Dummy function for profiling tests.
Definition librm_test.c:62
static void librm_test_exec(void)
Perform real mode transition self-tests.
Definition librm_test.c:70
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
A full register dump.
Definition registers.h:174
A data structure for storing profiling information.
Definition profile.h:27
unsigned long stopped
Stop timestamp.
Definition profile.h:33
A self-test set.
Definition test.h:15
Self-test infrastructure.
#define __self_test
Declare a self-test.
Definition test.h:32