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