mirror of https://github.com/xqemu/xqemu.git
Merge remote-tracking branch 'remotes/bonzini/memory' into staging
* remotes/bonzini/memory: qdev: correctly send DEVICE_DELETED for recursively-deleted devices memory: do not give a name to the internal exec.c regions memory: MemoryRegion: Add size property memory: MemoryRegion: Add may-overlap and priority props memory: MemoryRegion: Add container and addr props memory: MemoryRegion: replace owner field with QOM parent memory: MemoryRegion: QOMify memory: MemoryRegion: use /machine as default owner libqtest: escape strings in QMP commands, fix leak qom: object: Ignore refs/unrefs of NULL qom: object: remove parent pointer when unparenting mc146818rtc: add "rtc-time" link to "/machine/rtc" qom: allow creating an alias of a child<> property qom: add a generic mechanism to resolve paths qom: add object_property_add_alias() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c26f3a0a6d
12
exec.c
12
exec.c
|
@ -883,7 +883,7 @@ static void phys_section_destroy(MemoryRegion *mr)
|
||||||
|
|
||||||
if (mr->subpage) {
|
if (mr->subpage) {
|
||||||
subpage_t *subpage = container_of(mr, subpage_t, iomem);
|
subpage_t *subpage = container_of(mr, subpage_t, iomem);
|
||||||
memory_region_destroy(&subpage->iomem);
|
object_unref(OBJECT(&subpage->iomem));
|
||||||
g_free(subpage);
|
g_free(subpage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1768,7 +1768,7 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
|
||||||
mmio->as = as;
|
mmio->as = as;
|
||||||
mmio->base = base;
|
mmio->base = base;
|
||||||
memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio,
|
memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio,
|
||||||
"subpage", TARGET_PAGE_SIZE);
|
NULL, TARGET_PAGE_SIZE);
|
||||||
mmio->iomem.subpage = true;
|
mmio->iomem.subpage = true;
|
||||||
#if defined(DEBUG_SUBPAGE)
|
#if defined(DEBUG_SUBPAGE)
|
||||||
printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
|
printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
|
||||||
|
@ -1801,13 +1801,13 @@ MemoryRegion *iotlb_to_region(AddressSpace *as, hwaddr index)
|
||||||
|
|
||||||
static void io_mem_init(void)
|
static void io_mem_init(void)
|
||||||
{
|
{
|
||||||
memory_region_init_io(&io_mem_rom, NULL, &unassigned_mem_ops, NULL, "rom", UINT64_MAX);
|
memory_region_init_io(&io_mem_rom, NULL, &unassigned_mem_ops, NULL, NULL, UINT64_MAX);
|
||||||
memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
|
memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
|
||||||
"unassigned", UINT64_MAX);
|
NULL, UINT64_MAX);
|
||||||
memory_region_init_io(&io_mem_notdirty, NULL, ¬dirty_mem_ops, NULL,
|
memory_region_init_io(&io_mem_notdirty, NULL, ¬dirty_mem_ops, NULL,
|
||||||
"notdirty", UINT64_MAX);
|
NULL, UINT64_MAX);
|
||||||
memory_region_init_io(&io_mem_watch, NULL, &watch_mem_ops, NULL,
|
memory_region_init_io(&io_mem_watch, NULL, &watch_mem_ops, NULL,
|
||||||
"watch", UINT64_MAX);
|
NULL, UINT64_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mem_begin(MemoryListener *listener)
|
static void mem_begin(MemoryListener *listener)
|
||||||
|
|
|
@ -848,6 +848,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
||||||
if (dev->hotplugged && local_err == NULL) {
|
if (dev->hotplugged && local_err == NULL) {
|
||||||
device_reset(dev);
|
device_reset(dev);
|
||||||
}
|
}
|
||||||
|
dev->pending_deleted_event = false;
|
||||||
} else if (!value && dev->realized) {
|
} else if (!value && dev->realized) {
|
||||||
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||||
object_property_set_bool(OBJECT(bus), false, "realized",
|
object_property_set_bool(OBJECT(bus), false, "realized",
|
||||||
|
@ -862,6 +863,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
||||||
if (dc->unrealize && local_err == NULL) {
|
if (dc->unrealize && local_err == NULL) {
|
||||||
dc->unrealize(dev, &local_err);
|
dc->unrealize(dev, &local_err);
|
||||||
}
|
}
|
||||||
|
dev->pending_deleted_event = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
|
@ -972,7 +974,6 @@ static void device_unparent(Object *obj)
|
||||||
{
|
{
|
||||||
DeviceState *dev = DEVICE(obj);
|
DeviceState *dev = DEVICE(obj);
|
||||||
BusState *bus;
|
BusState *bus;
|
||||||
bool have_realized = dev->realized;
|
|
||||||
|
|
||||||
if (dev->realized) {
|
if (dev->realized) {
|
||||||
object_property_set_bool(obj, false, "realized", NULL);
|
object_property_set_bool(obj, false, "realized", NULL);
|
||||||
|
@ -988,7 +989,7 @@ static void device_unparent(Object *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only send event if the device had been completely realized */
|
/* Only send event if the device had been completely realized */
|
||||||
if (have_realized) {
|
if (dev->pending_deleted_event) {
|
||||||
gchar *path = object_get_canonical_path(OBJECT(dev));
|
gchar *path = object_get_canonical_path(OBJECT(dev));
|
||||||
|
|
||||||
qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort);
|
qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort);
|
||||||
|
|
|
@ -909,6 +909,9 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
|
||||||
|
|
||||||
object_property_add(OBJECT(s), "date", "struct tm",
|
object_property_add(OBJECT(s), "date", "struct tm",
|
||||||
rtc_get_date, NULL, NULL, s, NULL);
|
rtc_get_date, NULL, NULL, s, NULL);
|
||||||
|
|
||||||
|
object_property_add_alias(qdev_get_machine(), "rtc-time",
|
||||||
|
OBJECT(s), "date", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
|
ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
|
||||||
|
@ -950,11 +953,17 @@ static void rtc_class_initfn(ObjectClass *klass, void *data)
|
||||||
dc->cannot_instantiate_with_device_add_yet = true;
|
dc->cannot_instantiate_with_device_add_yet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rtc_finalize(Object *obj)
|
||||||
|
{
|
||||||
|
object_property_del(qdev_get_machine(), "rtc", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static const TypeInfo mc146818rtc_info = {
|
static const TypeInfo mc146818rtc_info = {
|
||||||
.name = TYPE_MC146818_RTC,
|
.name = TYPE_MC146818_RTC,
|
||||||
.parent = TYPE_ISA_DEVICE,
|
.parent = TYPE_ISA_DEVICE,
|
||||||
.instance_size = sizeof(RTCState),
|
.instance_size = sizeof(RTCState),
|
||||||
.class_init = rtc_class_initfn,
|
.class_init = rtc_class_initfn,
|
||||||
|
.instance_finalize = rtc_finalize,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mc146818rtc_register_types(void)
|
static void mc146818rtc_register_types(void)
|
||||||
|
|
|
@ -32,10 +32,15 @@
|
||||||
#include "qemu/int128.h"
|
#include "qemu/int128.h"
|
||||||
#include "qemu/notify.h"
|
#include "qemu/notify.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
#include "qom/object.h"
|
||||||
|
|
||||||
#define MAX_PHYS_ADDR_SPACE_BITS 62
|
#define MAX_PHYS_ADDR_SPACE_BITS 62
|
||||||
#define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
|
#define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
|
||||||
|
|
||||||
|
#define TYPE_MEMORY_REGION "qemu:memory-region"
|
||||||
|
#define MEMORY_REGION(obj) \
|
||||||
|
OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION)
|
||||||
|
|
||||||
typedef struct MemoryRegionOps MemoryRegionOps;
|
typedef struct MemoryRegionOps MemoryRegionOps;
|
||||||
typedef struct MemoryRegionMmio MemoryRegionMmio;
|
typedef struct MemoryRegionMmio MemoryRegionMmio;
|
||||||
|
|
||||||
|
@ -131,11 +136,11 @@ typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
||||||
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
|
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
|
||||||
|
|
||||||
struct MemoryRegion {
|
struct MemoryRegion {
|
||||||
|
Object parent_obj;
|
||||||
/* All fields are private - violators will be prosecuted */
|
/* All fields are private - violators will be prosecuted */
|
||||||
const MemoryRegionOps *ops;
|
const MemoryRegionOps *ops;
|
||||||
const MemoryRegionIOMMUOps *iommu_ops;
|
const MemoryRegionIOMMUOps *iommu_ops;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
struct Object *owner;
|
|
||||||
MemoryRegion *container;
|
MemoryRegion *container;
|
||||||
Int128 size;
|
Int128 size;
|
||||||
hwaddr addr;
|
hwaddr addr;
|
||||||
|
@ -152,7 +157,7 @@ struct MemoryRegion {
|
||||||
bool flush_coalesced_mmio;
|
bool flush_coalesced_mmio;
|
||||||
MemoryRegion *alias;
|
MemoryRegion *alias;
|
||||||
hwaddr alias_offset;
|
hwaddr alias_offset;
|
||||||
int priority;
|
int32_t priority;
|
||||||
bool may_overlap;
|
bool may_overlap;
|
||||||
QTAILQ_HEAD(subregions, MemoryRegion) subregions;
|
QTAILQ_HEAD(subregions, MemoryRegion) subregions;
|
||||||
QTAILQ_ENTRY(MemoryRegion) subregions_link;
|
QTAILQ_ENTRY(MemoryRegion) subregions_link;
|
||||||
|
|
|
@ -156,6 +156,7 @@ struct DeviceState {
|
||||||
|
|
||||||
const char *id;
|
const char *id;
|
||||||
bool realized;
|
bool realized;
|
||||||
|
bool pending_deleted_event;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
int hotplugged;
|
int hotplugged;
|
||||||
BusState *parent_bus;
|
BusState *parent_bus;
|
||||||
|
|
|
@ -303,6 +303,25 @@ typedef void (ObjectPropertyAccessor)(Object *obj,
|
||||||
const char *name,
|
const char *name,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ObjectPropertyResolve:
|
||||||
|
* @obj: the object that owns the property
|
||||||
|
* @opaque: the opaque registered with the property
|
||||||
|
* @part: the name of the property
|
||||||
|
*
|
||||||
|
* Resolves the #Object corresponding to property @part.
|
||||||
|
*
|
||||||
|
* The returned object can also be used as a starting point
|
||||||
|
* to resolve a relative path starting with "@part".
|
||||||
|
*
|
||||||
|
* Returns: If @path is the path that led to @obj, the function
|
||||||
|
* returns the #Object corresponding to "@path/@part".
|
||||||
|
* If "@path/@part" is not a valid object path, it returns #NULL.
|
||||||
|
*/
|
||||||
|
typedef Object *(ObjectPropertyResolve)(Object *obj,
|
||||||
|
void *opaque,
|
||||||
|
const char *part);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ObjectPropertyRelease:
|
* ObjectPropertyRelease:
|
||||||
* @obj: the object that owns the property
|
* @obj: the object that owns the property
|
||||||
|
@ -321,6 +340,7 @@ typedef struct ObjectProperty
|
||||||
gchar *type;
|
gchar *type;
|
||||||
ObjectPropertyAccessor *get;
|
ObjectPropertyAccessor *get;
|
||||||
ObjectPropertyAccessor *set;
|
ObjectPropertyAccessor *set;
|
||||||
|
ObjectPropertyResolve *resolve;
|
||||||
ObjectPropertyRelease *release;
|
ObjectPropertyRelease *release;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
|
||||||
|
@ -787,12 +807,16 @@ void object_unref(Object *obj);
|
||||||
* destruction. This may be NULL.
|
* destruction. This may be NULL.
|
||||||
* @opaque: an opaque pointer to pass to the callbacks for the property
|
* @opaque: an opaque pointer to pass to the callbacks for the property
|
||||||
* @errp: returns an error if this function fails
|
* @errp: returns an error if this function fails
|
||||||
|
*
|
||||||
|
* Returns: The #ObjectProperty; this can be used to set the @resolve
|
||||||
|
* callback for child and link properties.
|
||||||
*/
|
*/
|
||||||
void object_property_add(Object *obj, const char *name, const char *type,
|
ObjectProperty *object_property_add(Object *obj, const char *name,
|
||||||
ObjectPropertyAccessor *get,
|
const char *type,
|
||||||
ObjectPropertyAccessor *set,
|
ObjectPropertyAccessor *get,
|
||||||
ObjectPropertyRelease *release,
|
ObjectPropertyAccessor *set,
|
||||||
void *opaque, Error **errp);
|
ObjectPropertyRelease *release,
|
||||||
|
void *opaque, Error **errp);
|
||||||
|
|
||||||
void object_property_del(Object *obj, const char *name, Error **errp);
|
void object_property_del(Object *obj, const char *name, Error **errp);
|
||||||
|
|
||||||
|
@ -1230,6 +1254,26 @@ void object_property_add_uint32_ptr(Object *obj, const char *name,
|
||||||
void object_property_add_uint64_ptr(Object *obj, const char *name,
|
void object_property_add_uint64_ptr(Object *obj, const char *name,
|
||||||
const uint64_t *v, Error **Errp);
|
const uint64_t *v, Error **Errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* object_property_add_alias:
|
||||||
|
* @obj: the object to add a property to
|
||||||
|
* @name: the name of the property
|
||||||
|
* @target_obj: the object to forward property access to
|
||||||
|
* @target_name: the name of the property on the forwarded object
|
||||||
|
* @errp: if an error occurs, a pointer to an area to store the error
|
||||||
|
*
|
||||||
|
* Add an alias for a property on an object. This function will add a property
|
||||||
|
* of the same type as the forwarded property.
|
||||||
|
*
|
||||||
|
* The caller must ensure that <code>@target_obj</code> stays alive as long as
|
||||||
|
* this property exists. In the case of a child object or an alias on the same
|
||||||
|
* object this will be the case. For aliases to other objects the caller is
|
||||||
|
* responsible for taking a reference.
|
||||||
|
*/
|
||||||
|
void object_property_add_alias(Object *obj, const char *name,
|
||||||
|
Object *target_obj, const char *target_name,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* object_child_foreach:
|
* object_child_foreach:
|
||||||
* @obj: the object whose children will be navigated
|
* @obj: the object whose children will be navigated
|
||||||
|
|
239
memory.c
239
memory.c
|
@ -16,6 +16,7 @@
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "exec/ioport.h"
|
#include "exec/ioport.h"
|
||||||
|
#include "qapi/visitor.h"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
@ -842,40 +843,178 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr)
|
||||||
qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
|
qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool memory_region_need_escape(char c)
|
||||||
|
{
|
||||||
|
return c == '/' || c == '[' || c == '\\' || c == ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *memory_region_escape_name(const char *name)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
char *escaped, *q;
|
||||||
|
uint8_t c;
|
||||||
|
size_t bytes = 0;
|
||||||
|
|
||||||
|
for (p = name; *p; p++) {
|
||||||
|
bytes += memory_region_need_escape(*p) ? 4 : 1;
|
||||||
|
}
|
||||||
|
if (bytes == p - name) {
|
||||||
|
return g_memdup(name, bytes + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
escaped = g_malloc(bytes + 1);
|
||||||
|
for (p = name, q = escaped; *p; p++) {
|
||||||
|
c = *p;
|
||||||
|
if (unlikely(memory_region_need_escape(c))) {
|
||||||
|
*q++ = '\\';
|
||||||
|
*q++ = 'x';
|
||||||
|
*q++ = "0123456789abcdef"[c >> 4];
|
||||||
|
c = "0123456789abcdef"[c & 15];
|
||||||
|
}
|
||||||
|
*q++ = c;
|
||||||
|
}
|
||||||
|
*q = 0;
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void object_property_add_child_array(Object *owner,
|
||||||
|
const char *name,
|
||||||
|
Object *child)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *base_name = memory_region_escape_name(name);
|
||||||
|
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
char *full_name = g_strdup_printf("%s[%d]", base_name, i);
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
object_property_add_child(owner, full_name, child, &local_err);
|
||||||
|
g_free(full_name);
|
||||||
|
if (!local_err) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_free(local_err);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(base_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void memory_region_init(MemoryRegion *mr,
|
void memory_region_init(MemoryRegion *mr,
|
||||||
Object *owner,
|
Object *owner,
|
||||||
const char *name,
|
const char *name,
|
||||||
uint64_t size)
|
uint64_t size)
|
||||||
{
|
{
|
||||||
mr->ops = &unassigned_mem_ops;
|
if (!owner) {
|
||||||
mr->opaque = NULL;
|
owner = qdev_get_machine();
|
||||||
mr->owner = owner;
|
}
|
||||||
mr->iommu_ops = NULL;
|
|
||||||
mr->container = NULL;
|
object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
|
||||||
mr->size = int128_make64(size);
|
mr->size = int128_make64(size);
|
||||||
if (size == UINT64_MAX) {
|
if (size == UINT64_MAX) {
|
||||||
mr->size = int128_2_64();
|
mr->size = int128_2_64();
|
||||||
}
|
}
|
||||||
mr->addr = 0;
|
|
||||||
mr->subpage = false;
|
|
||||||
mr->enabled = true;
|
|
||||||
mr->terminates = false;
|
|
||||||
mr->ram = false;
|
|
||||||
mr->romd_mode = true;
|
|
||||||
mr->readonly = false;
|
|
||||||
mr->rom_device = false;
|
|
||||||
mr->destructor = memory_region_destructor_none;
|
|
||||||
mr->priority = 0;
|
|
||||||
mr->may_overlap = false;
|
|
||||||
mr->alias = NULL;
|
|
||||||
QTAILQ_INIT(&mr->subregions);
|
|
||||||
memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
|
|
||||||
QTAILQ_INIT(&mr->coalesced);
|
|
||||||
mr->name = g_strdup(name);
|
mr->name = g_strdup(name);
|
||||||
mr->dirty_log_mask = 0;
|
|
||||||
mr->ioeventfd_nb = 0;
|
if (name) {
|
||||||
mr->ioeventfds = NULL;
|
object_property_add_child_array(owner, name, OBJECT(mr));
|
||||||
mr->flush_coalesced_mmio = false;
|
object_unref(OBJECT(mr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void memory_region_get_addr(Object *obj, Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||||
|
uint64_t value = mr->addr;
|
||||||
|
|
||||||
|
visit_type_uint64(v, &value, name, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void memory_region_get_container(Object *obj, Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||||
|
gchar *path = (gchar *)"";
|
||||||
|
|
||||||
|
if (mr->container) {
|
||||||
|
path = object_get_canonical_path(OBJECT(mr->container));
|
||||||
|
}
|
||||||
|
visit_type_str(v, &path, name, errp);
|
||||||
|
if (mr->container) {
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object *memory_region_resolve_container(Object *obj, void *opaque,
|
||||||
|
const char *part)
|
||||||
|
{
|
||||||
|
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||||
|
|
||||||
|
return OBJECT(mr->container);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void memory_region_get_priority(Object *obj, Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||||
|
int32_t value = mr->priority;
|
||||||
|
|
||||||
|
visit_type_int32(v, &value, name, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool memory_region_get_may_overlap(Object *obj, Error **errp)
|
||||||
|
{
|
||||||
|
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||||
|
|
||||||
|
return mr->may_overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void memory_region_get_size(Object *obj, Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||||
|
uint64_t value = memory_region_size(mr);
|
||||||
|
|
||||||
|
visit_type_uint64(v, &value, name, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void memory_region_initfn(Object *obj)
|
||||||
|
{
|
||||||
|
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||||
|
ObjectProperty *op;
|
||||||
|
|
||||||
|
mr->ops = &unassigned_mem_ops;
|
||||||
|
mr->enabled = true;
|
||||||
|
mr->romd_mode = true;
|
||||||
|
mr->destructor = memory_region_destructor_none;
|
||||||
|
QTAILQ_INIT(&mr->subregions);
|
||||||
|
QTAILQ_INIT(&mr->coalesced);
|
||||||
|
|
||||||
|
op = object_property_add(OBJECT(mr), "container",
|
||||||
|
"link<" TYPE_MEMORY_REGION ">",
|
||||||
|
memory_region_get_container,
|
||||||
|
NULL, /* memory_region_set_container */
|
||||||
|
NULL, NULL, &error_abort);
|
||||||
|
op->resolve = memory_region_resolve_container;
|
||||||
|
|
||||||
|
object_property_add(OBJECT(mr), "addr", "uint64",
|
||||||
|
memory_region_get_addr,
|
||||||
|
NULL, /* memory_region_set_addr */
|
||||||
|
NULL, NULL, &error_abort);
|
||||||
|
object_property_add(OBJECT(mr), "priority", "uint32",
|
||||||
|
memory_region_get_priority,
|
||||||
|
NULL, /* memory_region_set_priority */
|
||||||
|
NULL, NULL, &error_abort);
|
||||||
|
object_property_add_bool(OBJECT(mr), "may-overlap",
|
||||||
|
memory_region_get_may_overlap,
|
||||||
|
NULL, /* memory_region_set_may_overlap */
|
||||||
|
&error_abort);
|
||||||
|
object_property_add(OBJECT(mr), "size", "uint64",
|
||||||
|
memory_region_get_size,
|
||||||
|
NULL, /* memory_region_set_size, */
|
||||||
|
NULL, NULL, &error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
|
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
|
||||||
|
@ -1113,8 +1252,10 @@ void memory_region_init_reservation(MemoryRegion *mr,
|
||||||
memory_region_init_io(mr, owner, &unassigned_mem_ops, mr, name, size);
|
memory_region_init_io(mr, owner, &unassigned_mem_ops, mr, name, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_region_destroy(MemoryRegion *mr)
|
static void memory_region_finalize(Object *obj)
|
||||||
{
|
{
|
||||||
|
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||||
|
|
||||||
assert(QTAILQ_EMPTY(&mr->subregions));
|
assert(QTAILQ_EMPTY(&mr->subregions));
|
||||||
assert(memory_region_transaction_depth == 0);
|
assert(memory_region_transaction_depth == 0);
|
||||||
mr->destructor(mr);
|
mr->destructor(mr);
|
||||||
|
@ -1123,22 +1264,45 @@ void memory_region_destroy(MemoryRegion *mr)
|
||||||
g_free(mr->ioeventfds);
|
g_free(mr->ioeventfds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memory_region_destroy(MemoryRegion *mr)
|
||||||
|
{
|
||||||
|
object_unparent(OBJECT(mr));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Object *memory_region_owner(MemoryRegion *mr)
|
Object *memory_region_owner(MemoryRegion *mr)
|
||||||
{
|
{
|
||||||
return mr->owner;
|
Object *obj = OBJECT(mr);
|
||||||
|
return obj->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_region_ref(MemoryRegion *mr)
|
void memory_region_ref(MemoryRegion *mr)
|
||||||
{
|
{
|
||||||
if (mr && mr->owner) {
|
/* MMIO callbacks most likely will access data that belongs
|
||||||
object_ref(mr->owner);
|
* to the owner, hence the need to ref/unref the owner whenever
|
||||||
|
* the memory region is in use.
|
||||||
|
*
|
||||||
|
* The memory region is a child of its owner. As long as the
|
||||||
|
* owner doesn't call unparent itself on the memory region,
|
||||||
|
* ref-ing the owner will also keep the memory region alive.
|
||||||
|
* Memory regions without an owner are supposed to never go away,
|
||||||
|
* but we still ref/unref them for debugging purposes.
|
||||||
|
*/
|
||||||
|
Object *obj = OBJECT(mr);
|
||||||
|
if (obj && obj->parent) {
|
||||||
|
object_ref(obj->parent);
|
||||||
|
} else {
|
||||||
|
object_ref(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_region_unref(MemoryRegion *mr)
|
void memory_region_unref(MemoryRegion *mr)
|
||||||
{
|
{
|
||||||
if (mr && mr->owner) {
|
Object *obj = OBJECT(mr);
|
||||||
object_unref(mr->owner);
|
if (obj && obj->parent) {
|
||||||
|
object_unref(obj->parent);
|
||||||
|
} else {
|
||||||
|
object_unref(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1946,3 +2110,18 @@ void mtree_info(fprintf_function mon_printf, void *f)
|
||||||
g_free(ml);
|
g_free(ml);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const TypeInfo memory_region_info = {
|
||||||
|
.parent = TYPE_OBJECT,
|
||||||
|
.name = TYPE_MEMORY_REGION,
|
||||||
|
.instance_size = sizeof(MemoryRegion),
|
||||||
|
.instance_init = memory_region_initfn,
|
||||||
|
.instance_finalize = memory_region_finalize,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void memory_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&memory_region_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(memory_register_types)
|
||||||
|
|
147
qom/object.c
147
qom/object.c
|
@ -356,11 +356,6 @@ static inline bool object_property_is_child(ObjectProperty *prop)
|
||||||
return strstart(prop->type, "child<", NULL);
|
return strstart(prop->type, "child<", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool object_property_is_link(ObjectProperty *prop)
|
|
||||||
{
|
|
||||||
return strstart(prop->type, "link<", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void object_property_del_all(Object *obj)
|
static void object_property_del_all(Object *obj)
|
||||||
{
|
{
|
||||||
while (!QTAILQ_EMPTY(&obj->properties)) {
|
while (!QTAILQ_EMPTY(&obj->properties)) {
|
||||||
|
@ -716,11 +711,17 @@ GSList *object_class_get_list(const char *implements_type,
|
||||||
|
|
||||||
void object_ref(Object *obj)
|
void object_ref(Object *obj)
|
||||||
{
|
{
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
atomic_inc(&obj->ref);
|
atomic_inc(&obj->ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_unref(Object *obj)
|
void object_unref(Object *obj)
|
||||||
{
|
{
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_assert(obj->ref > 0);
|
g_assert(obj->ref > 0);
|
||||||
|
|
||||||
/* parent always holds a reference to its children */
|
/* parent always holds a reference to its children */
|
||||||
|
@ -729,11 +730,12 @@ void object_unref(Object *obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_property_add(Object *obj, const char *name, const char *type,
|
ObjectProperty *
|
||||||
ObjectPropertyAccessor *get,
|
object_property_add(Object *obj, const char *name, const char *type,
|
||||||
ObjectPropertyAccessor *set,
|
ObjectPropertyAccessor *get,
|
||||||
ObjectPropertyRelease *release,
|
ObjectPropertyAccessor *set,
|
||||||
void *opaque, Error **errp)
|
ObjectPropertyRelease *release,
|
||||||
|
void *opaque, Error **errp)
|
||||||
{
|
{
|
||||||
ObjectProperty *prop;
|
ObjectProperty *prop;
|
||||||
|
|
||||||
|
@ -742,7 +744,7 @@ void object_property_add(Object *obj, const char *name, const char *type,
|
||||||
error_setg(errp, "attempt to add duplicate property '%s'"
|
error_setg(errp, "attempt to add duplicate property '%s'"
|
||||||
" to object (type '%s')", name,
|
" to object (type '%s')", name,
|
||||||
object_get_typename(obj));
|
object_get_typename(obj));
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,6 +759,7 @@ void object_property_add(Object *obj, const char *name, const char *type,
|
||||||
prop->opaque = opaque;
|
prop->opaque = opaque;
|
||||||
|
|
||||||
QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
|
QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
|
||||||
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectProperty *object_property_find(Object *obj, const char *name,
|
ObjectProperty *object_property_find(Object *obj, const char *name,
|
||||||
|
@ -1029,6 +1032,11 @@ static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
|
||||||
g_free(path);
|
g_free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
|
||||||
|
{
|
||||||
|
return opaque;
|
||||||
|
}
|
||||||
|
|
||||||
static void object_finalize_child_property(Object *obj, const char *name,
|
static void object_finalize_child_property(Object *obj, const char *name,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
|
@ -1042,15 +1050,18 @@ void object_property_add_child(Object *obj, const char *name,
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
gchar *type;
|
gchar *type;
|
||||||
|
ObjectProperty *op;
|
||||||
|
|
||||||
type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
|
type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
|
||||||
|
|
||||||
object_property_add(obj, name, type, object_get_child_property, NULL,
|
op = object_property_add(obj, name, type, object_get_child_property, NULL,
|
||||||
object_finalize_child_property, child, &local_err);
|
object_finalize_child_property, child, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op->resolve = object_resolve_child_property;
|
||||||
object_ref(child);
|
object_ref(child);
|
||||||
g_assert(child->parent == NULL);
|
g_assert(child->parent == NULL);
|
||||||
child->parent = obj;
|
child->parent = obj;
|
||||||
|
@ -1155,13 +1166,16 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_target) {
|
object_ref(new_target);
|
||||||
object_ref(new_target);
|
|
||||||
}
|
|
||||||
*child = new_target;
|
*child = new_target;
|
||||||
if (old_target != NULL) {
|
object_unref(old_target);
|
||||||
object_unref(old_target);
|
}
|
||||||
}
|
|
||||||
|
static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
|
||||||
|
{
|
||||||
|
LinkProperty *lprop = opaque;
|
||||||
|
|
||||||
|
return *lprop->child;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void object_release_link_property(Object *obj, const char *name,
|
static void object_release_link_property(Object *obj, const char *name,
|
||||||
|
@ -1185,6 +1199,7 @@ void object_property_add_link(Object *obj, const char *name,
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
LinkProperty *prop = g_malloc(sizeof(*prop));
|
LinkProperty *prop = g_malloc(sizeof(*prop));
|
||||||
gchar *full_type;
|
gchar *full_type;
|
||||||
|
ObjectProperty *op;
|
||||||
|
|
||||||
prop->child = child;
|
prop->child = child;
|
||||||
prop->check = check;
|
prop->check = check;
|
||||||
|
@ -1192,17 +1207,21 @@ void object_property_add_link(Object *obj, const char *name,
|
||||||
|
|
||||||
full_type = g_strdup_printf("link<%s>", type);
|
full_type = g_strdup_printf("link<%s>", type);
|
||||||
|
|
||||||
object_property_add(obj, name, full_type,
|
op = object_property_add(obj, name, full_type,
|
||||||
object_get_link_property,
|
object_get_link_property,
|
||||||
check ? object_set_link_property : NULL,
|
check ? object_set_link_property : NULL,
|
||||||
object_release_link_property,
|
object_release_link_property,
|
||||||
prop,
|
prop,
|
||||||
&local_err);
|
&local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
g_free(prop);
|
g_free(prop);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op->resolve = object_resolve_link_property;
|
||||||
|
|
||||||
|
out:
|
||||||
g_free(full_type);
|
g_free(full_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1261,11 +1280,8 @@ Object *object_resolve_path_component(Object *parent, const gchar *part)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object_property_is_link(prop)) {
|
if (prop->resolve) {
|
||||||
LinkProperty *lprop = prop->opaque;
|
return prop->resolve(parent, prop->opaque, part);
|
||||||
return *lprop->child;
|
|
||||||
} else if (object_property_is_child(prop)) {
|
|
||||||
return prop->opaque;
|
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1551,6 +1567,77 @@ void object_property_add_uint64_ptr(Object *obj, const char *name,
|
||||||
NULL, NULL, (void *)v, errp);
|
NULL, NULL, (void *)v, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Object *target_obj;
|
||||||
|
const char *target_name;
|
||||||
|
} AliasProperty;
|
||||||
|
|
||||||
|
static void property_get_alias(Object *obj, struct Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
AliasProperty *prop = opaque;
|
||||||
|
|
||||||
|
object_property_get(prop->target_obj, v, prop->target_name, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void property_set_alias(Object *obj, struct Visitor *v, void *opaque,
|
||||||
|
const char *name, Error **errp)
|
||||||
|
{
|
||||||
|
AliasProperty *prop = opaque;
|
||||||
|
|
||||||
|
object_property_set(prop->target_obj, v, prop->target_name, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object *property_resolve_alias(Object *obj, void *opaque,
|
||||||
|
const gchar *part)
|
||||||
|
{
|
||||||
|
AliasProperty *prop = opaque;
|
||||||
|
|
||||||
|
return object_resolve_path_component(prop->target_obj, prop->target_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void property_release_alias(Object *obj, const char *name, void *opaque)
|
||||||
|
{
|
||||||
|
AliasProperty *prop = opaque;
|
||||||
|
|
||||||
|
g_free(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void object_property_add_alias(Object *obj, const char *name,
|
||||||
|
Object *target_obj, const char *target_name,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
AliasProperty *prop;
|
||||||
|
ObjectProperty *op;
|
||||||
|
ObjectProperty *target_prop;
|
||||||
|
gchar *prop_type;
|
||||||
|
|
||||||
|
target_prop = object_property_find(target_obj, target_name, errp);
|
||||||
|
if (!target_prop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object_property_is_child(target_prop)) {
|
||||||
|
prop_type = g_strdup_printf("link%s",
|
||||||
|
target_prop->type + strlen("child"));
|
||||||
|
} else {
|
||||||
|
prop_type = g_strdup(target_prop->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
prop = g_malloc(sizeof(*prop));
|
||||||
|
prop->target_obj = target_obj;
|
||||||
|
prop->target_name = target_name;
|
||||||
|
|
||||||
|
op = object_property_add(obj, name, prop_type,
|
||||||
|
property_get_alias,
|
||||||
|
property_set_alias,
|
||||||
|
property_release_alias,
|
||||||
|
prop, errp);
|
||||||
|
op->resolve = property_resolve_alias;
|
||||||
|
|
||||||
|
g_free(prop_type);
|
||||||
|
}
|
||||||
|
|
||||||
static void object_instance_init(Object *obj)
|
static void object_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
|
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
|
||||||
|
|
|
@ -291,7 +291,7 @@ static void test_media_insert(void)
|
||||||
/* Insert media in drive. DSKCHK should not be reset until a step pulse
|
/* Insert media in drive. DSKCHK should not be reset until a step pulse
|
||||||
* is sent. */
|
* is sent. */
|
||||||
qmp_discard_response("{'execute':'change', 'arguments':{"
|
qmp_discard_response("{'execute':'change', 'arguments':{"
|
||||||
" 'device':'floppy0', 'target': '%s' }}",
|
" 'device':'floppy0', 'target': %s }}",
|
||||||
test_image);
|
test_image);
|
||||||
qmp_discard_response(""); /* ignore event
|
qmp_discard_response(""); /* ignore event
|
||||||
(FIXME open -> open transition?!) */
|
(FIXME open -> open transition?!) */
|
||||||
|
|
|
@ -30,8 +30,9 @@
|
||||||
|
|
||||||
#include "qemu/compiler.h"
|
#include "qemu/compiler.h"
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/qmp/json-streamer.h"
|
|
||||||
#include "qapi/qmp/json-parser.h"
|
#include "qapi/qmp/json-parser.h"
|
||||||
|
#include "qapi/qmp/json-streamer.h"
|
||||||
|
#include "qapi/qmp/qjson.h"
|
||||||
|
|
||||||
#define MAX_IRQ 256
|
#define MAX_IRQ 256
|
||||||
#define SOCKET_TIMEOUT 5
|
#define SOCKET_TIMEOUT 5
|
||||||
|
@ -220,19 +221,15 @@ void qtest_quit(QTestState *s)
|
||||||
g_free(s);
|
g_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void socket_sendf(int fd, const char *fmt, va_list ap)
|
static void socket_send(int fd, const char *buf, size_t size)
|
||||||
{
|
{
|
||||||
gchar *str;
|
size_t offset;
|
||||||
size_t size, offset;
|
|
||||||
|
|
||||||
str = g_strdup_vprintf(fmt, ap);
|
|
||||||
size = strlen(str);
|
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
while (offset < size) {
|
while (offset < size) {
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
len = write(fd, str + offset, size - offset);
|
len = write(fd, buf + offset, size - offset);
|
||||||
if (len == -1 && errno == EINTR) {
|
if (len == -1 && errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -244,6 +241,15 @@ static void socket_sendf(int fd, const char *fmt, va_list ap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void socket_sendf(int fd, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
gchar *str = g_strdup_vprintf(fmt, ap);
|
||||||
|
size_t size = strlen(str);
|
||||||
|
|
||||||
|
socket_send(fd, str, size);
|
||||||
|
g_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
|
static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -378,8 +384,29 @@ QDict *qtest_qmp_receive(QTestState *s)
|
||||||
|
|
||||||
QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
|
QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
/* Send QMP request */
|
va_list ap_copy;
|
||||||
socket_sendf(s->qmp_fd, fmt, ap);
|
QObject *qobj;
|
||||||
|
|
||||||
|
/* Going through qobject ensures we escape strings properly.
|
||||||
|
* This seemingly unnecessary copy is required in case va_list
|
||||||
|
* is an array type.
|
||||||
|
*/
|
||||||
|
va_copy(ap_copy, ap);
|
||||||
|
qobj = qobject_from_jsonv(fmt, &ap_copy);
|
||||||
|
va_end(ap_copy);
|
||||||
|
|
||||||
|
/* No need to send anything for an empty QObject. */
|
||||||
|
if (qobj) {
|
||||||
|
QString *qstr = qobject_to_json(qobj);
|
||||||
|
const char *str = qstring_get_str(qstr);
|
||||||
|
size_t size = qstring_get_length(qstr);
|
||||||
|
|
||||||
|
/* Send QMP request */
|
||||||
|
socket_send(s->qmp_fd, str, size);
|
||||||
|
|
||||||
|
QDECREF(qstr);
|
||||||
|
qobject_decref(qobj);
|
||||||
|
}
|
||||||
|
|
||||||
/* Receive reply */
|
/* Receive reply */
|
||||||
return qtest_qmp_receive(s);
|
return qtest_qmp_receive(s);
|
||||||
|
|
|
@ -53,7 +53,7 @@ static void test_properties(const char *path, bool recurse)
|
||||||
|
|
||||||
g_test_message("Obtaining properties of %s", path);
|
g_test_message("Obtaining properties of %s", path);
|
||||||
response = qmp("{ 'execute': 'qom-list',"
|
response = qmp("{ 'execute': 'qom-list',"
|
||||||
" 'arguments': { 'path': '%s' } }", path);
|
" 'arguments': { 'path': %s } }", path);
|
||||||
g_assert(response);
|
g_assert(response);
|
||||||
|
|
||||||
if (!recurse) {
|
if (!recurse) {
|
||||||
|
@ -76,8 +76,8 @@ static void test_properties(const char *path, bool recurse)
|
||||||
const char *prop = qdict_get_str(tuple, "name");
|
const char *prop = qdict_get_str(tuple, "name");
|
||||||
g_test_message("Testing property %s.%s", path, prop);
|
g_test_message("Testing property %s.%s", path, prop);
|
||||||
response = qmp("{ 'execute': 'qom-get',"
|
response = qmp("{ 'execute': 'qom-get',"
|
||||||
" 'arguments': { 'path': '%s',"
|
" 'arguments': { 'path': %s,"
|
||||||
" 'property': '%s' } }",
|
" 'property': %s } }",
|
||||||
path, prop);
|
path, prop);
|
||||||
/* qom-get may fail but should not, e.g., segfault. */
|
/* qom-get may fail but should not, e.g., segfault. */
|
||||||
g_assert(response);
|
g_assert(response);
|
||||||
|
|
|
@ -69,7 +69,7 @@ static int qmp_tmp105_get_temperature(const char *id)
|
||||||
QDict *response;
|
QDict *response;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': '%s', "
|
response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, "
|
||||||
"'property': 'temperature' } }", id);
|
"'property': 'temperature' } }", id);
|
||||||
g_assert(qdict_haskey(response, "return"));
|
g_assert(qdict_haskey(response, "return"));
|
||||||
ret = qdict_get_int(response, "return");
|
ret = qdict_get_int(response, "return");
|
||||||
|
@ -81,7 +81,7 @@ static void qmp_tmp105_set_temperature(const char *id, int value)
|
||||||
{
|
{
|
||||||
QDict *response;
|
QDict *response;
|
||||||
|
|
||||||
response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': '%s', "
|
response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, "
|
||||||
"'property': 'temperature', 'value': %d } }", id, value);
|
"'property': 'temperature', 'value': %d } }", id, value);
|
||||||
g_assert(qdict_haskey(response, "return"));
|
g_assert(qdict_haskey(response, "return"));
|
||||||
QDECREF(response);
|
QDECREF(response);
|
||||||
|
|
3
vl.c
3
vl.c
|
@ -3986,12 +3986,11 @@ int main(int argc, char **argv, char **envp)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_exec_init_all();
|
|
||||||
|
|
||||||
current_machine = MACHINE(object_new(object_class_get_name(
|
current_machine = MACHINE(object_new(object_class_get_name(
|
||||||
OBJECT_CLASS(machine_class))));
|
OBJECT_CLASS(machine_class))));
|
||||||
object_property_add_child(object_get_root(), "machine",
|
object_property_add_child(object_get_root(), "machine",
|
||||||
OBJECT(current_machine), &error_abort);
|
OBJECT(current_machine), &error_abort);
|
||||||
|
cpu_exec_init_all();
|
||||||
|
|
||||||
if (machine_class->hw_version) {
|
if (machine_class->hw_version) {
|
||||||
qemu_set_version(machine_class->hw_version);
|
qemu_set_version(machine_class->hw_version);
|
||||||
|
|
Loading…
Reference in New Issue