pal_internal.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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 OSCAR lab, 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 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 General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * pal_internal.h
  17. *
  18. * This file contains definition of functions, variables and data structures
  19. * for internal uses.
  20. */
  21. #ifndef PAL_INTERNAL_H
  22. #define PAL_INTERNAL_H
  23. #include "pal_defs.h"
  24. #include "pal.h"
  25. #include "atomic.h"
  26. #ifndef IN_PAL
  27. # error "pal_internal.h can only be included in PAL"
  28. #endif
  29. /* handle_ops is the operators provided for each handler type. They are
  30. mostly used by Stream-related PAL calls, but can also be used by
  31. some others in special ways. */
  32. struct handle_ops {
  33. /* 'getrealpath' return the real path that represent the handle */
  34. const char * (*getrealpath) (PAL_HANDLE handle);
  35. /* 'getname' is used by DkStreamGetName. It's different from
  36. 'getrealpath' */
  37. int (*getname) (PAL_HANDLE handle, char * buffer, int count);
  38. /* 'open' is used by DkStreamOpen. 'handle' is a preallocated handle,
  39. 'type' will be a normalized prefix, 'uri' is the remaining string
  40. of uri */
  41. int (*open) (PAL_HANDLE * handle, const char * type, const char * uri,
  42. int access, int share, int create, int options);
  43. /* 'read' and 'write' is used by DkStreamRead and DkStreamWrite, so
  44. they have exactly same prototype as them. */
  45. int (*read) (PAL_HANDLE handle, int offset, int count, void * buffer);
  46. int (*write) (PAL_HANDLE handle, int offset, int count,
  47. const void * buffer);
  48. /* 'readbyaddr' and 'writebyaddr' are the same as read and write,
  49. but with extra field to specify address */
  50. int (*readbyaddr) (PAL_HANDLE handle, int offset, int count, void * buffer,
  51. char * addr, int addrlen);
  52. int (*writebyaddr) (PAL_HANDLE handle, int offset, int count,
  53. const void * buffer, const char * addr, int addrlen);
  54. /* 'close' and 'delete' is used by DkObjectClose and DkStreamDelete,
  55. 'close' will close the stream, while 'delete' actually destroy
  56. the stream, such as deleting a file or shutting down a socket */
  57. int (*close) (PAL_HANDLE handle);
  58. int (*delete) (PAL_HANDLE handle, int access);
  59. /* 'map' and 'unmap' will map or unmap the handle into memory space,
  60. it's not necessary mapped by mmap, so unmap also needs 'handle'
  61. to deal with special cases */
  62. int (*map) (PAL_HANDLE handle, void ** address, int prot, int offset,
  63. int size);
  64. /* 'setlength' is used by DkStreamFlush. It truncate the stream
  65. to certain size. */
  66. int (*setlength) (PAL_HANDLE handle, int length);
  67. /* 'flush' is used by DkStreamFlush. It syncs the stream to the device */
  68. int (*flush) (PAL_HANDLE handle);
  69. /* 'waitforclient' is used by DkStreamWaitforClient. It accepts an
  70. connection */
  71. int (*waitforclient) (PAL_HANDLE server, PAL_HANDLE *client);
  72. /* 'attrquery' is used by DkStreamAttributesQuery. It queries the
  73. attributes of a stream */
  74. int (*attrquery) (const char * type, const char * uri,
  75. PAL_STREAM_ATTR * attr);
  76. /* 'attrquerybyhdl' is used by DkStreamAttributesQuerybyHandle. It queries
  77. the attributes of a stream handle */
  78. int (*attrquerybyhdl) (PAL_HANDLE handle, PAL_STREAM_ATTR * attr);
  79. /* 'attrsetbyhdl' is used by DkStreamAttributesSetbyHandle. It queries
  80. the attributes of a stream handle */
  81. int (*attrsetbyhdl) (PAL_HANDLE handle, PAL_STREAM_ATTR * attr);
  82. /* 'wait' is used for synchronous wait */
  83. int (*wait) (PAL_HANDLE handle, int time);
  84. /* 'rename' is used to change name of a stream, or reset its share
  85. option */
  86. int (*rename) (PAL_HANDLE handle, const char * type, const char * uri);
  87. };
  88. extern const struct handle_ops * pal_handle_ops [];
  89. #define HANDLE_OPS(handle) \
  90. ({ int _type = HANDLE_TYPE(handle); \
  91. (_type <= 0 || _type >= PAL_HANDLE_TYPE_BOUND) ? \
  92. NULL : pal_handle_ops[_type]; \
  93. })
  94. /* interger hash functions defined inline. The algorithm we used here
  95. is based on Robert Jenkins developed in 96', the algorithm has two
  96. version, 32-bit one and 64-bit one. */
  97. static inline uint32_t hash32 (uint32_t key)
  98. {
  99. key = ~key + (key << 15);
  100. key = key ^ (key >> 12);
  101. key = key + (key << 2);
  102. key = key ^ (key >> 4);
  103. key = (key + (key << 3)) + (key << 11);
  104. key = key ^ (key >> 16);
  105. return key;
  106. }
  107. static inline uint64_t hash64 (uint64_t key)
  108. {
  109. key = (~key) + (key << 21);
  110. key = key ^ (key >> 24);
  111. key = (key + (key << 3)) + (key << 8);
  112. key = key ^ (key >> 14);
  113. key = (key + (key << 2)) + (key << 4);
  114. key = key ^ (key >> 28);
  115. key = key + (key << 31);
  116. return key;
  117. }
  118. /* We allow dynamic size handle allocation. Here is some macro to help
  119. deciding the actual size of the handle */
  120. #define HANDLE_SIZE(type) ({ PAL_HANDLE _h; sizeof(_h->type); })
  121. #define UNKNOWN_HANDLE(handle) \
  122. (HANDLE_TYPE(handle) == 0 || HANDLE_TYPE(handle) >= PAL_HANDLE_TYPE_BOUND)
  123. static inline int handle_size (PAL_HANDLE handle)
  124. {
  125. static int handle_sizes[PAL_HANDLE_TYPE_BOUND]
  126. = { 0,
  127. sizeof(handle->file),
  128. sizeof(handle->pipe),
  129. sizeof(handle->pipe),
  130. sizeof(handle->pipe),
  131. sizeof(handle->pipeprv),
  132. sizeof(handle->dev),
  133. sizeof(handle->dir),
  134. sizeof(handle->sock),
  135. sizeof(handle->sock),
  136. sizeof(handle->sock),
  137. sizeof(handle->sock),
  138. sizeof(handle->process),
  139. sizeof(handle->mcast),
  140. sizeof(handle->thread),
  141. sizeof(handle->semaphore),
  142. sizeof(handle->event),
  143. sizeof(handle->gipc),
  144. };
  145. if (UNKNOWN_HANDLE(handle))
  146. return 0;
  147. else
  148. return handle_sizes[HANDLE_TYPE(handle)];
  149. }
  150. #ifdef __x86_64__
  151. # ifdef OMIT_FRAME_POINTER
  152. # define store_stack(rsp) \
  153. void * rsp; \
  154. do { \
  155. asm volatile ("movq %%rsp, %0\r\n" \
  156. : "=g"(rsp) :: "memory"); \
  157. } while(0)
  158. # else
  159. # define store_stack(rsp, rbp) \
  160. void * rsp, * rbp; \
  161. do { \
  162. asm volatile ("movq %%rsp, %0\r\n" \
  163. "movq %%rbp, %1\r\n" \
  164. : "=g"(rsp), "=g"(rbp) :: "memory"); \
  165. } while(0)
  166. # endif
  167. struct arch_frame {
  168. unsigned long rsp, rbp, rbx, rsi, rdi, r12, r13, r14, r15;
  169. };
  170. # define store_register(reg, var) \
  171. asm volatile ("movq %%" #reg ", %0" : "=g" (var) :: "memory");
  172. # define store_register_in_frame(reg, f) store_register(reg, (f)->reg)
  173. # define arch_store_frame(f) \
  174. store_register_in_frame(rsp, f) \
  175. store_register_in_frame(rbp, f) \
  176. store_register_in_frame(rbx, f) \
  177. store_register_in_frame(rsi, f) \
  178. store_register_in_frame(rdi, f) \
  179. store_register_in_frame(r12, f) \
  180. store_register_in_frame(r13, f) \
  181. store_register_in_frame(r14, f) \
  182. store_register_in_frame(r15, f)
  183. # define restore_register(reg, var, clobber...) \
  184. asm volatile ("movq %0, %%" #reg :: "g" (var) : "memory", ##clobber);
  185. # define restore_register_in_frame(reg, f) \
  186. restore_register(reg, (f)->reg, \
  187. "r15", "r14", "r13", "r12", "rdi", "rsi", "rbx")
  188. # define arch_restore_frame(f) \
  189. restore_register_in_frame(r15, f) \
  190. restore_register_in_frame(r14, f) \
  191. restore_register_in_frame(r13, f) \
  192. restore_register_in_frame(r12, f) \
  193. restore_register_in_frame(rdi, f) \
  194. restore_register_in_frame(rsi, f) \
  195. restore_register_in_frame(rbx, f) \
  196. restore_register_in_frame(rbp, f) \
  197. restore_register_in_frame(rsp, f)
  198. #endif /* __x86_64__ */
  199. struct pal_frame {
  200. volatile struct pal_frame * self;
  201. void * func;
  202. const char * funcname;
  203. struct arch_frame arch;
  204. PAL_CONTEXT * context;
  205. unsigned long * retval;
  206. };
  207. static inline
  208. void __store_frame (struct pal_frame * frame,
  209. void * func, const char * funcname)
  210. {
  211. frame->self = frame;
  212. frame->func = func;
  213. frame->funcname = funcname;
  214. frame->context = NULL;
  215. frame->retval = NULL;
  216. arch_store_frame(&frame->arch)
  217. }
  218. #define store_frame(f) \
  219. struct pal_frame frame; \
  220. __store_frame(&frame, &Dk##f, "Dk" #f)
  221. /* failure notify. The rountine is called whenever a PAL call return
  222. error code. As the current design of PAL does not return error
  223. code directly, we rely on DkAsynchronousEventUpcall to handle
  224. PAL call error. If the user does not set up a upcall, the error
  225. code will be ignored. Ignoring PAL error code can be a possible
  226. optimization for SHIM. */
  227. void notify_failure (unsigned long error);
  228. #include <sigset.h>
  229. /* all pal config value */
  230. extern struct pal_config {
  231. const char * manifest;
  232. const char * exec;
  233. PAL_HANDLE manifest_handle;
  234. PAL_HANDLE exec_handle;
  235. struct config_store * root_config;
  236. unsigned long pagesize;
  237. unsigned long alloc_align;
  238. bool daemonize;
  239. void * user_addr_start, * user_addr_end;
  240. void * lib_text_start, * lib_text_end;
  241. void * lib_data_start, * lib_data_end;
  242. PAL_HANDLE console_output;
  243. const char * syscall_sym_name;
  244. void * syscall_sym_addr;
  245. } pal_config;
  246. #define BREAK() \
  247. do { \
  248. asm volatile ("int $3"); \
  249. } while (0)
  250. extern PAL_CONTROL __pal_control;
  251. extern void * text_start, * text_end;
  252. extern void * data_start, * data_end;
  253. /* constants and macros to help rounding addresses to page
  254. boundaries */
  255. extern unsigned long allocsize, allocshift, allocmask;
  256. #define ALLOC_ALIGNDOWN(addr) \
  257. ({ \
  258. assert(allocsize && allocshift && allocmask); \
  259. ((unsigned long) (addr)) & allocmask; \
  260. })
  261. #define ALLOC_ALIGNUP(addr) \
  262. ({ \
  263. assert(allocsize && allocshift && allocmask); \
  264. (((unsigned long) (addr)) + allocshift) & allocmask; \
  265. })
  266. #define ALLOC_ALIGNED(addr) \
  267. ({ \
  268. assert(allocsize && allocshift && allocmask); \
  269. (unsigned long) (addr) == \
  270. (((unsigned long) (addr)) & allocmask); \
  271. })
  272. /* For initialization */
  273. void pal_main (int argc, const char ** argv, const char ** envp);
  274. unsigned long _DkGetPagesize (void);
  275. unsigned long _DkGetAllocationAlignment (void);
  276. int _DkInitHost (int * pargc, const char *** pargv);
  277. #include <atomic.h>
  278. int _DkInternalLock (PAL_LOCK * mut);
  279. int _DkInternalUnlock (PAL_LOCK * mut);
  280. /* Internal DK calls, in case any of the internal routines needs to use them */
  281. /* DkStream calls */
  282. int _DkStreamOpen (PAL_HANDLE * handle, const char * uri,
  283. int access, int share, int create, int options);
  284. int _DkStreamDelete (PAL_HANDLE handle, int access);
  285. int _DkStreamRead (PAL_HANDLE handle, int offset, int count, void * buf,
  286. char * addr, int addrlen);
  287. int _DkStreamWrite (PAL_HANDLE handle, int offset, int count,
  288. const void * buf, const char * addr, int addrlen);
  289. int _DkStreamAttributesQuery (const char * uri, PAL_STREAM_ATTR * attr);
  290. int _DkStreamAttributesQuerybyHandle (PAL_HANDLE hdl, PAL_STREAM_ATTR * attr);
  291. int _DkStreamMap (PAL_HANDLE handle, void ** addr, int prot, int offset,
  292. size_t size);
  293. int _DkStreamUnmap (void * addr, size_t size);
  294. int _DkStreamSetLength (PAL_HANDLE handle, size_t length);
  295. int _DkStreamFlush (PAL_HANDLE handle);
  296. const char * _DkStreamRealpath (PAL_HANDLE hdl);
  297. int _DkSendHandle(PAL_HANDLE hdl, PAL_HANDLE cargo);
  298. int _DkReceiveHandle(PAL_HANDLE hdl, PAL_HANDLE cargo);
  299. PAL_HANDLE _DkBroadcastStreamOpen (int port);
  300. /* DkProcess and DkThread calls */
  301. int _DkThreadCreate (PAL_HANDLE * handle, int (*callback) (void *),
  302. const void * parem, int flags);
  303. void * _DkThreadPrivate (void * addr);
  304. void _DkThreadExit (int exitcode);
  305. int _DkThreadDelayExecution (unsigned long * duration);
  306. void _DkThreadYieldExecution (void);
  307. int _DkThreadResume (PAL_HANDLE threadHandle);
  308. int _DkProcessCreate (PAL_HANDLE * handle, const char * uri,
  309. int flags, const char ** args);
  310. void _DkProcessExit (int exitCode);
  311. int _DkProcessSandboxCreate (const char * manifest, int flags);
  312. /* DkSemaphore calls */
  313. int _DkSemaphoreCreate (PAL_HANDLE handle, int initialCount, int maxCount);
  314. void _DkSemaphoreDestroy (PAL_HANDLE semaphoreHandle);
  315. int _DkSemaphoreAcquire (PAL_HANDLE sem, int count);
  316. int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, int timeout);
  317. void _DkSemaphoreRelease (PAL_HANDLE sem, int count);
  318. int _DkSemaphoreGetCurrentCount (PAL_HANDLE sem);
  319. /* DkEvent calls */
  320. int _DkEventCreate (PAL_HANDLE * event, bool initialState,
  321. bool isnotification);
  322. void _DkEventDestroy (PAL_HANDLE handle);
  323. int _DkEventSet (PAL_HANDLE event);
  324. int _DkEventWaitTimeout (PAL_HANDLE event, int timeout);
  325. int _DkEventWait (PAL_HANDLE event);
  326. int _DkEventClear (PAL_HANDLE event);
  327. /* DkVirtualMemory calls */
  328. int _DkVirtualMemoryAlloc (void ** paddr, size_t size, int alloc_type,
  329. int prot);
  330. int _DkVirtualMemoryFree (void * addr, size_t size);
  331. int _DkVirtualMemoryProtect (void * addr, size_t size, int prot);
  332. /* DkObject calls */
  333. int _DkObjectReference (PAL_HANDLE objectHandle);
  334. int _DkObjectClose (PAL_HANDLE objectHandle);
  335. int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
  336. PAL_HANDLE * polled);
  337. /* DkException calls & structures */
  338. typedef void (*PAL_UPCALL) (PAL_PTR, PAL_NUM, PAL_CONTEXT *);
  339. int (*_DkExceptionHandlers[PAL_EVENT_NUM_BOUND]) (int, PAL_UPCALL, int);
  340. void _DkExceptionReturn (const void * event);
  341. /* other DK calls */
  342. unsigned long _DkSystemTimeQuery (void);
  343. int _DkRandomBitsRead (void * buffer, int size);
  344. int _DkInstructionCacheFlush (const void * addr, size_t size);
  345. int _DkCreatePhysicalMemoryChannel (PAL_HANDLE * handle, unsigned long * key);
  346. int _DkPhysicalMemoryCommit (PAL_HANDLE channel, int entries, void ** addrs,
  347. unsigned long * sizes, int flags);
  348. int _DkPhysicalMemoryMap (PAL_HANDLE channel, int entries, void ** addrs,
  349. unsigned long * sizes, unsigned int * prots);
  350. /* To setup the system-wise signal handlers, including SIGKILL, SIGTERM,
  351. * SIGINT, SIGUSR1, etc */
  352. int signal_setup (void);
  353. /* random number generator: initialization and fetching */
  354. int getrand (void * buffer, int size);
  355. /* blocking and unblocking signals */
  356. int block_signals (int * sigs, int nsig);
  357. int unblock_signals (int * sigs, int nsig);
  358. void * find_address (void * addr);
  359. /* function and definition for loading binaries */
  360. enum object_type { OBJECT_RTLD, OBJECT_EXEC, OBJECT_PRELOAD, OBJECT_EXTERNAL };
  361. int check_elf_object (PAL_HANDLE handle);
  362. int load_elf_object (const char * uri, enum object_type type);
  363. int load_elf_object_by_handle (PAL_HANDLE handle, enum object_type type);
  364. void init_slab_mgr (void);
  365. void * malloc (int size);
  366. void * remalloc (const void * mem, int size);
  367. void * calloc (int nmem, int size);
  368. void free (void * mem);
  369. #define attribute_hidden __attribute__ ((visibility ("hidden")))
  370. #define alias_str(name) #name
  371. #define extern_alias(name) \
  372. extern __typeof(name) pal_##name __attribute ((alias (alias_str(name))))
  373. void _DkPrintConsole (const void * buf, int size);
  374. int printf (const char *fmt, ...);
  375. int snprintf (char * buf, size_t n, const char * fmt, ...);
  376. #endif