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

qdev-clock: introduce an init array to ease the device construction

Introduce a function and macro helpers to setup several clocks
in a device from a static array description.

An element of the array describes the clock (name and direction) as
well as the related callback and an optional offset to store the
created object pointer in the device state structure.

The array must be terminated by a special element QDEV_CLOCK_END.

This is based on the original work of Frederic Konrad.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 20200406135251.157596-5-damien.hedde@greensocs.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Damien Hedde and committed by
Peter Maydell
f0bc2a64 0e6934f2

+72
+17
hw/core/qdev-clock.c
··· 116 116 return ncl->clock; 117 117 } 118 118 119 + void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks) 120 + { 121 + const struct ClockPortInitElem *elem; 122 + 123 + for (elem = &clocks[0]; elem->name != NULL; elem++) { 124 + Clock **clkp; 125 + /* offset cannot be inside the DeviceState part */ 126 + assert(elem->offset > sizeof(DeviceState)); 127 + clkp = (Clock **)(((void *) dev) + elem->offset); 128 + if (elem->is_output) { 129 + *clkp = qdev_init_clock_out(dev, elem->name); 130 + } else { 131 + *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev); 132 + } 133 + } 134 + } 135 + 119 136 static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name) 120 137 { 121 138 NamedClockList *ncl;
+55
include/hw/qdev-clock.h
··· 101 101 */ 102 102 void qdev_finalize_clocklist(DeviceState *dev); 103 103 104 + /** 105 + * ClockPortInitElem: 106 + * @name: name of the clock (can't be NULL) 107 + * @output: indicates whether the clock is input or output 108 + * @callback: for inputs, optional callback to be called on clock's update 109 + * with device as opaque 110 + * @offset: optional offset to store the ClockIn or ClockOut pointer in device 111 + * state structure (0 means unused) 112 + */ 113 + struct ClockPortInitElem { 114 + const char *name; 115 + bool is_output; 116 + ClockCallback *callback; 117 + size_t offset; 118 + }; 119 + 120 + #define clock_offset_value(devstate, field) \ 121 + (offsetof(devstate, field) + \ 122 + type_check(Clock *, typeof_field(devstate, field))) 123 + 124 + #define QDEV_CLOCK(out_not_in, devstate, field, cb) { \ 125 + .name = (stringify(field)), \ 126 + .is_output = out_not_in, \ 127 + .callback = cb, \ 128 + .offset = clock_offset_value(devstate, field), \ 129 + } 130 + 131 + /** 132 + * QDEV_CLOCK_(IN|OUT): 133 + * @devstate: structure type. @dev argument of qdev_init_clocks below must be 134 + * a pointer to that same type. 135 + * @field: a field in @_devstate (must be Clock*) 136 + * @callback: (for input only) callback (or NULL) to be called with the device 137 + * state as argument 138 + * 139 + * The name of the clock will be derived from @field 140 + */ 141 + #define QDEV_CLOCK_IN(devstate, field, callback) \ 142 + QDEV_CLOCK(false, devstate, field, callback) 143 + 144 + #define QDEV_CLOCK_OUT(devstate, field) \ 145 + QDEV_CLOCK(true, devstate, field, NULL) 146 + 147 + #define QDEV_CLOCK_END { .name = NULL } 148 + 149 + typedef struct ClockPortInitElem ClockPortInitArray[]; 150 + 151 + /** 152 + * qdev_init_clocks: 153 + * @dev: the device to add clocks to 154 + * @clocks: a QDEV_CLOCK_END-terminated array which contains the 155 + * clocks information. 156 + */ 157 + void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks); 158 + 104 159 #endif /* QDEV_CLOCK_H */