db_misc.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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_defs.h"
  23. #include "pal_error.h"
  24. #include "pal_internal.h"
  25. #include "pal_linux.h"
  26. #include "pal_linux_defs.h"
  27. #include "pal_security.h"
  28. int __gettimeofday(struct timeval* tv, struct timezone* tz);
  29. unsigned long _DkSystemTimeQueryEarly(void) {
  30. #if USE_CLOCK_GETTIME == 1
  31. struct timespec time;
  32. int ret;
  33. ret = INLINE_SYSCALL(clock_gettime, 2, CLOCK_REALTIME, &time);
  34. /* Come on, gettimeofday mostly never fails */
  35. if (IS_ERR(ret))
  36. return 0;
  37. /* in microseconds */
  38. return 1000000ULL * time.tv_sec + time.tv_nsec / 1000;
  39. #else
  40. struct timeval time;
  41. int ret;
  42. ret = INLINE_SYSCALL(gettimeofday, 2, &time, NULL);
  43. /* Come on, gettimeofday mostly never fails */
  44. if (IS_ERR(ret))
  45. return 0;
  46. /* in microseconds */
  47. return 1000000ULL * time.tv_sec + time.tv_usec;
  48. #endif
  49. }
  50. unsigned long _DkSystemTimeQuery(void) {
  51. #if USE_CLOCK_GETTIME == 1
  52. struct timespec time;
  53. int ret;
  54. #if USE_VDSO_GETTIME == 1
  55. if (linux_state.vdso_clock_gettime) {
  56. ret = linux_state.vdso_clock_gettime(CLOCK_REALTIME, &time);
  57. } else {
  58. #endif
  59. ret = INLINE_SYSCALL(clock_gettime, 2, CLOCK_REALTIME, &time);
  60. #if USE_VDSO_GETTIME == 1
  61. }
  62. #endif
  63. /* Come on, gettimeofday mostly never fails */
  64. if (IS_ERR(ret))
  65. return 0;
  66. /* in microseconds */
  67. return 1000000ULL * time.tv_sec + time.tv_nsec / 1000;
  68. #else
  69. struct timeval time;
  70. int ret;
  71. #if USE_VDSO_GETTIME == 1
  72. if (linux_state.vdso_gettimeofday) {
  73. ret = linux_state.vdso_gettimeofday(&time, NULL);
  74. } else {
  75. #endif
  76. #if USE_VSYSCALL_GETTIME == 1
  77. ret = __gettimeofday(&time, NULL);
  78. #else
  79. ret = INLINE_SYSCALL(gettimeofday, 2, &time, NULL);
  80. #endif
  81. #if USE_VDSO_GETTIME == 1
  82. }
  83. #endif
  84. /* Come on, gettimeofday mostly never fails */
  85. if (IS_ERR(ret))
  86. return 0;
  87. /* in microseconds */
  88. return 1000000ULL * time.tv_sec + time.tv_usec;
  89. #endif
  90. }
  91. #if USE_ARCH_RDRAND == 1
  92. int _DkRandomBitsRead(void* buffer, int size) {
  93. int total_bytes = 0;
  94. do {
  95. unsigned long rand;
  96. asm volatile(".Lretry: rdrand %%rax\r\n jnc .Lretry\r\n" : "=a"(rand)::"memory", "cc");
  97. if (total_bytes + sizeof(rand) <= size) {
  98. *(unsigned long*)(buffer + total_bytes) = rand;
  99. total_bytes += sizeof(rand);
  100. } else {
  101. for (int i = 0; i < size - total_bytes; i++)
  102. *(unsigned char*)(buffer + total_bytes + i) = ((unsigned char*)&rand)[i];
  103. total_bytes = size;
  104. }
  105. } while (total_bytes < size);
  106. return 0;
  107. }
  108. #else
  109. size_t _DkRandomBitsRead(void* buffer, size_t size) {
  110. if (!pal_sec.random_device) {
  111. int fd = INLINE_SYSCALL(open, 3, RANDGEN_DEVICE, O_RDONLY, 0);
  112. if (IS_ERR(fd))
  113. return -PAL_ERROR_DENIED;
  114. pal_sec.random_device = fd;
  115. }
  116. size_t total_bytes = 0;
  117. do {
  118. int bytes = INLINE_SYSCALL(read, 3, pal_sec.random_device, buffer + total_bytes,
  119. size - total_bytes);
  120. if (IS_ERR(bytes))
  121. return -PAL_ERROR_DENIED;
  122. total_bytes += (size_t)bytes;
  123. } while (total_bytes < size);
  124. return 0;
  125. }
  126. #endif
  127. #if defined(__i386__)
  128. #include <asm/ldt.h>
  129. #else
  130. #include <asm/prctl.h>
  131. #endif
  132. int _DkSegmentRegisterSet(int reg, const void* addr) {
  133. int ret = 0;
  134. #if defined(__i386__)
  135. struct user_desc u_info;
  136. ret = INLINE_SYSCALL(get_thread_area, 1, &u_info);
  137. if (IS_ERR(ret))
  138. return NULL;
  139. u_info->entry_number = -1;
  140. u_info->base_addr = (unsigned int)addr;
  141. ret = INLINE_SYSCALL(set_thread_area, 1, &u_info);
  142. #else
  143. if (reg == PAL_SEGMENT_FS) {
  144. ret = INLINE_SYSCALL(arch_prctl, 2, ARCH_SET_FS, addr);
  145. } else if (reg == PAL_SEGMENT_GS) {
  146. return -PAL_ERROR_DENIED;
  147. } else {
  148. return -PAL_ERROR_INVAL;
  149. }
  150. #endif
  151. if (IS_ERR(ret))
  152. return -PAL_ERROR_DENIED;
  153. return 0;
  154. }
  155. int _DkSegmentRegisterGet(int reg, void** addr) {
  156. int ret;
  157. #if defined(__i386__)
  158. struct user_desc u_info;
  159. ret = INLINE_SYSCALL(get_thread_area, 1, &u_info);
  160. if (IS_ERR(ret))
  161. return -PAL_ERROR_DENIED;
  162. *addr = (void*)u_info->base_addr;
  163. #else
  164. unsigned long ret_addr;
  165. if (reg == PAL_SEGMENT_FS) {
  166. ret = INLINE_SYSCALL(arch_prctl, 2, ARCH_GET_FS, &ret_addr);
  167. } else if (reg == PAL_SEGMENT_GS) {
  168. // The GS segment is used for the internal TCB of PAL
  169. return -PAL_ERROR_DENIED;
  170. } else {
  171. return -PAL_ERROR_INVAL;
  172. }
  173. if (IS_ERR(ret))
  174. return -PAL_ERROR_DENIED;
  175. *addr = (void*)ret_addr;
  176. #endif
  177. return 0;
  178. }
  179. int _DkInstructionCacheFlush(const void* addr, int size) {
  180. __UNUSED(addr);
  181. __UNUSED(size);
  182. return -PAL_ERROR_NOTIMPLEMENTED;
  183. }
  184. int _DkCpuIdRetrieve(unsigned int leaf, unsigned int subleaf, unsigned int values[4]) {
  185. cpuid(leaf, subleaf, values);
  186. return 0;
  187. }