crypto.cpp 6.0 KB

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