qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

hw/nvram/fw_cfg: Add the FW_CFG_DATA_GENERATOR interface

The FW_CFG_DATA_GENERATOR allows any object to produce
blob of data consumable by the fw_cfg device.

Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20200623172726.21040-3-philmd@redhat.com>

+86 -1
+8 -1
docs/specs/fw_cfg.txt
··· 219 219 220 220 = Externally Provided Items = 221 221 222 - As of v2.4, "file" fw_cfg items (i.e., items with selector keys above 222 + Since v2.4, "file" fw_cfg items (i.e., items with selector keys above 223 223 FW_CFG_FILE_FIRST, and with a corresponding entry in the fw_cfg file 224 224 directory structure) may be inserted via the QEMU command line, using 225 225 the following syntax: ··· 229 229 Or 230 230 231 231 -fw_cfg [name=]<item_name>,string=<string> 232 + 233 + Since v5.1, QEMU allows some objects to generate fw_cfg-specific content, 234 + the content is then associated with a "file" item using the 'gen_id' option 235 + in the command line, using the following syntax: 236 + 237 + -object <generator-type>,id=<generated_id>,[generator-specific-options] \ 238 + -fw_cfg [name=]<item_name>,gen_id=<generated_id> 232 239 233 240 See QEMU man page for more documentation. 234 241
+35
hw/nvram/fw_cfg.c
··· 1032 1032 return NULL; 1033 1033 } 1034 1034 1035 + void fw_cfg_add_from_generator(FWCfgState *s, const char *filename, 1036 + const char *gen_id, Error **errp) 1037 + { 1038 + FWCfgDataGeneratorClass *klass; 1039 + Error *local_err = NULL; 1040 + GByteArray *array; 1041 + Object *obj; 1042 + gsize size; 1043 + 1044 + obj = object_resolve_path_component(object_get_objects_root(), gen_id); 1045 + if (!obj) { 1046 + error_setg(errp, "Cannot find object ID '%s'", gen_id); 1047 + return; 1048 + } 1049 + if (!object_dynamic_cast(obj, TYPE_FW_CFG_DATA_GENERATOR_INTERFACE)) { 1050 + error_setg(errp, "Object ID '%s' is not a '%s' subclass", 1051 + gen_id, TYPE_FW_CFG_DATA_GENERATOR_INTERFACE); 1052 + return; 1053 + } 1054 + klass = FW_CFG_DATA_GENERATOR_GET_CLASS(obj); 1055 + array = klass->get_data(obj, &local_err); 1056 + if (local_err) { 1057 + error_propagate(errp, local_err); 1058 + return; 1059 + } 1060 + size = array->len; 1061 + fw_cfg_add_file(s, filename, g_byte_array_free(array, TRUE), size); 1062 + } 1063 + 1035 1064 static void fw_cfg_machine_reset(void *opaque) 1036 1065 { 1037 1066 MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); ··· 1333 1362 .class_init = fw_cfg_mem_class_init, 1334 1363 }; 1335 1364 1365 + static const TypeInfo fw_cfg_data_generator_interface_info = { 1366 + .parent = TYPE_INTERFACE, 1367 + .name = TYPE_FW_CFG_DATA_GENERATOR_INTERFACE, 1368 + .class_size = sizeof(FWCfgDataGeneratorClass), 1369 + }; 1336 1370 1337 1371 static void fw_cfg_register_types(void) 1338 1372 { 1339 1373 type_register_static(&fw_cfg_info); 1340 1374 type_register_static(&fw_cfg_io_info); 1341 1375 type_register_static(&fw_cfg_mem_info); 1376 + type_register_static(&fw_cfg_data_generator_interface_info); 1342 1377 } 1343 1378 1344 1379 type_init(fw_cfg_register_types)
+43
include/hw/nvram/fw_cfg.h
··· 9 9 #define TYPE_FW_CFG "fw_cfg" 10 10 #define TYPE_FW_CFG_IO "fw_cfg_io" 11 11 #define TYPE_FW_CFG_MEM "fw_cfg_mem" 12 + #define TYPE_FW_CFG_DATA_GENERATOR_INTERFACE "fw_cfg-data-generator" 12 13 13 14 #define FW_CFG(obj) OBJECT_CHECK(FWCfgState, (obj), TYPE_FW_CFG) 14 15 #define FW_CFG_IO(obj) OBJECT_CHECK(FWCfgIoState, (obj), TYPE_FW_CFG_IO) 15 16 #define FW_CFG_MEM(obj) OBJECT_CHECK(FWCfgMemState, (obj), TYPE_FW_CFG_MEM) 17 + 18 + #define FW_CFG_DATA_GENERATOR_CLASS(class) \ 19 + OBJECT_CLASS_CHECK(FWCfgDataGeneratorClass, (class), \ 20 + TYPE_FW_CFG_DATA_GENERATOR_INTERFACE) 21 + #define FW_CFG_DATA_GENERATOR_GET_CLASS(obj) \ 22 + OBJECT_GET_CLASS(FWCfgDataGeneratorClass, (obj), \ 23 + TYPE_FW_CFG_DATA_GENERATOR_INTERFACE) 24 + 25 + typedef struct FWCfgDataGeneratorClass { 26 + /*< private >*/ 27 + InterfaceClass parent_class; 28 + /*< public >*/ 29 + 30 + /** 31 + * get_data: 32 + * @obj: the object implementing this interface 33 + * @errp: pointer to a NULL-initialized error object 34 + * 35 + * Returns: reference to a byte array containing the data. 36 + * The caller should release the reference when no longer 37 + * required. 38 + */ 39 + GByteArray *(*get_data)(Object *obj, Error **errp); 40 + } FWCfgDataGeneratorClass; 16 41 17 42 typedef struct fw_cfg_file FWCfgFile; 18 43 ··· 262 287 */ 263 288 void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data, 264 289 size_t len); 290 + 291 + /** 292 + * fw_cfg_add_from_generator: 293 + * @s: fw_cfg device being modified 294 + * @filename: name of new fw_cfg file item 295 + * @gen_id: name of object implementing FW_CFG_DATA_GENERATOR interface 296 + * @errp: pointer to a NULL initialized error object 297 + * 298 + * Add a new NAMED fw_cfg item with the content generated from the 299 + * @gen_id object. The data generated by the @gen_id object is copied 300 + * into the data structure of the fw_cfg device. 301 + * The next available (unused) selector key starting at FW_CFG_FILE_FIRST 302 + * will be used; also, a new entry will be added to the file directory 303 + * structure residing at key value FW_CFG_FILE_DIR, containing the item name, 304 + * data size, and assigned selector key value. 305 + */ 306 + void fw_cfg_add_from_generator(FWCfgState *s, const char *filename, 307 + const char *gen_id, Error **errp); 265 308 266 309 FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase, 267 310 AddressSpace *dma_as);