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

Merge remote-tracking branch 'remotes/kraxel/tags/modules-20200707-pull-request' into staging

qom: add support for qom objects in modules.
build some devices (qxl, virtio-gpu, ccid, usb-redir) as modules.
build braille chardev as module.

v2: more verbose comment for "build: fix device module builds" patch.

note: qemu doesn't rebuild objects on cflags changes (specifically
-fPIC being added when code is switched from builtin to module).
Workaround for resulting build errors: "make clean", rebuild.

# gpg: Signature made Tue 07 Jul 2020 14:42:16 BST
# gpg: using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/modules-20200707-pull-request:
chardev: enable modules, use for braille
vga: build virtio-gpu as module
vga: build virtio-gpu only once
vga: build qxl as module
usb: build usb-redir as module
ccid: build smartcard as module
build: fix device module builds
qdev: device module support
object: qom module support
module: qom module support

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+155 -24
+2
Makefile.objs
··· 59 59 common-obj-y += audio/ 60 60 common-obj-m += audio/ 61 61 common-obj-y += hw/ 62 + common-obj-m += hw/ 62 63 63 64 common-obj-y += replay/ 64 65 ··· 70 71 71 72 common-obj-y += backends/ 72 73 common-obj-y += chardev/ 74 + common-obj-m += chardev/ 73 75 74 76 common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o 75 77 qemu-seccomp.o-cflags := $(SECCOMP_CFLAGS)
+14
Makefile.target
··· 179 179 dummy := $(call unnest-vars,,obj-y) 180 180 all-obj-y := $(obj-y) 181 181 182 + # 183 + # common-obj-m has some crap here, probably as side effect from 184 + # unnest-vars recursing into target directories to fill obj-y and not 185 + # properly handling the -m case. 186 + # 187 + # Clear common-obj-m as workaround. Fixes suspious dependency errors 188 + # when building devices as modules. A bit hackish, but should be ok 189 + # as long as we do not have any target-specific modules. 190 + # 191 + # The meson-based build system currently in development doesn't need 192 + # unnest-vars and will obsolete this workaround. 193 + # 194 + common-obj-m := 195 + 182 196 include $(SRC_PATH)/Makefile.objs 183 197 dummy := $(call unnest-vars,.., \ 184 198 authz-obj-y \
+4 -1
chardev/Makefile.objs
··· 18 18 chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o 19 19 20 20 common-obj-y += msmouse.o wctablet.o testdev.o 21 - common-obj-$(CONFIG_BRLAPI) += baum.o 21 + 22 + ifeq ($(CONFIG_BRLAPI),y) 23 + common-obj-m += baum.o 22 24 baum.o-cflags := $(SDL_CFLAGS) 23 25 baum.o-libs := $(BRLAPI_LIBS) 26 + endif 24 27 25 28 common-obj-$(CONFIG_SPICE) += spice.o
+1 -1
chardev/char.c
··· 527 527 const ChardevClass *cc; 528 528 char *typename = g_strdup_printf("chardev-%s", driver); 529 529 530 - oc = object_class_by_name(typename); 530 + oc = module_object_class_by_name(typename); 531 531 g_free(typename); 532 532 533 533 if (!object_class_dynamic_cast(oc, TYPE_CHARDEV)) {
+2
hw/Makefile.objs
··· 43 43 endif 44 44 45 45 common-obj-y += $(devices-dirs-y) 46 + common-obj-m += display/ 47 + common-obj-m += usb/ 46 48 obj-y += $(devices-dirs-y)
+4 -2
hw/core/qdev.c
··· 137 137 */ 138 138 DeviceState *qdev_new(const char *name) 139 139 { 140 + if (!object_class_by_name(name)) { 141 + module_load_qom_one(name); 142 + } 140 143 return DEVICE(object_new(name)); 141 144 } 142 145 ··· 147 150 */ 148 151 DeviceState *qdev_try_new(const char *name) 149 152 { 150 - if (!object_class_by_name(name)) { 153 + if (!module_object_class_by_name(name)) { 151 154 return NULL; 152 155 } 153 - 154 156 return DEVICE(object_new(name)); 155 157 } 156 158
+17 -11
hw/display/Makefile.objs
··· 44 44 45 45 obj-$(CONFIG_VGA) += vga.o 46 46 47 - common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o 47 + ifeq ($(CONFIG_QXL),y) 48 + common-obj-m += qxl.mo 49 + qxl.mo-objs = qxl.o qxl-logger.o qxl-render.o 50 + endif 48 51 49 - obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu-base.o virtio-gpu.o virtio-gpu-3d.o 50 - obj-$(CONFIG_VHOST_USER_GPU) += vhost-user-gpu.o 51 - obj-$(call land,$(CONFIG_VIRTIO_GPU),$(CONFIG_VIRTIO_PCI)) += virtio-gpu-pci.o 52 - obj-$(call land,$(CONFIG_VHOST_USER_GPU),$(CONFIG_VIRTIO_PCI)) += vhost-user-gpu-pci.o 53 - obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o 54 - obj-$(CONFIG_VHOST_USER_VGA) += vhost-user-vga.o 55 - virtio-gpu.o-cflags := $(VIRGL_CFLAGS) 56 - virtio-gpu.o-libs += $(VIRGL_LIBS) 57 - virtio-gpu-3d.o-cflags := $(VIRGL_CFLAGS) 58 - virtio-gpu-3d.o-libs += $(VIRGL_LIBS) 52 + ifeq ($(CONFIG_VIRTIO_GPU),y) 53 + common-obj-m += virtio-gpu.mo 54 + virtio-gpu-obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu-base.o virtio-gpu.o virtio-gpu-3d.o 55 + virtio-gpu-obj-$(CONFIG_VHOST_USER_GPU) += vhost-user-gpu.o 56 + virtio-gpu-obj-$(call land,$(CONFIG_VIRTIO_GPU),$(CONFIG_VIRTIO_PCI)) += virtio-gpu-pci.o 57 + virtio-gpu-obj-$(call land,$(CONFIG_VHOST_USER_GPU),$(CONFIG_VIRTIO_PCI)) += vhost-user-gpu-pci.o 58 + virtio-gpu-obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o 59 + virtio-gpu-obj-$(CONFIG_VHOST_USER_VGA) += vhost-user-vga.o 60 + virtio-gpu.mo-objs := $(virtio-gpu-obj-y) 61 + virtio-gpu.mo-cflags := $(VIRGL_CFLAGS) 62 + virtio-gpu.mo-libs := $(VIRGL_LIBS) 63 + endif 64 + 59 65 common-obj-$(CONFIG_DPCD) += dpcd.o 60 66 common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx_dp.o 61 67
+9 -4
hw/usb/Makefile.objs
··· 29 29 30 30 ifeq ($(CONFIG_USB_SMARTCARD),y) 31 31 common-obj-y += dev-smartcard-reader.o 32 - common-obj-$(CONFIG_SMARTCARD) += smartcard.mo 32 + ifeq ($(CONFIG_SMARTCARD),y) 33 + common-obj-m += smartcard.mo 33 34 smartcard.mo-objs := ccid-card-passthru.o ccid-card-emulated.o 34 35 smartcard.mo-cflags := $(SMARTCARD_CFLAGS) 35 36 smartcard.mo-libs := $(SMARTCARD_LIBS) 37 + endif 36 38 endif 37 39 38 40 ifeq ($(CONFIG_POSIX),y) ··· 41 43 42 44 # usb redirection 43 45 ifeq ($(CONFIG_USB),y) 44 - common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o 45 - redirect.o-cflags = $(USB_REDIR_CFLAGS) 46 - redirect.o-libs = $(USB_REDIR_LIBS) 46 + ifeq ($(CONFIG_USB_REDIR),y) 47 + common-obj-m += redirect.mo 48 + redirect.mo-objs = redirect.o quirks.o 49 + redirect.mo-cflags = $(USB_REDIR_CFLAGS) 50 + redirect.mo-libs = $(USB_REDIR_LIBS) 51 + endif 47 52 endif 48 53 49 54 # usb pass-through
+2
include/qemu/module.h
··· 70 70 71 71 void module_call_init(module_init_type type); 72 72 bool module_load_one(const char *prefix, const char *lib_name); 73 + void module_load_qom_one(const char *type); 74 + void module_load_qom_all(void); 73 75 74 76 #endif
+12
include/qom/object.h
··· 994 994 */ 995 995 ObjectClass *object_class_by_name(const char *typename); 996 996 997 + /** 998 + * module_object_class_by_name: 999 + * @typename: The QOM typename to obtain the class for. 1000 + * 1001 + * For objects which might be provided by a module. Behaves like 1002 + * object_class_by_name, but additionally tries to load the module 1003 + * needed in case the class is not available. 1004 + * 1005 + * Returns: The class for @typename or %NULL if not found. 1006 + */ 1007 + ObjectClass *module_object_class_by_name(const char *typename); 1008 + 997 1009 void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), 998 1010 const char *implements_type, bool include_abstract, 999 1011 void *opaque);
+3 -2
qdev-monitor.c
··· 149 149 int i; 150 150 bool cat_printed; 151 151 152 + module_load_qom_all(); 152 153 list = object_class_get_list_sorted(TYPE_DEVICE, false); 153 154 154 155 for (i = 0; i <= DEVICE_CATEGORY_MAX; i++) { ··· 217 218 DeviceClass *dc; 218 219 const char *original_name = *driver; 219 220 220 - oc = object_class_by_name(*driver); 221 + oc = module_object_class_by_name(*driver); 221 222 if (!oc) { 222 223 const char *typename = find_typename_by_alias(*driver); 223 224 224 225 if (typename) { 225 226 *driver = typename; 226 - oc = object_class_by_name(*driver); 227 + oc = module_object_class_by_name(*driver); 227 228 } 228 229 } 229 230
+14
qom/object.c
··· 985 985 return type->class; 986 986 } 987 987 988 + ObjectClass *module_object_class_by_name(const char *typename) 989 + { 990 + ObjectClass *oc; 991 + 992 + oc = object_class_by_name(typename); 993 + #ifdef CONFIG_MODULES 994 + if (!oc) { 995 + module_load_qom_one(typename); 996 + oc = object_class_by_name(typename); 997 + } 998 + #endif 999 + return oc; 1000 + } 1001 + 988 1002 ObjectClass *object_class_get_parent(ObjectClass *class) 989 1003 { 990 1004 TypeImpl *type = type_get_parent(class->type);
+2 -1
qom/qom-qmp-cmds.c
··· 116 116 { 117 117 ObjectTypeInfoList *ret = NULL; 118 118 119 + module_load_qom_all(); 119 120 object_class_foreach(qom_list_types_tramp, implements, abstract, &ret); 120 121 121 122 return ret; ··· 130 131 ObjectPropertyIterator iter; 131 132 ObjectPropertyInfoList *prop_list = NULL; 132 133 133 - klass = object_class_by_name(typename); 134 + klass = module_object_class_by_name(typename); 134 135 if (klass == NULL) { 135 136 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 136 137 "Device '%s' not found", typename);
+2 -2
softmmu/vl.c
··· 1772 1772 1773 1773 assert(t < VGA_TYPE_MAX); 1774 1774 return !ti->class_names[0] || 1775 - object_class_by_name(ti->class_names[0]) || 1776 - object_class_by_name(ti->class_names[1]); 1775 + module_object_class_by_name(ti->class_names[0]) || 1776 + module_object_class_by_name(ti->class_names[1]); 1777 1777 } 1778 1778 1779 1779 static const char *
+67
util/module.c
··· 245 245 #endif 246 246 return success; 247 247 } 248 + 249 + /* 250 + * Building devices and other qom objects modular is mostly useful in 251 + * case they have dependencies to external shared libraries, so we can 252 + * cut down the core qemu library dependencies. Which is the case for 253 + * only a very few devices & objects. 254 + * 255 + * So with the expectation that this will be rather the exception than 256 + * to rule and the list will not gain that many entries go with a 257 + * simple manually maintained list for now. 258 + */ 259 + static struct { 260 + const char *type; 261 + const char *prefix; 262 + const char *module; 263 + } const qom_modules[] = { 264 + { "ccid-card-passthru", "hw-", "usb-smartcard" }, 265 + { "ccid-card-emulated", "hw-", "usb-smartcard" }, 266 + { "usb-redir", "hw-", "usb-redirect" }, 267 + { "qxl-vga", "hw-", "display-qxl" }, 268 + { "qxl", "hw-", "display-qxl" }, 269 + { "virtio-gpu-device", "hw-", "display-virtio-gpu" }, 270 + { "virtio-gpu-pci", "hw-", "display-virtio-gpu" }, 271 + { "virtio-vga", "hw-", "display-virtio-gpu" }, 272 + { "vhost-user-gpu-device", "hw-", "display-virtio-gpu" }, 273 + { "vhost-user-gpu-pci", "hw-", "display-virtio-gpu" }, 274 + { "vhost-user-vga", "hw-", "display-virtio-gpu" }, 275 + { "chardev-braille", "chardev-", "baum" }, 276 + }; 277 + 278 + static bool module_loaded_qom_all; 279 + 280 + void module_load_qom_one(const char *type) 281 + { 282 + int i; 283 + 284 + if (module_loaded_qom_all) { 285 + return; 286 + } 287 + for (i = 0; i < ARRAY_SIZE(qom_modules); i++) { 288 + if (strcmp(qom_modules[i].type, type) == 0) { 289 + module_load_one(qom_modules[i].prefix, 290 + qom_modules[i].module); 291 + return; 292 + } 293 + } 294 + } 295 + 296 + void module_load_qom_all(void) 297 + { 298 + int i; 299 + 300 + if (module_loaded_qom_all) { 301 + return; 302 + } 303 + for (i = 0; i < ARRAY_SIZE(qom_modules); i++) { 304 + if (i > 0 && (strcmp(qom_modules[i - 1].module, 305 + qom_modules[i].module) == 0 && 306 + strcmp(qom_modules[i - 1].prefix, 307 + qom_modules[i].prefix) == 0)) { 308 + /* one module implementing multiple types -> load only once */ 309 + continue; 310 + } 311 + module_load_one(qom_modules[i].prefix, qom_modules[i].module); 312 + } 313 + module_loaded_qom_all = true; 314 + }