1/**
2 * \file
3 * \brief System-wide tracing
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <stdio.h>
16#include <barrelfish/barrelfish.h>
17#include <barrelfish/dispatch.h>
18#include <barrelfish/dispatcher_arch.h>
19#include <barrelfish/curdispatcher_arch.h>
20#include <trace/trace.h>
21#include <spawndomain/spawndomain.h>
22
23STATIC_ASSERT_SIZEOF(struct trace_event, 16);
24STATIC_ASSERT((sizeof(struct trace_buffer) <= TRACE_PERCORE_BUF_SIZE), "size mismatch");
25
26/**
27 * \brief Initialize per-core tracing buffer
28 *
29 * This function creates a cap for the tracing buffer in taskcn.
30 * It is called from init at startup.
31 *
32 * Note that it does *not* map the buffer into its own vspace.
33 */
34errval_t trace_init(void)
35{
36    errval_t err;
37    size_t bytes;
38
39    struct capref cap = {
40        .cnode = cnode_task,
41        .slot = TASKCN_SLOT_TRACEBUF
42    };
43
44    err = frame_create(cap, TRACE_ALLOC_SIZE, &bytes);
45    if (err_is_fail(err)) {
46        return err_push(err, TRACE_ERR_CREATE_CAP);
47    }
48
49    return SYS_ERR_OK;
50}
51
52/**
53 * \brief Turn off tracing for this domain
54 */
55errval_t trace_disable_domain(void)
56{
57    dispatcher_handle_t handle = curdispatcher();
58    struct dispatcher_generic *disp = get_dispatcher_generic(handle);
59    disp->trace_buf = NULL;
60    return SYS_ERR_OK;
61}
62
63
64/**
65 * Sets up tracing framework for current dispatcher
66 */
67void trace_init_disp(void)
68{
69    dispatcher_handle_t handle = curdispatcher();
70    struct dispatcher_generic *disp = get_dispatcher_generic(handle);
71    disp->trace_buf = (struct trace_buffer*)trace_buffer_va;
72}
73
74/**
75 * \brief Setup the tracing buffer for a child domain
76 *
77 * Assumes that the child domain is currently being spawned
78 * (because we rely on libspawndomain having the right state to
79 * allow us to map the trace buffer into the child's vspace).
80 *
81 * trace_init must already have been called
82 */
83errval_t trace_setup_child(struct cnoderef taskcn,
84                           dispatcher_handle_t handle)
85{
86    errval_t err;
87
88    // Pass tracing buffer cap to new domain
89    struct capref src = {
90        .cnode  = cnode_task,
91        .slot   = TASKCN_SLOT_TRACEBUF
92    };
93    struct capref dst = {
94        .cnode = taskcn,
95        .slot  = TASKCN_SLOT_TRACEBUF
96    };
97    err = cap_copy(dst, src);
98    if (err_is_fail(err)) {
99        return err_push(err, TRACE_ERR_CAP_COPY);
100    }
101
102    return SYS_ERR_OK;
103}
104
105/**
106 * \brief Set up the trace buffer on the current core and notify the kernel.
107 *
108 * Clear the buffer. Return the cap for the buffer.
109 * Should be called once on each core.
110 */
111errval_t trace_setup_on_core(struct capref *retcap)
112{
113#ifdef __i386__
114    return TRACE_ERR_NO_BUFFER;
115#endif
116
117    // Clear the buffer
118    trace_reset_buffer();
119
120    // Tell the kernel that the trace buffer exists
121    struct capref tracecap = {
122        .cnode = cnode_task,
123        .slot = TASKCN_SLOT_TRACEBUF
124    };
125    *retcap = tracecap;
126
127    return SYS_ERR_OK;
128}
129
130