db_misc.c 5.1 KB

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