/* * (C) Copyright David Gibson , IBM Corporation. 2007. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include "dtc.h" #ifdef TRACE_CHECKS #define TRACE(c, ...) \ do { \ fprintf(stderr, "=== %s: ", (c)->name); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ } while (0) #else #define TRACE(c, fmt, ...) do { } while (0) #endif enum checkstatus { UNCHECKED = 0, PREREQ, PASSED, FAILED, }; struct check; typedef void (*tree_check_fn)(struct check *c, struct node *dt); typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node); typedef void (*prop_check_fn)(struct check *c, struct node *dt, struct node *node, struct property *prop); struct check { const char *name; tree_check_fn tree_fn; node_check_fn node_fn; prop_check_fn prop_fn; void *data; bool warn, error; enum checkstatus status; int inprogress; int num_prereqs; struct check **prereq; }; #define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \ static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ static struct check nm = { \ .name = #nm, \ .tree_fn = (tfn), \ .node_fn = (nfn), \ .prop_fn = (pfn), \ .data = (d), \ .warn = (w), \ .error = (e), \ .status = UNCHECKED, \ .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ .prereq = nm##_prereqs, \ }; #define WARNING(nm, tfn, nfn, pfn, d, ...) \ CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__) #define ERROR(nm, tfn, nfn, pfn, d, ...) \ CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__) #define CHECK(nm, tfn, nfn, pfn, d, ...) \ CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__) #define TREE_WARNING(nm, d, ...) \ WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) #define TREE_ERROR(nm, d, ...) \ ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) #define TREE_CHECK(nm, d, ...) \ CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) #define NODE_WARNING(nm, d, ...) \ WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) #define NODE_ERROR(nm, d, ...) \ ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) #define NODE_CHECK(nm, d, ...) \ CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) #define PROP_WARNING(nm, d, ...) \ WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) #define PROP_ERROR(nm, d, ...) \ ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) #define PROP_CHECK(nm, d, ...) \ CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) #ifdef __GNUC__ static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); #endif static inline void check_msg(struct check *c, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if ((c->warn && (quiet < 1)) || (c->error && (quiet < 2))) { fprintf(stderr, "%s (%s): ", (c->error) ? "ERROR" : "Warning", c->name); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } } #define FAIL(c, ...) \ do { \ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ (c)->status = FAILED; \ check_msg((c), __VA_ARGS__); \ } while (0) static void check_nodes_props(struct check *c, struct node *dt, struct node *node) { struct node *child; struct property *prop; TRACE(c, "%s", node->fullpath); if (c->node_fn) c->node_fn(c, dt, node); if (c->prop_fn) for_each_property(node, prop) { TRACE(c, "%s\t'%s'", node->fullpath, prop->name); c->prop_fn(c, dt, node, prop); } for_each_child(node, child) check_nodes_props(c, dt, child); } static int run_check(struct check *c, struct node *dt) { int error = 0; int i; assert(!c->inprogress); if (c->status != UNCHECKED) goto out; c->inprogress = 1; for (i = 0; i < c->num_prereqs; i++) { struct check *prq = c->prereq[i]; error |= run_check(prq, dt); if (prq->status != PASSED) { c->status = PREREQ; check_msg(c, "Failed prerequisite '%s'", c->prereq[i]->name); } } if (c->status != UNCHECKED) goto out; if (c->node_fn || c->prop_fn) check_nodes_props(c, dt, dt); if (c->tree_fn) c->tree_fn(c, dt); if (c->status == UNCHECKED) c->status = PASSED; TRACE(c, "\tCompleted, status %d", c->status); out: c->inprogress = 0; if ((c->status != PASSED) && (c->error)) error = 1; return error; } /* * Utility check functions */ /* A check which always fails, for testing purposes only */ static inline void check_always_fail(struct check *c, struct node *dt) { FAIL(c, "always_fail check"); } TREE_CHECK(always_fail, NULL); static void check_is_string(struct check *c, struct node *root, struct node *node) { struct property *prop; char *propname = c->data; prop = get_property(node, propname); if (!prop) return; /* Not present, assumed ok */ if (!data_is_one_string(prop->val)) FAIL(c, "\"%s\" property in %s is not a string", propname, node->fullpath); } #define WARNING_IF_NOT_STRING(nm, propname) \ WARNING(nm, N
/*
 * Ftrace trace backend
 *
 * Copyright (C) 2013 Hitachi, Ltd.
 * Created by Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
 */

#include "qemu/osdep.h"
#include "trace.h"
#include "trace/control.h"

int trace_marker_fd;

static int find_debugfs(char *debugfs)
{
    char type[100];
    FILE *fp;

    fp = fopen("/proc/mounts", "r");
    if (fp == NULL) {
        return 0;
    }

    while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
                  debugfs, type) == 2) {
        if (strcmp(type, "debugfs") == 0) {
            break;
        }
    }
    fclose(fp);

    if (strcmp(type, "debugfs") != 0) {
        return 0;
    }
    return 1;
}

bool ftrace_init(void)
{
    char debugfs[PATH_MAX];
    char path[PATH_MAX];
    int debugfs_found;
    int trace_fd = -1;

    debugfs_found = find_debugfs(debugfs);
    if (debugfs_found) {
        snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs);
        trace_fd = open(path, O_WRONLY);
        if (trace_fd < 0) {
            perror("Could not open ftrace 'tracing_on' file");
            return false;
        } else {
            if (write(trace_fd, "1", 1)