qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio
at jcs-hda-dma 187 lines 5.0 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#ifndef THUNK_H 20#define THUNK_H 21 22#include "cpu.h" 23 24/* types enums definitions */ 25 26typedef enum argtype { 27 TYPE_NULL, 28 TYPE_CHAR, 29 TYPE_SHORT, 30 TYPE_INT, 31 TYPE_LONG, 32 TYPE_ULONG, 33 TYPE_PTRVOID, /* pointer on unknown data */ 34 TYPE_LONGLONG, 35 TYPE_ULONGLONG, 36 TYPE_PTR, 37 TYPE_ARRAY, 38 TYPE_STRUCT, 39 TYPE_OLDDEVT, 40} argtype; 41 42#define MK_PTR(type) TYPE_PTR, type 43#define MK_ARRAY(type, size) TYPE_ARRAY, size, type 44#define MK_STRUCT(id) TYPE_STRUCT, id 45 46#define THUNK_TARGET 0 47#define THUNK_HOST 1 48 49typedef struct { 50 /* standard struct handling */ 51 const argtype *field_types; 52 int nb_fields; 53 int *field_offsets[2]; 54 /* special handling */ 55 void (*convert[2])(void *dst, const void *src); 56 int size[2]; 57 int align[2]; 58 const char *name; 59} StructEntry; 60 61/* Translation table for bitmasks... */ 62typedef struct bitmask_transtbl { 63 unsigned int target_mask; 64 unsigned int target_bits; 65 unsigned int host_mask; 66 unsigned int host_bits; 67} bitmask_transtbl; 68 69void thunk_register_struct(int id, const char *name, const argtype *types); 70void thunk_register_struct_direct(int id, const char *name, 71 const StructEntry *se1); 72const argtype *thunk_convert(void *dst, const void *src, 73 const argtype *type_ptr, int to_host); 74 75extern StructEntry *struct_entries; 76 77int thunk_type_size_array(const argtype *type_ptr, int is_host); 78int thunk_type_align_array(const argtype *type_ptr, int is_host); 79 80static inline int thunk_type_size(const argtype *type_ptr, int is_host) 81{ 82 int type, size; 83 const StructEntry *se; 84 85 type = *type_ptr; 86 switch(type) { 87 case TYPE_CHAR: 88 return 1; 89 case TYPE_SHORT: 90 return 2; 91 case TYPE_INT: 92 return 4; 93 case TYPE_LONGLONG: 94 case TYPE_ULONGLONG: 95 return 8; 96 case TYPE_LONG: 97 case TYPE_ULONG: 98 case TYPE_PTRVOID: 99 case TYPE_PTR: 100 if (is_host) { 101 return sizeof(void *); 102 } else { 103 return TARGET_ABI_BITS / 8; 104 } 105 break; 106 case TYPE_OLDDEVT: 107 if (is_host) { 108#if defined(HOST_X86_64) 109 return 8; 110#elif defined(HOST_ALPHA) || defined(HOST_IA64) || defined(HOST_MIPS) || \ 111 defined(HOST_PARISC) || defined(HOST_SPARC64) 112 return 4; 113#elif defined(HOST_PPC) 114 return sizeof(void *); 115#else 116 return 2; 117#endif 118 } else { 119#if defined(TARGET_X86_64) 120 return 8; 121#elif defined(TARGET_ALPHA) || defined(TARGET_IA64) || defined(TARGET_MIPS) || \ 122 defined(TARGET_PARISC) || defined(TARGET_SPARC64) 123 return 4; 124#elif defined(TARGET_PPC) 125 return TARGET_ABI_BITS / 8; 126#else 127 return 2; 128#endif 129 } 130 break; 131 case TYPE_ARRAY: 132 size = type_ptr[1]; 133 return size * thunk_type_size_array(type_ptr + 2, is_host); 134 case TYPE_STRUCT: 135 se = struct_entries + type_ptr[1]; 136 return se->size[is_host]; 137 default: 138 return -1; 139 } 140} 141 142static inline int thunk_type_align(const argtype *type_ptr, int is_host) 143{ 144 int type; 145 const StructEntry *se; 146 147 type = *type_ptr; 148 switch(type) { 149 case TYPE_CHAR: 150 return 1; 151 case TYPE_SHORT: 152 return 2; 153 case TYPE_INT: 154 return 4; 155 case TYPE_LONGLONG: 156 case TYPE_ULONGLONG: 157 return 8; 158 case TYPE_LONG: 159 case TYPE_ULONG: 160 case TYPE_PTRVOID: 161 case TYPE_PTR: 162 if (is_host) { 163 return sizeof(void *); 164 } else { 165 return TARGET_ABI_BITS / 8; 166 } 167 break; 168 case TYPE_OLDDEVT: 169 return thunk_type_size(type_ptr, is_host); 170 case TYPE_ARRAY: 171 return thunk_type_align_array(type_ptr + 2, is_host); 172 case TYPE_STRUCT: 173 se = struct_entries + type_ptr[1]; 174 return se->align[is_host]; 175 default: 176 return -1; 177 } 178} 179 180unsigned int target_to_host_bitmask(unsigned int target_mask, 181 const bitmask_transtbl * trans_tbl); 182unsigned int host_to_target_bitmask(unsigned int host_mask, 183 const bitmask_transtbl * trans_tbl); 184 185void thunk_init(unsigned int max_structs); 186 187#endif