db_misc.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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_freebsd_defs.h"
  20. #include "pal.h"
  21. #include "pal_internal.h"
  22. #include "pal_freebsd.h"
  23. #include "pal_error.h"
  24. #include "pal_security.h"
  25. #include "api.h"
  26. #include <sys/time.h>
  27. #include <fcntl.h>
  28. unsigned long _DkSystemTimeQuery (void)
  29. {
  30. #if USE_CLOCK_GETTIME == 1
  31. struct timespec time;
  32. int ret;
  33. ret = INLINE_SYSCALL(clock_gettime, 2, CLOCK_MONOTONIC, &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. #if USE_ARCH_RDRAND == 1
  51. int _DkRandomBitsRead (void * buffer, int size)
  52. {
  53. int total_bytes = 0;
  54. do {
  55. unsigned long rand;
  56. asm volatile (".Lretry: rdrand %%rax\r\n jnc .Lretry\r\n"
  57. : "=a"(rand) :: "memory");
  58. if (total_bytes + sizeof(rand) <= size) {
  59. *(unsigned long *) (buffer + total_bytes) = rand;
  60. total_bytes += sizeof(rand);
  61. } else {
  62. for (int i = 0 ; i < size - total_bytes ; i++)
  63. *(unsigned char *) (buffer + total_bytes + i) = ((unsigned char *) &rand)[i];
  64. total_bytes = size;
  65. }
  66. } while (total_bytes < size);
  67. return 0;
  68. }
  69. #else
  70. int _DkRandomBitsRead (void * buffer, int size)
  71. {
  72. if (!pal_sec.rand_gen) {
  73. int rand = INLINE_SYSCALL(open, 3, "/dev/urandom", O_RDONLY, 0);
  74. if (IS_ERR(rand))
  75. return -PAL_ERROR_DENIED;
  76. pal_sec.rand_gen = rand;
  77. }
  78. int total_bytes = 0;
  79. do {
  80. int bytes = INLINE_SYSCALL(read, 3, pal_sec.rand_gen,
  81. buffer + total_bytes, size - total_bytes);
  82. if (IS_ERR(bytes))
  83. return -PAL_ERROR_DENIED;
  84. total_bytes += bytes;
  85. } while (total_bytes < size);
  86. return 0;
  87. }
  88. #endif
  89. #if defined(__i386__)
  90. #include <ldt.h>
  91. #else
  92. #include <x86/sysarch.h>
  93. #endif
  94. int _DkSegmentRegisterSet (int reg, const void * addr)
  95. {
  96. int ret = 0;
  97. #if defined(__i386__)
  98. struct user_desc u_info;
  99. ret = INLINE_SYSCALL(sysarch, 2, I386_GET_FSBASE, &u_info);
  100. if (IS_ERR(ret))
  101. return NULL;
  102. u_info->entry_number = -1;
  103. u_info->base_addr = (unsigned int) addr;
  104. ret = INLINE_SYSCALL(sysarch, 2, I386_SET_FSBASE, &u_info);
  105. #else
  106. if (reg == PAL_SEGMENT_FS) {
  107. ret = INLINE_SYSCALL(sysarch, 2, AMD64_SET_FSBASE, &addr);
  108. } else if (reg == PAL_SEGMENT_GS) {
  109. ret = INLINE_SYSCALL(sysarch, 2, AMD64_SET_GSBASE, &addr);
  110. } else {
  111. return -PAL_ERROR_INVAL;
  112. }
  113. #endif
  114. if (IS_ERR(ret))
  115. return -PAL_ERROR_DENIED;
  116. return 0;
  117. }
  118. int _DkSegmentRegisterGet (int reg, void ** addr)
  119. {
  120. int ret;
  121. #if defined(__i386__)
  122. struct user_desc u_info;
  123. ret = INLINE_SYSCALL(sysarch, 2, I386_GET_FSBASE, &u_info);
  124. if (IS_ERR(ret))
  125. return -PAL_ERROR_DENIED;
  126. *addr = (void *) u_info->base_addr;
  127. #else
  128. unsigned long ret_addr;
  129. if (reg == PAL_SEGMENT_FS) {
  130. ret = INLINE_SYSCALL(sysarch, 2, AMD64_GET_FSBASE, &ret_addr);
  131. } else if (reg == PAL_SEGMENT_GS) {
  132. ret = INLINE_SYSCALL(sysarch, 2, AMD64_GET_GSBASE, &ret_addr);
  133. } else {
  134. return -PAL_ERROR_INVAL;
  135. }
  136. if (IS_ERR(ret))
  137. return -PAL_ERROR_DENIED;
  138. *addr = (void *) ret_addr;
  139. #endif
  140. return 0;
  141. }
  142. int _DkInstructionCacheFlush (const void * addr, int size)
  143. {
  144. return -PAL_ERROR_NOTIMPLEMENTED;
  145. }
  146. int _DkCpuIdRetrieve (unsigned int leaf, unsigned int subleaf,
  147. unsigned int values[4])
  148. {
  149. return -PAL_ERROR_NOTIMPLEMENTED;
  150. }