DM:tools: add acrntrace tool

acrntrace: is an debug tool running on SOS to capture trace data.

Usage:
1) Start tracing
  Capture buffered trace data:
  # acrntrace
  or clear buffer before tracing start:
  # acrntrace -c

  A folder will be created to save the trace data files are under
  /tmp/acrntrace/, named with time string.
  Eg: /tmp/acrntrace/20171115-101605
2) Stop tracing
  # q <enter>

Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Yan, Like <like.yan@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yan, Like 2018-03-29 13:46:06 +08:00 committed by Jack Ren
parent c730806a36
commit 99c69c7773
6 changed files with 866 additions and 0 deletions

View File

@ -0,0 +1,5 @@
all:
gcc -o acrntrace acrntrace.c sbuf.c -I. -lpthread
clean:
rm acrntrace

View File

@ -0,0 +1,381 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include "acrntrace.h"
#include "trace_event.h"
/* for opt */
static uint64_t period = 10000;
static const char optString[] = "t:hc";
static const char dev_name[] = "/dev/acrn_trace";
static uint32_t flags;
static char trace_file_dir[TRACE_FILE_DIR_LEN];
static reader_struct *reader;
static int pcpu_num = 0;
static void display_usage(void)
{
printf("acrntrace - tool to collect ACRN trace data\n"
"[Usage] acrntrace [-t] [period in msec] [-ch]\n\n"
"[Options]\n"
"\t-h: print this message\n"
"\t-t: period_in_ms: specify polling interval [1-999]\n"
"\t-c: clear the buffered old data\n");
}
static int parse_opt(int argc, char *argv[])
{
int opt, ret;
while ((opt = getopt(argc, argv, optString)) != -1) {
switch (opt) {
case 't':
ret = atoi(optarg);
if (ret <= 0 || ret >=1000) {
pr_err("'-t' require integer between [1-999]\n");
return -EINVAL;
}
period = ret * 1000;
pr_dbg("Period is %lu\n", period);
break;
case 'c':
flags |= FLAG_CLEAR_BUF;
break;
case 'h':
display_usage();
return -EINVAL;
default:
/* Undefined operation. */
display_usage();
return -EINVAL;
}
};
return 0;
}
static int shell_cmd(const char *cmd, char *outbuf, int len)
{
FILE *ptr;
char cmd_buf[256];
int ret;
if (!outbuf)
return system(cmd);
memset(cmd_buf, 0, sizeof(cmd_buf));
memset(outbuf, 0, len);
snprintf(cmd_buf, sizeof(cmd_buf), "%s 2>&1", cmd);
ptr = popen(cmd_buf, "re");
if (!ptr)
return -1;
ret = fread(outbuf, 1, len, ptr);
pclose(ptr);
return ret;
}
static int get_cpu_num(void)
{
char cmd[128];
char buf[16];
int ret;
snprintf(cmd, sizeof(cmd), "ls %s_* | wc -l", dev_name);
ret = shell_cmd(cmd, buf, sizeof(buf));
if (ret <= 0) {
pr_err("Faile to get cpu number, use default 4\n");
return PCPU_NUM;
}
ret = atoi(buf);
if (ret <= 0) {
pr_err("Wrong cpu number, use default 4\n");
return PCPU_NUM;
}
return ret;
}
static double get_cpu_freq(void)
{
char cmd[] =
"cat /proc/cpuinfo | grep -m 1 \"cpu MHz\" | awk '{print $4}'";
char buf[16];
int ret;
double freq = 0;
ret = shell_cmd(cmd, buf, sizeof(buf));
if (ret <= 0) {
pr_err("Faile to get cpu freq, use default 1920MHz\n");
return 1920.00;
}
freq = atof(buf);
if (freq <= 0) {
pr_err("Invalid cpu freq string, use default 1920MHz\n");
return 1920.00;
}
return freq;
}
static int create_trace_file_dir(char *dir)
{
int status;
char cmd[CMD_MAX_LEN];
char time_str[TIME_STR_LEN];
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep);
snprintf(time_str, TIME_STR_LEN, "%d%02d%02d-%02d%02d%02d",
(1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday,
p->tm_hour, p->tm_min, p->tm_sec);
pr_info("start tracing at %s\n", time_str);
snprintf(dir, TRACE_FILE_DIR_LEN, "%s%s", TRACE_FILE_ROOT, time_str);
memset(cmd, 0, CMD_MAX_LEN);
snprintf(cmd, CMD_MAX_LEN, "%s %s", "mkdir -p ", dir);
status = system(cmd);
if (-1 == status)
return -1; /* failed to execute sh */
pr_dbg("dir %s creted\n", dir);
return WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE;
}
/* function executed in each consumer thread */
static void reader_fn(param_t * param)
{
int ret;
uint32_t cpuid = param->cpuid;
FILE *fp = param->trace_filep;
shared_buf_t *sbuf = param->sbuf;
trace_ev_t e;
pr_dbg("reader thread[%lu] created for FILE*[0x%p]\n",
pthread_self(), fp);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
/* Clear the old data in sbuf */
if (flags & FLAG_CLEAR_BUF)
sbuf_clear_buffered(sbuf);
/* write cpu freq to the first line of output file */
fprintf(fp, "CPU Freq: %f\n", get_cpu_freq());
while (1) {
do {
ret = sbuf_get(sbuf, (void *)&e);
if (ret == 0)
break;
else if (ret < 0) {
pr_err("sbuf[%u] read error: %d\n", cpuid, ret);
return;
}
fprintf(fp, "%u | %lu | ", cpuid, e.tsc);
switch (e.id) {
/* defined in trace_event.h */
/* for each ev type */
ALL_CASES;
}
} while (ret > 0);
usleep(period);
}
}
static int create_reader(reader_struct * reader, uint32_t cpu)
{
char trace_file_name[TRACE_FILE_NAME_LEN];
snprintf(reader->dev_name, DEV_PATH_LEN, "%s_%u", dev_name, cpu);
reader->param.cpuid = cpu;
reader->dev_fd = open(reader->dev_name, O_RDWR);
if (reader->dev_fd < 0) {
pr_err("Failed to open %s, err %d\n", reader->dev_name, errno);
reader->dev_fd = 0;
return -1;
}
reader->param.sbuf = mmap(NULL, MMAP_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED, reader->dev_fd, 0);
if (reader->param.sbuf == MAP_FAILED) {
pr_err("mmap failed for cpu%d, errno %d\n", cpu, errno);
reader->param.sbuf = NULL;
return -2;
}
pr_dbg("sbuf[%d]:\nmagic_num: %lx\nele_num: %u\n ele_size: %u\n",
cpu, reader->param.sbuf->magic, reader->param.sbuf->ele_num,
reader->param.sbuf->ele_size);
snprintf(trace_file_name, TRACE_FILE_NAME_LEN, "%s/%d", trace_file_dir,
cpu);
reader->param.trace_filep = fopen(trace_file_name, "w+");
if (!reader->param.trace_filep) {
pr_err("Failed to open %s, err %d\n", trace_file_name, errno);
return -3;
}
pr_info("trace data file %s created for %s\n",
trace_file_name, reader->dev_name);
if (pthread_create(&reader->thrd, NULL,
(void *)&reader_fn, &reader->param)) {
pr_err("failed to create reader thread, %d\n", cpu);
return -4;
}
return 0;
}
static void destory_reader(reader_struct * reader)
{
if (reader->thrd) {
pthread_cancel(reader->thrd);
if (pthread_join(reader->thrd, NULL) != 0)
pr_err("failed to cancel thread[%lu]\n", reader->thrd);
else
reader->thrd = 0;
}
if (reader->param.sbuf) {
munmap(reader->param.sbuf, MMAP_SIZE);
reader->param.sbuf = NULL;
}
if (reader->dev_fd) {
close(reader->dev_fd);
reader->dev_fd = 0;
}
if (reader->param.trace_filep) {
fflush(reader->param.trace_filep);
fclose(reader->param.trace_filep);
reader->param.trace_filep = NULL;
}
}
static void handle_on_exit(void)
{
uint32_t cpu;
/* if nothing to release */
if (!(flags & FLAG_TO_REL))
return;
pr_info("exiting - to release resources...\n");
foreach_cpu(cpu)
destory_reader(&reader[cpu]);
}
static void signal_exit_handler(int sig)
{
pr_info("exit on signal %d\n", sig);
exit(0);
}
int main(int argc, char *argv[])
{
uint32_t cpu = 0;
/* parse options */
if (parse_opt(argc, argv))
exit(EXIT_FAILURE);
/* how many cpus */
pcpu_num = get_cpu_num();
reader = malloc(sizeof(reader_struct) * pcpu_num);
if (!reader) {
pr_err("Failed to allocate reader memory\n");
exit(EXIT_FAILURE);
}
memset(reader, 0, sizeof(reader_struct) * pcpu_num);
/* create dir for trace file */
if (create_trace_file_dir(trace_file_dir)) {
pr_err("Failed to create dir for trace files\n");
exit(EXIT_FAILURE);
}
atexit(handle_on_exit);
/* acquair res for each trace dev */
flags |= FLAG_TO_REL;
foreach_cpu(cpu)
if (create_reader(&reader[cpu], cpu) < 0)
goto out_free;
/* for kill exit handling */
signal(SIGTERM, signal_exit_handler);
signal(SIGINT, signal_exit_handler);
/* wait for user input to stop */
printf("q <enter> to quit:\n");
while (getchar() != 'q')
printf("q <enter> to quit:\n");
out_free:
foreach_cpu(cpu)
destory_reader(&reader[cpu]);
free(reader);
flags &= ~FLAG_TO_REL;
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "sbuf.h"
#define PCPU_NUM 4
#define TRACE_ELEMENT_SIZE 32 /* byte */
#define TRACE_ELEMENT_NUM ((4 * 1024 * 1024 - 64) / TRACE_ELEMENT_SIZE)
#define PAGE_SIZE 4096
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define MMAP_SIZE (4 * 1024 * 1024)
/*
#define MMAP_SIZE ((TRACE_ELEMENT_SIZE * TRACE_ELEMENT_NUM \
+ PAGE_SIZE - 1) & PAGE_MASK)
*/
#define TRACE_FILE_NAME_LEN 36
#define TRACE_FILE_DIR_LEN (TRACE_FILE_NAME_LEN - 2)
#define TRACE_FILE_ROOT "/tmp/acrntrace/"
#define DEV_PATH_LEN 18
#define TIME_STR_LEN 16
#define CMD_MAX_LEN 48
#define pr_fmt(fmt) "acrntrace: " fmt
#define pr_info(fmt, ...) printf(pr_fmt(fmt), ##__VA_ARGS__)
#define pr_err(fmt, ...) printf(pr_fmt(fmt), ##__VA_ARGS__)
#ifdef DEBUG
#define pr_dbg(fmt, ...) printf(pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_dbg(fmt, ...)
#endif
/*
* flags:
* FLAG_TO_REL - resources need to be release
* FLAG_CLEAR_BUF - to clear buffered old data
*/
#define FLAG_TO_REL (1UL << 0)
#define FLAG_CLEAR_BUF (1UL << 1)
#define foreach_cpu(cpu) \
for ((cpu) = 0; (cpu) < (pcpu_num); (cpu)++)
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned long uint64_t;
typedef struct {
uint64_t tsc;
uint64_t id;
union {
struct {
uint32_t a, b, c, d;
};
struct {
uint8_t a1, a2, a3, a4;
uint8_t b1, b2, b3, b4;
uint8_t c1, c2, c3, c4;
uint8_t d1, d2, d3, d4;
};
struct {
uint64_t e;
uint64_t f;
};
char str[16];
};
} trace_ev_t;
typedef struct {
uint32_t cpuid;
int exit_flag;
FILE *trace_filep;
shared_buf_t *sbuf;
pthread_mutex_t *sbuf_lock;
} param_t;
typedef struct {
int dev_fd;
char dev_name[DEV_PATH_LEN];
pthread_t thrd;
param_t param;
} reader_struct;

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <asm/errno.h>
#include <string.h>
#include <stdbool.h>
#include "sbuf.h"
static inline bool sbuf_is_empty(shared_buf_t *sbuf)
{
return (sbuf->head == sbuf->tail);
}
static inline uint32_t sbuf_next_ptr(uint32_t pos,
uint32_t span, uint32_t scope)
{
pos += span;
pos = (pos >= scope) ? (pos - scope) : pos;
return pos;
}
int sbuf_get(shared_buf_t *sbuf, uint8_t *data)
{
const void *from;
if ((sbuf == NULL) || (data == NULL))
return -EINVAL;
if (sbuf_is_empty(sbuf)) {
/* no data available */
return 0;
}
from = (void *)sbuf + SBUF_HEAD_SIZE + sbuf->head;
memcpy(data, from, sbuf->ele_size);
sbuf->head = sbuf_next_ptr(sbuf->head, sbuf->ele_size, sbuf->size);
return sbuf->ele_size;
}
int sbuf_clear_buffered(shared_buf_t *sbuf)
{
if (sbuf == NULL)
return -EINVAL;
sbuf->head = sbuf->tail;
return 0;
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SHARED_BUF_H
#define SHARED_BUF_H
#include <linux/types.h>
#define SBUF_MAGIC 0x5aa57aa71aa13aa3
#define SBUF_MAX_SIZE (1ULL << 22)
#define SBUF_HEAD_SIZE 64
/* sbuf flags */
#define OVERRUN_CNT_EN (1ULL << 0) /* whether overrun counting is enabled */
#define OVERWRITE_EN (1ULL << 1) /* whether overwrite is enabled */
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned long uint64_t;
/**
* (sbuf) head + buf (store (ele_num - 1) elements at most)
* buffer empty: tail == head
* buffer full: (tail + ele_size) % size == head
*
* Base of memory for elements
* |
* |
* ---------------------------------------------------------------------------------------
* | shared_buf_t | raw data (ele_size)| raw date (ele_size) | ... | raw data (ele_size) |
* ---------------------------------------------------------------------------------------
* |
* |
* shared_buf_t *buf
*/
/* Make sure sizeof(shared_buf_t) == SBUF_HEAD_SIZE */
typedef struct shared_buf {
uint64_t magic;
uint32_t ele_num; /* number of elements */
uint32_t ele_size; /* sizeof of elements */
uint32_t head; /* offset from base, to read */
uint32_t tail; /* offset from base, to write */
uint64_t flags;
uint32_t overrun_cnt; /* count of overrun */
uint32_t size; /* ele_num * ele_size */
uint32_t padding[6];
} shared_buf_t;
static inline void sbuf_clear_flags(shared_buf_t *sbuf, uint64_t flags)
{
sbuf->flags &= ~flags;
}
static inline void sbuf_set_flags(shared_buf_t *sbuf, uint64_t flags)
{
sbuf->flags = flags;
}
static inline void sbuf_add_flags(shared_buf_t *sbuf, uint64_t flags)
{
sbuf->flags |= flags;
}
int sbuf_get(shared_buf_t *sbuf, uint8_t *data);
int sbuf_clear_buffered(shared_buf_t *sbuf);
#endif /* SHARED_BUF_H */

View File

@ -0,0 +1,198 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TRACE_EVENT_H
#define TRACE_EVENT_H
#define GEN_CASE(id) case (id):{ id##_FMT; break; }
/* TIMER */
#define TRACE_TIMER_ACTION_ADDED 0x1
#define TRACE_TIMER_ACTION_PCKUP 0x2
#define TRACE_TIMER_ACTION_UPDAT 0x3
#define TRACE_TIMER_IRQ 0x4
#define TRACE_VM_EXIT 0x10
#define TRACE_VM_ENTER 0X11
#define TRC_VMEXIT_ENTRY 0x10000
#define TRC_VMEXIT_EXCEPTION_OR_NMI (TRC_VMEXIT_ENTRY + 0x00000000)
#define TRC_VMEXIT_EXTERNAL_INTERRUPT (TRC_VMEXIT_ENTRY + 0x00000001)
#define TRC_VMEXIT_INTERRUPT_WINDOW (TRC_VMEXIT_ENTRY + 0x00000002)
#define TRC_VMEXIT_CPUID (TRC_VMEXIT_ENTRY + 0x00000004)
#define TRC_VMEXIT_RDTSC (TRC_VMEXIT_ENTRY + 0x00000010)
#define TRC_VMEXIT_VMCALL (TRC_VMEXIT_ENTRY + 0x00000012)
#define TRC_VMEXIT_CR_ACCESS (TRC_VMEXIT_ENTRY + 0x0000001C)
#define TRC_VMEXIT_IO_INSTRUCTION (TRC_VMEXIT_ENTRY + 0x0000001E)
#define TRC_VMEXIT_RDMSR (TRC_VMEXIT_ENTRY + 0x0000001F)
#define TRC_VMEXIT_WRMSR (TRC_VMEXIT_ENTRY + 0x00000020)
#define TRC_VMEXIT_EPT_VIOLATION (TRC_VMEXIT_ENTRY + 0x00000030)
#define TRC_VMEXIT_EPT_MISCONFIGURATION (TRC_VMEXIT_ENTRY + 0x00000031)
#define TRC_VMEXIT_RDTSCP (TRC_VMEXIT_ENTRY + 0x00000033)
#define TRC_VMEXIT_APICV_WRITE (TRC_VMEXIT_ENTRY + 0x00000038)
#define TRC_VMEXIT_APICV_ACCESS (TRC_VMEXIT_ENTRY + 0x00000039)
#define TRC_VMEXIT_APICV_VIRT_EOI (TRC_VMEXIT_ENTRY + 0x0000003A)
#define TRC_VMEXIT_UNHANDLED 0x20000
#define TRACE_CUSTOM 0xFC
#define TRACE_FUNC_ENTER 0xFD
#define TRACE_FUNC_EXIT 0xFE
#define TRACE_STR 0xFF
/* TRACE_EVENTID_MAX 256 */
#define PR(fmt, ...) fprintf((fp), fmt, ##__VA_ARGS__);
#define TRACE_TIMER_ACTION_ADDED_FMT \
{PR("TIMER_ACTION ADDED: ID %d, deadline %lx total %d\n", \
(e).a, ((uint64_t)((e).c)<<32)|(e).b, (e).d); }
#define TRACE_TIMER_ACTION_PCKUP_FMT \
{PR("TIMER_ACTION PCKUP: ID %d, deadline %lx total %d\n", \
(e).a, ((uint64_t)((e).c)<<32)|(e).b, (e).d); }
#define TRACE_TIMER_ACTION_UPDAT_FMT \
{PR("TIMER_ACTION UPDAT: ID %d, deadline %lx total %d\n", \
(e).a, ((unsigned long)((e).c)<<32)|(e).b, (e).d); }
#define TRACE_TIMER_IRQ_FMT \
PR("TIMER_IRQ total: %lx\n", (e).e)
#define TRACE_CUSTOM_FMT \
PR("CUSTOM: 0x%lx 0x%lx\n", (e).e, (e).f)
#define TRACE_FUNC_ENTER_FMT \
PR("ENTER: %s\n", (e).str)
#define TRACE_FUNC_EXIT_FMT \
PR("EXIT : %s\n", (e).str)
#define TRACE_STR_FMT \
PR("STR: %s\n", (e).str)
#define TRACE_VM_EXIT_FMT \
PR("VM_EXIT: exit_reason 0x%016lx, guest_rip 0x%016lx\n", \
(e).e, (e).f)
#define TRACE_VM_ENTER_FMT \
PR("VM_ENTER:\n")
#define TRC_VMEXIT_EXCEPTION_OR_NMI_FMT \
PR("VMEXIT_EXCEPTION_OR_NMI: \
vec 0x%08x, err_code 0x%08x, type %d\n", \
(e).a, (e).b, (e).c)
#define TRC_VMEXIT_EXTERNAL_INTERRUPT_FMT \
PR("VMEXIT_EXTERNAL_INTERRUPT: vec 0x%08lx\n", (e).e)
#define TRC_VMEXIT_INTERRUPT_WINDOW_FMT \
PR("VMEXIT_INTERRUPT_WINDOW:\n")
#define TRC_VMEXIT_CPUID_FMT \
PR("VMEXIT_CPUID: vcpuid %lu\n", (e).e)
#define TRC_VMEXIT_RDTSC_FMT \
PR("VMEXIT_RDTSC: host_tsc 0x%016lx, tsc_offset 0x%016lx\n", \
(e).e, (e).f)
#define TRC_VMEXIT_VMCALL_FMT \
PR("VMEXIT_VMCALL: vmid %lu, hypercall_id %lu\n", \
(e).e, (e).f)
#define TRC_VMEXIT_CR_ACCESS_FMT \
PR("VMEXIT_CR_ACCESS: op %s, rn_nr %lu\n", \
(e).e?"Read":"Write", (e).f)
#define TRC_VMEXIT_IO_INSTRUCTION_FMT \
PR("VMEXIT_IO_INSTRUCTION: \
port %u, dir %u, sz %u, cur_ctx_idx %u\n", \
(e).a, (e).b, (e).c, (e).d)
#define TRC_VMEXIT_RDMSR_FMT \
PR("VMEXIT_RDMSR: msr 0x%08lx, val 0x%08lx\n", \
(e).e, (e).f)
#define TRC_VMEXIT_WRMSR_FMT \
PR("VMEXIT_WRMSR: msr 0x%08lx, val 0x%08lx\n", \
(e).e, (e).f)
#define TRC_VMEXIT_EPT_VIOLATION_FMT \
PR("VMEXIT_EPT_VIOLATION: qual 0x%016lx, gpa 0x%016lx\n", \
(e).e, (e).f)
#define TRC_VMEXIT_EPT_MISCONFIGURATION_FMT \
PR("VMEXIT_EPT_MISCONFIGURATION:\n")
#define TRC_VMEXIT_RDTSCP_FMT \
PR("VMEXIT_RDTSCP: guest_tsc 0x%lx, tsc_aux 0x%lx\n", \
(e).e, (e).f)
#define TRC_VMEXIT_APICV_WRITE_FMT \
PR("VMEXIT_APICV_WRITE: offset 0x%lx\n", (e).e)
#define TRC_VMEXIT_APICV_ACCESS_FMT \
PR("VMEXIT_APICV_ACCESS:\n")
#define TRC_VMEXIT_APICV_VIRT_EOI_FMT \
PR("VMEXIT_APICV_VIRT_EOI: vec 0x%08lx\n", (e).e)
#define TRC_VMEXIT_UNHANDLED_FMT \
PR("VMEXIT_UNHANDLED: 0x%08lx\n", (e).e)
#define ALL_CASES \
GEN_CASE(TRACE_TIMER_ACTION_ADDED); \
GEN_CASE(TRACE_TIMER_ACTION_PCKUP); \
GEN_CASE(TRACE_TIMER_ACTION_UPDAT); \
GEN_CASE(TRACE_TIMER_IRQ); \
GEN_CASE(TRACE_CUSTOM); \
GEN_CASE(TRACE_STR); \
GEN_CASE(TRACE_FUNC_ENTER); \
GEN_CASE(TRACE_FUNC_EXIT); \
GEN_CASE(TRACE_VM_EXIT); \
GEN_CASE(TRACE_VM_ENTER); \
GEN_CASE(TRC_VMEXIT_EXCEPTION_OR_NMI); \
GEN_CASE(TRC_VMEXIT_EXTERNAL_INTERRUPT);\
GEN_CASE(TRC_VMEXIT_INTERRUPT_WINDOW); \
GEN_CASE(TRC_VMEXIT_CPUID); \
GEN_CASE(TRC_VMEXIT_RDTSC); \
GEN_CASE(TRC_VMEXIT_VMCALL); \
GEN_CASE(TRC_VMEXIT_CR_ACCESS); \
GEN_CASE(TRC_VMEXIT_IO_INSTRUCTION); \
GEN_CASE(TRC_VMEXIT_RDMSR); \
GEN_CASE(TRC_VMEXIT_WRMSR); \
GEN_CASE(TRC_VMEXIT_EPT_VIOLATION); \
GEN_CASE(TRC_VMEXIT_EPT_MISCONFIGURATION);\
GEN_CASE(TRC_VMEXIT_RDTSCP); \
GEN_CASE(TRC_VMEXIT_APICV_WRITE); \
GEN_CASE(TRC_VMEXIT_APICV_ACCESS); \
GEN_CASE(TRC_VMEXIT_APICV_VIRT_EOI); \
GEN_CASE(TRC_VMEXIT_UNHANDLED); \
#endif /* TRACE_EVENT_H */