PageRenderTime 64ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/linux-user/thunk.c

https://gitlab.com/paelzer/qemu
C | 481 lines | 413 code | 38 blank | 30 comment | 68 complexity | d3ee8792d3d3f9f1d8b30e719848d73d MD5 | raw file
  1. /*
  2. * Generic thunking code to convert data between host and target CPU
  3. *
  4. * Copyright (c) 2003 Fabrice Bellard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "qemu/osdep.h"
  20. #include "qemu/log.h"
  21. #include "qemu.h"
  22. #include "exec/user/thunk.h"
  23. //#define DEBUG
  24. static unsigned int max_struct_entries;
  25. StructEntry *struct_entries;
  26. static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
  27. static inline const argtype *thunk_type_next(const argtype *type_ptr)
  28. {
  29. int type;
  30. type = *type_ptr++;
  31. switch(type) {
  32. case TYPE_CHAR:
  33. case TYPE_SHORT:
  34. case TYPE_INT:
  35. case TYPE_LONGLONG:
  36. case TYPE_ULONGLONG:
  37. case TYPE_LONG:
  38. case TYPE_ULONG:
  39. case TYPE_PTRVOID:
  40. case TYPE_OLDDEVT:
  41. return type_ptr;
  42. case TYPE_PTR:
  43. return thunk_type_next_ptr(type_ptr);
  44. case TYPE_ARRAY:
  45. return thunk_type_next_ptr(type_ptr + 1);
  46. case TYPE_STRUCT:
  47. return type_ptr + 1;
  48. default:
  49. return NULL;
  50. }
  51. }
  52. static const argtype *thunk_type_next_ptr(const argtype *type_ptr)
  53. {
  54. return thunk_type_next(type_ptr);
  55. }
  56. void thunk_register_struct(int id, const char *name, const argtype *types)
  57. {
  58. const argtype *type_ptr;
  59. StructEntry *se;
  60. int nb_fields, offset, max_align, align, size, i, j;
  61. assert(id < max_struct_entries);
  62. /* first we count the number of fields */
  63. type_ptr = types;
  64. nb_fields = 0;
  65. while (*type_ptr != TYPE_NULL) {
  66. type_ptr = thunk_type_next(type_ptr);
  67. nb_fields++;
  68. }
  69. assert(nb_fields > 0);
  70. se = struct_entries + id;
  71. se->field_types = types;
  72. se->nb_fields = nb_fields;
  73. se->name = name;
  74. #ifdef DEBUG
  75. printf("struct %s: id=%d nb_fields=%d\n",
  76. se->name, id, se->nb_fields);
  77. #endif
  78. /* now we can alloc the data */
  79. for (i = 0; i < ARRAY_SIZE(se->field_offsets); i++) {
  80. offset = 0;
  81. max_align = 1;
  82. se->field_offsets[i] = g_new(int, nb_fields);
  83. type_ptr = se->field_types;
  84. for(j = 0;j < nb_fields; j++) {
  85. size = thunk_type_size(type_ptr, i);
  86. align = thunk_type_align(type_ptr, i);
  87. offset = (offset + align - 1) & ~(align - 1);
  88. se->field_offsets[i][j] = offset;
  89. offset += size;
  90. if (align > max_align)
  91. max_align = align;
  92. type_ptr = thunk_type_next(type_ptr);
  93. }
  94. offset = (offset + max_align - 1) & ~(max_align - 1);
  95. se->size[i] = offset;
  96. se->align[i] = max_align;
  97. #ifdef DEBUG
  98. printf("%s: size=%d align=%d\n",
  99. i == THUNK_HOST ? "host" : "target", offset, max_align);
  100. #endif
  101. }
  102. }
  103. void thunk_register_struct_direct(int id, const char *name,
  104. const StructEntry *se1)
  105. {
  106. StructEntry *se;
  107. assert(id < max_struct_entries);
  108. se = struct_entries + id;
  109. *se = *se1;
  110. se->name = name;
  111. }
  112. /* now we can define the main conversion functions */
  113. const argtype *thunk_convert(void *dst, const void *src,
  114. const argtype *type_ptr, int to_host)
  115. {
  116. int type;
  117. type = *type_ptr++;
  118. switch(type) {
  119. case TYPE_CHAR:
  120. *(uint8_t *)dst = *(uint8_t *)src;
  121. break;
  122. case TYPE_SHORT:
  123. *(uint16_t *)dst = tswap16(*(uint16_t *)src);
  124. break;
  125. case TYPE_INT:
  126. *(uint32_t *)dst = tswap32(*(uint32_t *)src);
  127. break;
  128. case TYPE_LONGLONG:
  129. case TYPE_ULONGLONG:
  130. *(uint64_t *)dst = tswap64(*(uint64_t *)src);
  131. break;
  132. #if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
  133. case TYPE_LONG:
  134. case TYPE_ULONG:
  135. case TYPE_PTRVOID:
  136. *(uint32_t *)dst = tswap32(*(uint32_t *)src);
  137. break;
  138. #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
  139. case TYPE_LONG:
  140. case TYPE_ULONG:
  141. case TYPE_PTRVOID:
  142. if (to_host) {
  143. if (type == TYPE_LONG) {
  144. /* sign extension */
  145. *(uint64_t *)dst = (int32_t)tswap32(*(uint32_t *)src);
  146. } else {
  147. *(uint64_t *)dst = tswap32(*(uint32_t *)src);
  148. }
  149. } else {
  150. *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
  151. }
  152. break;
  153. #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
  154. case TYPE_LONG:
  155. case TYPE_ULONG:
  156. case TYPE_PTRVOID:
  157. *(uint64_t *)dst = tswap64(*(uint64_t *)src);
  158. break;
  159. #elif HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 64
  160. case TYPE_LONG:
  161. case TYPE_ULONG:
  162. case TYPE_PTRVOID:
  163. if (to_host) {
  164. *(uint32_t *)dst = tswap64(*(uint64_t *)src);
  165. } else {
  166. if (type == TYPE_LONG) {
  167. /* sign extension */
  168. *(uint64_t *)dst = tswap64(*(int32_t *)src);
  169. } else {
  170. *(uint64_t *)dst = tswap64(*(uint32_t *)src);
  171. }
  172. }
  173. break;
  174. #else
  175. #warning unsupported conversion
  176. #endif
  177. case TYPE_OLDDEVT:
  178. {
  179. uint64_t val = 0;
  180. switch (thunk_type_size(type_ptr - 1, !to_host)) {
  181. case 2:
  182. val = *(uint16_t *)src;
  183. break;
  184. case 4:
  185. val = *(uint32_t *)src;
  186. break;
  187. case 8:
  188. val = *(uint64_t *)src;
  189. break;
  190. }
  191. switch (thunk_type_size(type_ptr - 1, to_host)) {
  192. case 2:
  193. *(uint16_t *)dst = tswap16(val);
  194. break;
  195. case 4:
  196. *(uint32_t *)dst = tswap32(val);
  197. break;
  198. case 8:
  199. *(uint64_t *)dst = tswap64(val);
  200. break;
  201. }
  202. break;
  203. }
  204. case TYPE_ARRAY:
  205. {
  206. int array_length, i, dst_size, src_size;
  207. const uint8_t *s;
  208. uint8_t *d;
  209. array_length = *type_ptr++;
  210. dst_size = thunk_type_size(type_ptr, to_host);
  211. src_size = thunk_type_size(type_ptr, 1 - to_host);
  212. d = dst;
  213. s = src;
  214. for(i = 0;i < array_length; i++) {
  215. thunk_convert(d, s, type_ptr, to_host);
  216. d += dst_size;
  217. s += src_size;
  218. }
  219. type_ptr = thunk_type_next(type_ptr);
  220. }
  221. break;
  222. case TYPE_STRUCT:
  223. {
  224. int i;
  225. const StructEntry *se;
  226. const uint8_t *s;
  227. uint8_t *d;
  228. const argtype *field_types;
  229. const int *dst_offsets, *src_offsets;
  230. assert(*type_ptr < max_struct_entries);
  231. se = struct_entries + *type_ptr++;
  232. if (se->convert[0] != NULL) {
  233. /* specific conversion is needed */
  234. (*se->convert[to_host])(dst, src);
  235. } else {
  236. /* standard struct conversion */
  237. field_types = se->field_types;
  238. dst_offsets = se->field_offsets[to_host];
  239. src_offsets = se->field_offsets[1 - to_host];
  240. d = dst;
  241. s = src;
  242. for(i = 0;i < se->nb_fields; i++) {
  243. field_types = thunk_convert(d + dst_offsets[i],
  244. s + src_offsets[i],
  245. field_types, to_host);
  246. }
  247. }
  248. }
  249. break;
  250. default:
  251. fprintf(stderr, "Invalid type 0x%x\n", type);
  252. break;
  253. }
  254. return type_ptr;
  255. }
  256. const argtype *thunk_print(void *arg, const argtype *type_ptr)
  257. {
  258. int type;
  259. type = *type_ptr++;
  260. switch (type) {
  261. case TYPE_CHAR:
  262. qemu_log("%c", *(uint8_t *)arg);
  263. break;
  264. case TYPE_SHORT:
  265. qemu_log("%" PRId16, tswap16(*(uint16_t *)arg));
  266. break;
  267. case TYPE_INT:
  268. qemu_log("%" PRId32, tswap32(*(uint32_t *)arg));
  269. break;
  270. case TYPE_LONGLONG:
  271. qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
  272. break;
  273. case TYPE_ULONGLONG:
  274. qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
  275. break;
  276. #if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
  277. case TYPE_PTRVOID:
  278. qemu_log("0x%" PRIx32, tswap32(*(uint32_t *)arg));
  279. break;
  280. case TYPE_LONG:
  281. qemu_log("%" PRId32, tswap32(*(uint32_t *)arg));
  282. break;
  283. case TYPE_ULONG:
  284. qemu_log("%" PRIu32, tswap32(*(uint32_t *)arg));
  285. break;
  286. #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
  287. case TYPE_PTRVOID:
  288. qemu_log("0x%" PRIx32, tswap32(*(uint64_t *)arg & 0xffffffff));
  289. break;
  290. case TYPE_LONG:
  291. qemu_log("%" PRId32, tswap32(*(uint64_t *)arg & 0xffffffff));
  292. break;
  293. case TYPE_ULONG:
  294. qemu_log("%" PRIu32, tswap32(*(uint64_t *)arg & 0xffffffff));
  295. break;
  296. #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
  297. case TYPE_PTRVOID:
  298. qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg));
  299. break;
  300. case TYPE_LONG:
  301. qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
  302. break;
  303. case TYPE_ULONG:
  304. qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
  305. break;
  306. #else
  307. case TYPE_PTRVOID:
  308. qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg));
  309. break;
  310. case TYPE_LONG:
  311. qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
  312. break;
  313. case TYPE_ULONG:
  314. qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
  315. break;
  316. #endif
  317. case TYPE_OLDDEVT:
  318. {
  319. uint64_t val = 0;
  320. switch (thunk_type_size(type_ptr - 1, 1)) {
  321. case 2:
  322. val = *(uint16_t *)arg;
  323. break;
  324. case 4:
  325. val = *(uint32_t *)arg;
  326. break;
  327. case 8:
  328. val = *(uint64_t *)arg;
  329. break;
  330. }
  331. switch (thunk_type_size(type_ptr - 1, 0)) {
  332. case 2:
  333. qemu_log("%" PRIu16, tswap16(val));
  334. break;
  335. case 4:
  336. qemu_log("%" PRIu32, tswap32(val));
  337. break;
  338. case 8:
  339. qemu_log("%" PRIu64, tswap64(val));
  340. break;
  341. }
  342. }
  343. break;
  344. case TYPE_ARRAY:
  345. {
  346. int i, array_length, arg_size;
  347. uint8_t *a;
  348. int is_string = 0;
  349. array_length = *type_ptr++;
  350. arg_size = thunk_type_size(type_ptr, 0);
  351. a = arg;
  352. if (*type_ptr == TYPE_CHAR) {
  353. qemu_log("\"");
  354. is_string = 1;
  355. } else {
  356. qemu_log("[");
  357. }
  358. for (i = 0; i < array_length; i++) {
  359. if (i > 0 && !is_string) {
  360. qemu_log(",");
  361. }
  362. thunk_print(a, type_ptr);
  363. a += arg_size;
  364. }
  365. if (is_string) {
  366. qemu_log("\"");
  367. } else {
  368. qemu_log("]");
  369. }
  370. type_ptr = thunk_type_next(type_ptr);
  371. }
  372. break;
  373. case TYPE_STRUCT:
  374. {
  375. int i;
  376. const StructEntry *se;
  377. uint8_t *a;
  378. const argtype *field_types;
  379. const int *arg_offsets;
  380. se = struct_entries + *type_ptr++;
  381. if (se->print != NULL) {
  382. se->print(arg);
  383. } else {
  384. a = arg;
  385. field_types = se->field_types;
  386. arg_offsets = se->field_offsets[0];
  387. qemu_log("{");
  388. for (i = 0; i < se->nb_fields; i++) {
  389. if (i > 0) {
  390. qemu_log(",");
  391. }
  392. field_types = thunk_print(a + arg_offsets[i], field_types);
  393. }
  394. qemu_log("}");
  395. }
  396. }
  397. break;
  398. default:
  399. g_assert_not_reached();
  400. }
  401. return type_ptr;
  402. }
  403. /* from em86 */
  404. /* Utility function: Table-driven functions to translate bitmasks
  405. * between host and target formats
  406. */
  407. unsigned int target_to_host_bitmask(unsigned int target_mask,
  408. const bitmask_transtbl * trans_tbl)
  409. {
  410. const bitmask_transtbl *btp;
  411. unsigned int host_mask = 0;
  412. for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) {
  413. if ((target_mask & btp->target_mask) == btp->target_bits) {
  414. host_mask |= btp->host_bits;
  415. }
  416. }
  417. return host_mask;
  418. }
  419. unsigned int host_to_target_bitmask(unsigned int host_mask,
  420. const bitmask_transtbl * trans_tbl)
  421. {
  422. const bitmask_transtbl *btp;
  423. unsigned int target_mask = 0;
  424. for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) {
  425. if ((host_mask & btp->host_mask) == btp->host_bits) {
  426. target_mask |= btp->target_bits;
  427. }
  428. }
  429. return target_mask;
  430. }
  431. int thunk_type_size_array(const argtype *type_ptr, int is_host)
  432. {
  433. return thunk_type_size(type_ptr, is_host);
  434. }
  435. int thunk_type_align_array(const argtype *type_ptr, int is_host)
  436. {
  437. return thunk_type_align(type_ptr, is_host);
  438. }
  439. void thunk_init(unsigned int max_structs)
  440. {
  441. max_struct_entries = max_structs;
  442. struct_entries = g_new0(StructEntry, max_structs);
  443. }