1// Copyright 2016 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7#ifdef __x86_64__ // entire file
8
9#include <inttypes.h>
10
11#include "lib/mtrace.h"
12#include "trace.h"
13
14#include <lib/zircon-internal/mtrace.h>
15
16#include "arch/x86/proc_trace.h"
17
18#define LOCAL_TRACE 0
19
20zx_status_t mtrace_insntrace_control(uint32_t action, uint32_t options,
21                                     user_inout_ptr<void> arg, size_t size) {
22    TRACEF("action %u, options 0x%x, arg %p, size 0x%zx\n",
23           action, options, arg.get(), size);
24
25    switch (action) {
26    case MTRACE_INSNTRACE_ALLOC_TRACE: {
27        if (options != 0)
28            return ZX_ERR_INVALID_ARGS;
29        uint32_t mode;
30        if (size != sizeof(mode))
31            return ZX_ERR_INVALID_ARGS;
32        zx_status_t status = arg.reinterpret<uint32_t>().copy_from_user(&mode);
33        if (status != ZX_OK)
34            return status;
35        TRACEF("action %u, mode 0x%x\n", action, mode);
36        switch (mode) {
37        case IPT_MODE_CPUS:
38            return x86_ipt_alloc_trace(IPT_TRACE_CPUS);
39        case IPT_MODE_THREADS:
40            return x86_ipt_alloc_trace(IPT_TRACE_THREADS);
41        default:
42            return ZX_ERR_INVALID_ARGS;
43        }
44    }
45
46    case MTRACE_INSNTRACE_FREE_TRACE:
47        if (options != 0 || size != 0)
48            return ZX_ERR_INVALID_ARGS;
49        return x86_ipt_free_trace();
50
51    case MTRACE_INSNTRACE_STAGE_TRACE_DATA: {
52        zx_x86_pt_regs_t regs;
53        if (size != sizeof(regs))
54            return ZX_ERR_INVALID_ARGS;
55        zx_status_t status = arg.reinterpret<zx_x86_pt_regs_t>().copy_from_user(&regs);
56        if (status != ZX_OK)
57            return status;
58        zx_itrace_buffer_descriptor_t descriptor = options;
59        TRACEF("action %u, descriptor %u, ctl 0x%" PRIx64 ", output_base 0x%" PRIx64 "\n",
60               action, descriptor, regs.ctl, regs.output_base);
61        return x86_ipt_stage_trace_data(descriptor, &regs);
62    }
63
64    case MTRACE_INSNTRACE_GET_TRACE_DATA: {
65        zx_x86_pt_regs_t regs;
66        if (size != sizeof(regs))
67            return ZX_ERR_INVALID_ARGS;
68        zx_itrace_buffer_descriptor_t descriptor = options;
69        auto status = x86_ipt_get_trace_data(descriptor, &regs);
70        if (status != ZX_OK)
71            return status;
72        TRACEF("action %u, descriptor %u, ctl 0x%" PRIx64 ", output_base 0x%" PRIx64 "\n",
73               action, descriptor, regs.ctl, regs.output_base);
74        status = arg.reinterpret<zx_x86_pt_regs_t>().copy_to_user(regs);
75        if (status != ZX_OK)
76            return status;
77        return ZX_OK;
78    }
79
80    case MTRACE_INSNTRACE_START:
81        if (options != 0 || size != 0)
82            return ZX_ERR_INVALID_ARGS;
83        return x86_ipt_start();
84
85    case MTRACE_INSNTRACE_STOP:
86        if (options != 0 || size != 0)
87            return ZX_ERR_INVALID_ARGS;
88        return x86_ipt_stop();
89
90    default:
91        return ZX_ERR_INVALID_ARGS;
92    }
93}
94
95#endif
96