db_misc.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * db_misc.c
  17. *
  18. * This file contains APIs for miscellaneous use.
  19. */
  20. #include "pal_defs.h"
  21. #include "pal_linux_defs.h"
  22. #include "pal.h"
  23. #include "pal_internal.h"
  24. #include "pal_linux.h"
  25. #include "pal_error.h"
  26. #include "pal_debug.h"
  27. #include "pal_security.h"
  28. #include "api.h"
  29. #include <linux/time.h>
  30. #include <asm/fcntl.h>
  31. unsigned long _DkSystemTimeQuery (void)
  32. {
  33. unsigned long microsec;
  34. int ret = ocall_gettime(&microsec);
  35. assert(!ret);
  36. return microsec;
  37. }
  38. int _DkRandomBitsRead (void * buffer, int size)
  39. {
  40. int i = 0;
  41. for ( ; i < size ; i += 4) {
  42. uint32_t rand = rdrand();
  43. if (i + 4 <= size) {
  44. *(uint32_t *)(buffer + i) = rand;
  45. } else {
  46. switch (size - i) {
  47. case 3:
  48. *(uint16_t *)(buffer + i) = rand & 0xffff;
  49. i += 2;
  50. rand >>= 16;
  51. case 1:
  52. *(uint8_t *)(buffer + i) = rand & 0xff;
  53. i++;
  54. break;
  55. case 2:
  56. *(uint16_t *)(buffer + i) = rand & 0xffff;
  57. i += 2;
  58. break;
  59. }
  60. break;
  61. }
  62. }
  63. return i;
  64. }
  65. int _DkInstructionCacheFlush (const void * addr, int size)
  66. {
  67. return -PAL_ERROR_NOTIMPLEMENTED;
  68. }
  69. int _DkSegmentRegisterSet (int reg, const void * addr)
  70. {
  71. /* GS is internally used, denied any access to it */
  72. if (reg != PAL_SEGMENT_FS)
  73. return -PAL_ERROR_DENIED;
  74. SET_ENCLAVE_TLS(fsbase, (void *) addr);
  75. wrfsbase((uint64_t) addr);
  76. return 0;
  77. }
  78. int _DkSegmentRegisterGet (int reg, void ** addr)
  79. {
  80. /* GS is internally used, denied any access to it */
  81. if (reg != PAL_SEGMENT_FS)
  82. return -PAL_ERROR_DENIED;
  83. *addr = (void *) GET_ENCLAVE_TLS(fsbase);
  84. return 0;
  85. }
  86. #define CPUID_CACHE_SIZE 64
  87. #define CPUID_CACHE_INVALID ((unsigned int) -1)
  88. static PAL_LOCK cpuid_cache_lock = LOCK_INIT;
  89. static struct pal_cpuid {
  90. unsigned int recently;
  91. unsigned int leaf, subleaf;
  92. unsigned int values[4];
  93. } pal_cpuid_cache[CPUID_CACHE_SIZE];
  94. static int pal_cpuid_cache_top = 0;
  95. static unsigned int pal_cpuid_clock = 0;
  96. int get_cpuid_from_cache (unsigned int leaf, unsigned int subleaf,
  97. unsigned int values[4])
  98. {
  99. _DkInternalLock(&cpuid_cache_lock);
  100. for (int i = 0 ; i < pal_cpuid_cache_top ; i++)
  101. if (pal_cpuid_cache[i].leaf == leaf &&
  102. pal_cpuid_cache[i].subleaf == subleaf) {
  103. values[0] = pal_cpuid_cache[i].values[0];
  104. values[1] = pal_cpuid_cache[i].values[1];
  105. values[2] = pal_cpuid_cache[i].values[2];
  106. values[3] = pal_cpuid_cache[i].values[3];
  107. pal_cpuid_cache[i].recently = ++pal_cpuid_clock;
  108. _DkInternalUnlock(&cpuid_cache_lock);
  109. return 0;
  110. }
  111. _DkInternalUnlock(&cpuid_cache_lock);
  112. return -PAL_ERROR_DENIED;
  113. }
  114. void add_cpuid_to_cache (unsigned int leaf, unsigned int subleaf,
  115. unsigned int values[4])
  116. {
  117. struct pal_cpuid * chosen;
  118. _DkInternalLock(&cpuid_cache_lock);
  119. if (pal_cpuid_cache_top < CPUID_CACHE_SIZE) {
  120. for (int i = 0 ; i < pal_cpuid_cache_top ; i++)
  121. if (pal_cpuid_cache[i].leaf == leaf &&
  122. pal_cpuid_cache[i].subleaf == subleaf) {
  123. _DkInternalUnlock(&cpuid_cache_lock);
  124. return;
  125. }
  126. chosen = &pal_cpuid_cache[pal_cpuid_cache_top++];
  127. } else {
  128. unsigned int oldest_clock = pal_cpuid_cache[0].recently;
  129. chosen = &pal_cpuid_cache[0];
  130. if (pal_cpuid_cache[0].leaf == leaf &&
  131. pal_cpuid_cache[0].subleaf == subleaf) {
  132. _DkInternalUnlock(&cpuid_cache_lock);
  133. return;
  134. }
  135. for (int i = 1 ; i < pal_cpuid_cache_top ; i++) {
  136. if (pal_cpuid_cache[i].leaf == leaf &&
  137. pal_cpuid_cache[i].subleaf == subleaf) {
  138. _DkInternalUnlock(&cpuid_cache_lock);
  139. return;
  140. }
  141. if (pal_cpuid_cache[i].recently > oldest_clock) {
  142. chosen = &pal_cpuid_cache[i];
  143. oldest_clock = pal_cpuid_cache[i].recently;
  144. }
  145. }
  146. }
  147. chosen->leaf = leaf;
  148. chosen->subleaf = subleaf;
  149. chosen->values[0] = values[0];
  150. chosen->values[1] = values[1];
  151. chosen->values[2] = values[2];
  152. chosen->values[3] = values[3];
  153. chosen->recently = ++pal_cpuid_clock;
  154. _DkInternalUnlock(&cpuid_cache_lock);
  155. }
  156. int _DkCpuIdRetrieve (unsigned int leaf, unsigned int subleaf,
  157. unsigned int values[4])
  158. {
  159. if (leaf != 0x4 && leaf != 0x7 && leaf != 0xb)
  160. subleaf = 0;
  161. if (!get_cpuid_from_cache(leaf, subleaf, values))
  162. return 0;
  163. if (ocall_cpuid(leaf, subleaf, values) < 0)
  164. return -PAL_ERROR_DENIED;
  165. add_cpuid_to_cache(leaf, subleaf, values);
  166. return 0;
  167. }