mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-21 05:02:24 +00:00
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:
parent
c730806a36
commit
99c69c7773
5
devicemodel/tools/acrntrace/Makefile
Normal file
5
devicemodel/tools/acrntrace/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
all:
|
||||
gcc -o acrntrace acrntrace.c sbuf.c -I. -lpthread
|
||||
|
||||
clean:
|
||||
rm acrntrace
|
381
devicemodel/tools/acrntrace/acrntrace.c
Normal file
381
devicemodel/tools/acrntrace/acrntrace.c
Normal 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;
|
||||
}
|
110
devicemodel/tools/acrntrace/acrntrace.h
Normal file
110
devicemodel/tools/acrntrace/acrntrace.h
Normal 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;
|
78
devicemodel/tools/acrntrace/sbuf.c
Normal file
78
devicemodel/tools/acrntrace/sbuf.c
Normal 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;
|
||||
}
|
94
devicemodel/tools/acrntrace/sbuf.h
Normal file
94
devicemodel/tools/acrntrace/sbuf.h
Normal 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 */
|
198
devicemodel/tools/acrntrace/trace_event.h
Normal file
198
devicemodel/tools/acrntrace/trace_event.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user