1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sched.h>
#include <sys/resource.h>
#include <ctype.h>
#define USEC_PER_SEC 1000000ULL
#define MAX_COUNT 1000000000ULL
#define NUM_INSTS_GARBAGE 18
// Contains information about benchmark options.
typedef struct {
int cpu_to_lock;
int locked_freq;
} command_data_t;
void usage() {
printf("--------------------------------------------------------------------------------\n");
printf("Usage:");
printf(" crypto [--cpu_to_lock CPU] [--locked_freq FREQ_IN_KHZ]\n\n");
printf("!!!!!!Lock the desired core to a desired frequency before invoking this benchmark.\n");
printf(
"Hint: Set scaling_max_freq=scaling_min_freq=FREQ_IN_KHZ. FREQ_IN_KHZ "
"can be obtained from scaling_available_freq\n");
printf("--------------------------------------------------------------------------------\n");
}
int processOptions(int argc, char **argv, command_data_t *cmd_data) {
// Initialize the command_flags.
cmd_data->cpu_to_lock = 0;
cmd_data->locked_freq = 1;
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
int *save_value = NULL;
if (strcmp(argv[i], "--cpu_to_lock") == 0) {
save_value = &cmd_data->cpu_to_lock;
} else if (strcmp(argv[i], "--locked_freq") == 0) {
save_value = &cmd_data->locked_freq;
} else {
printf("Unknown option %s\n", argv[i]);
return -1;
}
if (save_value) {
// Checking both characters without a strlen() call should be
// safe since as long as the argument exists, one character will
// be present (\0). And if the first character is '-', then
// there will always be a second character (\0 again).
if (i == argc - 1 ||
(argv[i + 1][0] == '-' && !isdigit(argv[i + 1][1]))) {
printf("The option %s requires one argument.\n", argv[i]);
return -1;
}
*save_value = (int)strtol(argv[++i], NULL, 0);
}
}
}
return 0;
}
/* Performs encryption on garbage values. In Cortex-A57 r0p1 and later
* revisions, pairs of dependent AESE/AESMC and AESD/AESIMC instructions are
* higher performance when adjacent, and in the described order below. */
void garbage_encrypt() {
__asm__ __volatile__(
"aese v0.16b, v4.16b ;"
"aesmc v0.16b, v0.16b ;"
"aese v1.16b, v4.16b ;"
"aesmc v1.16b, v1.16b ;"
"aese v2.16b, v4.16b ;"
"aesmc v2.16b, v2.16b ;"
"aese v0.16b, v5.16b ;"
"aesmc v0.16b, v0.16b ;"
"aese v1.16b, v5.16b ;"
"aesmc v1.16b, v1.16b ;"
"aese v2.16b, v5.16b ;"
"aesmc v2.16b, v2.16b ;"
"aese v0.16b, v6.16b ;"
"aesmc v0.16b, v0.16b ;"
"aese v1.16b, v6.16b ;"
"aesmc v1.16b, v1.16b ;"
"aese v2.16b, v6.16b ;"
"aesmc v2.16b, v2.16b ;");
}
void garbage_decrypt() {
__asm__ __volatile__(
"aesd v0.16b, v4.16b ;"
"aesimc v0.16b, v0.16b ;"
"aesd v1.16b, v4.16b ;"
"aesimc v1.16b, v1.16b ;"
"aesd v2.16b, v4.16b ;"
"aesimc v2.16b, v2.16b ;"
"aesd v0.16b, v5.16b ;"
"aesimc v0.16b, v0.16b ;"
"aesd v1.16b, v5.16b ;"
"aesimc v1.16b, v1.16b ;"
"aesd v2.16b, v5.16b ;"
"aesimc v2.16b, v2.16b ;"
"aesd v0.16b, v6.16b ;"
"aesimc v0.16b, v0.16b ;"
"aesd v1.16b, v6.16b ;"
"aesimc v1.16b, v1.16b ;"
"aesd v2.16b, v6.16b ;"
"aesimc v2.16b, v2.16b ;");
}
int main(int argc, char **argv) {
usage();
command_data_t cmd_data;
if(processOptions(argc, argv, &cmd_data) == -1) {
usage();
return -1;
}
unsigned long long count = 0;
struct timeval begin_time, end_time, elapsed_time;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cmd_data.cpu_to_lock, &cpuset);
if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
perror("sched_setaffinity failed");
return 1;
}
gettimeofday(&begin_time, NULL);
while (count < MAX_COUNT) {
garbage_encrypt();
count++;
}
gettimeofday(&end_time, NULL);
timersub(&end_time, &begin_time, &elapsed_time);
fprintf(stderr, "encrypt: %llu us\n",
elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec);
fprintf(stderr, "encrypt instructions: %llu\n",
MAX_COUNT * NUM_INSTS_GARBAGE);
fprintf(stderr, "encrypt instructions per second: %f\n",
(float)(MAX_COUNT * NUM_INSTS_GARBAGE * USEC_PER_SEC) /
(elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec));
if (cmd_data.locked_freq != 0) {
fprintf(stderr, "encrypt instructions per cycle: %f\n",
(float)(MAX_COUNT * NUM_INSTS_GARBAGE * USEC_PER_SEC) /
((elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec) *
1000 * cmd_data.locked_freq));
}
printf("--------------------------------------------------------------------------------\n");
count = 0;
gettimeofday(&begin_time, NULL);
while (count < MAX_COUNT) {
garbage_decrypt();
count++;
}
gettimeofday(&end_time, NULL);
timersub(&end_time, &begin_time, &elapsed_time);
fprintf(stderr, "decrypt: %llu us\n",
elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec);
fprintf(stderr, "decrypt instructions: %llu\n",
MAX_COUNT * NUM_INSTS_GARBAGE);
fprintf(stderr, "decrypt instructions per second: %f\n",
(float)(MAX_COUNT * NUM_INSTS_GARBAGE * USEC_PER_SEC) /
(elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec));
if (cmd_data.locked_freq != 0) {
fprintf(stderr, "decrypt instructions per cycle: %f\n",
(float)(MAX_COUNT * NUM_INSTS_GARBAGE * USEC_PER_SEC) /
((elapsed_time.tv_sec * USEC_PER_SEC + elapsed_time.tv_usec) *
1000 * cmd_data.locked_freq));
}
return 0;
}
|