db_misc.c 5.8 KB

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