cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

object_interfaces.c (9676B)


      1#include "qemu/osdep.h"
      2
      3#include "qemu/cutils.h"
      4#include "qapi/error.h"
      5#include "qapi/qapi-commands-qom.h"
      6#include "qapi/qapi-visit-qom.h"
      7#include "qapi/qmp/qdict.h"
      8#include "qapi/qmp/qerror.h"
      9#include "qapi/qmp/qjson.h"
     10#include "qapi/qobject-input-visitor.h"
     11#include "qapi/qobject-output-visitor.h"
     12#include "qom/object_interfaces.h"
     13#include "qemu/help_option.h"
     14#include "qemu/id.h"
     15#include "qemu/module.h"
     16#include "qemu/option.h"
     17#include "qemu/qemu-print.h"
     18#include "qapi/opts-visitor.h"
     19#include "qemu/config-file.h"
     20
     21bool user_creatable_complete(UserCreatable *uc, Error **errp)
     22{
     23    UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
     24    Error *err = NULL;
     25
     26    if (ucc->complete) {
     27        ucc->complete(uc, &err);
     28        error_propagate(errp, err);
     29    }
     30    return !err;
     31}
     32
     33bool user_creatable_can_be_deleted(UserCreatable *uc)
     34{
     35
     36    UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
     37
     38    if (ucc->can_be_deleted) {
     39        return ucc->can_be_deleted(uc);
     40    } else {
     41        return true;
     42    }
     43}
     44
     45static void object_set_properties_from_qdict(Object *obj, const QDict *qdict,
     46                                             Visitor *v, Error **errp)
     47{
     48    const QDictEntry *e;
     49    Error *local_err = NULL;
     50
     51    if (!visit_start_struct(v, NULL, NULL, 0, &local_err)) {
     52        goto out;
     53    }
     54    for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
     55        if (!object_property_set(obj, e->key, v, &local_err)) {
     56            break;
     57        }
     58    }
     59    if (!local_err) {
     60        visit_check_struct(v, &local_err);
     61    }
     62    visit_end_struct(v, NULL);
     63
     64out:
     65    if (local_err) {
     66        error_propagate(errp, local_err);
     67    }
     68}
     69
     70void object_set_properties_from_keyval(Object *obj, const QDict *qdict,
     71                                       bool from_json, Error **errp)
     72{
     73    Visitor *v;
     74    if (from_json) {
     75        v = qobject_input_visitor_new(QOBJECT(qdict));
     76    } else {
     77        v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
     78    }
     79    object_set_properties_from_qdict(obj, qdict, v, errp);
     80    visit_free(v);
     81}
     82
     83Object *user_creatable_add_type(const char *type, const char *id,
     84                                const QDict *qdict,
     85                                Visitor *v, Error **errp)
     86{
     87    ERRP_GUARD();
     88    Object *obj;
     89    ObjectClass *klass;
     90    Error *local_err = NULL;
     91
     92    if (id != NULL && !id_wellformed(id)) {
     93        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
     94        error_append_hint(errp, "Identifiers consist of letters, digits, "
     95                          "'-', '.', '_', starting with a letter.\n");
     96        return NULL;
     97    }
     98
     99    klass = object_class_by_name(type);
    100    if (!klass) {
    101        error_setg(errp, "invalid object type: %s", type);
    102        return NULL;
    103    }
    104
    105    if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
    106        error_setg(errp, "object type '%s' isn't supported by object-add",
    107                   type);
    108        return NULL;
    109    }
    110
    111    if (object_class_is_abstract(klass)) {
    112        error_setg(errp, "object type '%s' is abstract", type);
    113        return NULL;
    114    }
    115
    116    assert(qdict);
    117    obj = object_new(type);
    118    object_set_properties_from_qdict(obj, qdict, v, &local_err);
    119    if (local_err) {
    120        goto out;
    121    }
    122
    123    if (id != NULL) {
    124        object_property_try_add_child(object_get_objects_root(),
    125                                      id, obj, &local_err);
    126        if (local_err) {
    127            goto out;
    128        }
    129    }
    130
    131    if (!user_creatable_complete(USER_CREATABLE(obj), &local_err)) {
    132        if (id != NULL) {
    133            object_property_del(object_get_objects_root(), id);
    134        }
    135        goto out;
    136    }
    137out:
    138    if (local_err) {
    139        error_propagate(errp, local_err);
    140        object_unref(obj);
    141        return NULL;
    142    }
    143    return obj;
    144}
    145
    146void user_creatable_add_qapi(ObjectOptions *options, Error **errp)
    147{
    148    Visitor *v;
    149    QObject *qobj;
    150    QDict *props;
    151    Object *obj;
    152
    153    v = qobject_output_visitor_new(&qobj);
    154    visit_type_ObjectOptions(v, NULL, &options, &error_abort);
    155    visit_complete(v, &qobj);
    156    visit_free(v);
    157
    158    props = qobject_to(QDict, qobj);
    159    qdict_del(props, "qom-type");
    160    qdict_del(props, "id");
    161
    162    v = qobject_input_visitor_new(QOBJECT(props));
    163    obj = user_creatable_add_type(ObjectType_str(options->qom_type),
    164                                  options->id, props, v, errp);
    165    object_unref(obj);
    166    qobject_unref(qobj);
    167    visit_free(v);
    168}
    169
    170char *object_property_help(const char *name, const char *type,
    171                           QObject *defval, const char *description)
    172{
    173    GString *str = g_string_new(NULL);
    174
    175    g_string_append_printf(str, "  %s=<%s>", name, type);
    176    if (description || defval) {
    177        if (str->len < 24) {
    178            g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
    179        }
    180        g_string_append(str, " - ");
    181    }
    182    if (description) {
    183        g_string_append(str, description);
    184    }
    185    if (defval) {
    186        g_autofree char *def_json = g_string_free(qobject_to_json(defval),
    187                                                  false);
    188        g_string_append_printf(str, " (default: %s)", def_json);
    189    }
    190
    191    return g_string_free(str, false);
    192}
    193
    194static void user_creatable_print_types(void)
    195{
    196    GSList *l, *list;
    197
    198    qemu_printf("List of user creatable objects:\n");
    199    list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
    200    for (l = list; l != NULL; l = l->next) {
    201        ObjectClass *oc = OBJECT_CLASS(l->data);
    202        qemu_printf("  %s\n", object_class_get_name(oc));
    203    }
    204    g_slist_free(list);
    205}
    206
    207bool type_print_class_properties(const char *type)
    208{
    209    ObjectClass *klass;
    210    ObjectPropertyIterator iter;
    211    ObjectProperty *prop;
    212    GPtrArray *array;
    213    int i;
    214
    215    klass = object_class_by_name(type);
    216    if (!klass) {
    217        return false;
    218    }
    219
    220    array = g_ptr_array_new();
    221    object_class_property_iter_init(&iter, klass);
    222    while ((prop = object_property_iter_next(&iter))) {
    223        if (!prop->set) {
    224            continue;
    225        }
    226
    227        g_ptr_array_add(array,
    228                        object_property_help(prop->name, prop->type,
    229                                             prop->defval, prop->description));
    230    }
    231    g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
    232    if (array->len > 0) {
    233        qemu_printf("%s options:\n", type);
    234    } else {
    235        qemu_printf("There are no options for %s.\n", type);
    236    }
    237    for (i = 0; i < array->len; i++) {
    238        qemu_printf("%s\n", (char *)array->pdata[i]);
    239    }
    240    g_ptr_array_set_free_func(array, g_free);
    241    g_ptr_array_free(array, true);
    242    return true;
    243}
    244
    245bool user_creatable_print_help(const char *type, QemuOpts *opts)
    246{
    247    if (is_help_option(type)) {
    248        user_creatable_print_types();
    249        return true;
    250    }
    251
    252    if (qemu_opt_has_help_opt(opts)) {
    253        return type_print_class_properties(type);
    254    }
    255
    256    return false;
    257}
    258
    259static void user_creatable_print_help_from_qdict(QDict *args)
    260{
    261    const char *type = qdict_get_try_str(args, "qom-type");
    262
    263    if (!type || !type_print_class_properties(type)) {
    264        user_creatable_print_types();
    265    }
    266}
    267
    268ObjectOptions *user_creatable_parse_str(const char *optarg, Error **errp)
    269{
    270    ERRP_GUARD();
    271    QObject *obj;
    272    bool help;
    273    Visitor *v;
    274    ObjectOptions *options;
    275
    276    if (optarg[0] == '{') {
    277        obj = qobject_from_json(optarg, errp);
    278        if (!obj) {
    279            return NULL;
    280        }
    281        v = qobject_input_visitor_new(obj);
    282    } else {
    283        QDict *args = keyval_parse(optarg, "qom-type", &help, errp);
    284        if (*errp) {
    285            return NULL;
    286        }
    287        if (help) {
    288            user_creatable_print_help_from_qdict(args);
    289            qobject_unref(args);
    290            return NULL;
    291        }
    292
    293        obj = QOBJECT(args);
    294        v = qobject_input_visitor_new_keyval(obj);
    295    }
    296
    297    visit_type_ObjectOptions(v, NULL, &options, errp);
    298    visit_free(v);
    299    qobject_unref(obj);
    300
    301    return options;
    302}
    303
    304bool user_creatable_add_from_str(const char *optarg, Error **errp)
    305{
    306    ERRP_GUARD();
    307    ObjectOptions *options;
    308
    309    options = user_creatable_parse_str(optarg, errp);
    310    if (!options) {
    311        return false;
    312    }
    313
    314    user_creatable_add_qapi(options, errp);
    315    qapi_free_ObjectOptions(options);
    316    return !*errp;
    317}
    318
    319void user_creatable_process_cmdline(const char *optarg)
    320{
    321    if (!user_creatable_add_from_str(optarg, &error_fatal)) {
    322        /* Help was printed */
    323        exit(EXIT_SUCCESS);
    324    }
    325}
    326
    327bool user_creatable_del(const char *id, Error **errp)
    328{
    329    QemuOptsList *opts_list;
    330    Object *container;
    331    Object *obj;
    332
    333    container = object_get_objects_root();
    334    obj = object_resolve_path_component(container, id);
    335    if (!obj) {
    336        error_setg(errp, "object '%s' not found", id);
    337        return false;
    338    }
    339
    340    if (!user_creatable_can_be_deleted(USER_CREATABLE(obj))) {
    341        error_setg(errp, "object '%s' is in use, can not be deleted", id);
    342        return false;
    343    }
    344
    345    /*
    346     * if object was defined on the command-line, remove its corresponding
    347     * option group entry
    348     */
    349    opts_list = qemu_find_opts_err("object", NULL);
    350    if (opts_list) {
    351        qemu_opts_del(qemu_opts_find(opts_list, id));
    352    }
    353
    354    object_unparent(obj);
    355    return true;
    356}
    357
    358void user_creatable_cleanup(void)
    359{
    360    object_unparent(object_get_objects_root());
    361}
    362
    363static void register_types(void)
    364{
    365    static const TypeInfo uc_interface_info = {
    366        .name          = TYPE_USER_CREATABLE,
    367        .parent        = TYPE_INTERFACE,
    368        .class_size = sizeof(UserCreatableClass),
    369    };
    370
    371    type_register_static(&uc_interface_info);
    372}
    373
    374type_init(register_types)