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

qos_external.c (4345B)


      1/*
      2 * libqos driver framework
      3 *
      4 * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
      5 *
      6 * This library is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License version 2.1 as published by the Free Software Foundation.
      9 *
     10 * This library is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13 * Lesser General Public License for more details.
     14 *
     15 * You should have received a copy of the GNU Lesser General Public
     16 * License along with this library; if not, see <http://www.gnu.org/licenses/>
     17 */
     18
     19#include "qemu/osdep.h"
     20#include <getopt.h>
     21#include "libqtest.h"
     22#include "qapi/qmp/qdict.h"
     23#include "qapi/qmp/qbool.h"
     24#include "qapi/qmp/qstring.h"
     25#include "qemu/module.h"
     26#include "qapi/qmp/qlist.h"
     27#include "malloc.h"
     28#include "qgraph.h"
     29#include "qgraph_internal.h"
     30#include "qos_external.h"
     31
     32static void machine_apply_to_node(const char *name)
     33{
     34    char *machine_name = g_strconcat(qtest_get_arch(), "/", name, NULL);
     35
     36    qos_graph_node_set_availability(machine_name, true);
     37    g_free(machine_name);
     38}
     39
     40void machines_apply_to_node(MachineInfoList *mach_info)
     41{
     42    MachineInfoList *tail;
     43
     44    for (tail = mach_info; tail; tail = tail->next) {
     45        machine_apply_to_node(tail->value->name);
     46        if (tail->value->alias) {
     47            machine_apply_to_node(tail->value->alias);
     48        }
     49    }
     50}
     51
     52static void type_apply_to_node(const char *name, bool is_abstract)
     53{
     54    qos_graph_node_set_availability(name, true);
     55    if (is_abstract) {
     56        qos_delete_cmd_line(name);
     57    }
     58}
     59
     60void types_apply_to_node(ObjectTypeInfoList *type_info)
     61{
     62    ObjectTypeInfoList *tail;
     63
     64    for (tail = type_info; tail; tail = tail->next) {
     65        type_apply_to_node(tail->value->name, tail->value->abstract);
     66    }
     67}
     68
     69static QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
     70{
     71    return obj->get_driver(obj, "memory");
     72}
     73
     74/**
     75 * allocate_objects(): given an array of nodes @arg,
     76 * walks the path invoking all constructors and
     77 * passing the corresponding parameter in order to
     78 * continue the objects allocation.
     79 * Once the test is reached, return the object it consumes.
     80 *
     81 * Since the machine and QEDGE_CONSUMED_BY nodes allocate
     82 * memory in the constructor, g_test_queue_destroy is used so
     83 * that after execution they can be safely free'd.  (The test's
     84 * ->before callback is also welcome to use g_test_queue_destroy).
     85 *
     86 * Note: as specified in walk_path() too, @arg is an array of
     87 * char *, where arg[0] is a pointer to the command line
     88 * string that will be used to properly start QEMU when executing
     89 * the test, and the remaining elements represent the actual objects
     90 * that will be allocated.
     91 */
     92void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc)
     93{
     94    int current = 0;
     95    QGuestAllocator *alloc;
     96    QOSGraphObject *parent = NULL;
     97    QOSGraphEdge *edge;
     98    QOSGraphNode *node;
     99    void *edge_arg;
    100    void *obj;
    101
    102    node = qos_graph_get_node(path[current]);
    103    g_assert(node->type == QNODE_MACHINE);
    104
    105    obj = qos_machine_new(node, qts);
    106    qos_object_queue_destroy(obj);
    107
    108    alloc = get_machine_allocator(obj);
    109    if (p_alloc) {
    110        *p_alloc = alloc;
    111    }
    112
    113    for (;;) {
    114        if (node->type != QNODE_INTERFACE) {
    115            qos_object_start_hw(obj);
    116            parent = obj;
    117        }
    118
    119        /* follow edge and get object for next node constructor */
    120        current++;
    121        edge = qos_graph_get_edge(path[current - 1], path[current]);
    122        node = qos_graph_get_node(path[current]);
    123
    124        if (node->type == QNODE_TEST) {
    125            g_assert(qos_graph_edge_get_type(edge) == QEDGE_CONSUMED_BY);
    126            return obj;
    127        }
    128
    129        switch (qos_graph_edge_get_type(edge)) {
    130        case QEDGE_PRODUCES:
    131            obj = parent->get_driver(parent, path[current]);
    132            break;
    133
    134        case QEDGE_CONSUMED_BY:
    135            edge_arg = qos_graph_edge_get_arg(edge);
    136            obj = qos_driver_new(node, obj, alloc, edge_arg);
    137            qos_object_queue_destroy(obj);
    138            break;
    139
    140        case QEDGE_CONTAINS:
    141            obj = parent->get_device(parent, path[current]);
    142            break;
    143        }
    144    }
    145}
    146