From: Philippe Proulx Date: Wed, 13 Apr 2016 19:52:48 +0000 (-0400) Subject: barectf-tracepoint: add QEMU ARM target example X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=69e3ffe8863ec4d3ef542f4fd835fd4378d43831;p=deliverable%2Fbarectf.git barectf-tracepoint: add QEMU ARM target example Signed-off-by: Philippe Proulx --- diff --git a/doc/examples/barectf-tracepoint/.gitignore b/doc/examples/barectf-tracepoint/.gitignore new file mode 100644 index 0000000..b288a24 --- /dev/null +++ b/doc/examples/barectf-tracepoint/.gitignore @@ -0,0 +1,5 @@ +barectf-tracepoint-barectf-linux-fs +barectf-tracepoint-barectf-qemu-arm-uart +barectf-tracepoint-lttng-ust +ctf-linux-fs +ctf-qemu-arm-uart diff --git a/doc/examples/barectf-tracepoint/Makefile.barectf-qemu-arm-uart b/doc/examples/barectf-tracepoint/Makefile.barectf-qemu-arm-uart new file mode 100644 index 0000000..073bc2b --- /dev/null +++ b/doc/examples/barectf-tracepoint/Makefile.barectf-qemu-arm-uart @@ -0,0 +1,45 @@ +BARECTF ?= barectf +ARCH = arm-none-eabi + +RM = rm -rf +MKDIR = mkdir -p +CC = $(ARCH)-gcc + +VERSION = qemu-arm-uart +CPU=arm926ej-s +EXTRA_DIR = ../../../extra +CFLAGS = -DWITH_QEMU_ARM_UART=1 -ffunction-sections -mcpu=$(CPU) -O2 -Wall -pedantic -std=gnu99 -I$(EXTRA_DIR) -I. +LDFLAGS= -T barectf-platform-$(VERSION).ld -lc -lnosys + +TARGET = barectf-tracepoint-barectf-$(VERSION) +OBJS = $(TARGET).o barectf-$(VERSION).o barectf-platform-$(VERSION).o +TRACEDIR = ctf-$(VERSION) + +.PHONY: all clean sim + +all: $(TARGET) + +$(TRACEDIR): + $(MKDIR) $@ + +$(TARGET): $(OBJS) + $(CC) -o $@ $^ $(LDFLAGS) + +$(TRACEDIR)/metadata barectf-bitfield.h barectf.h barectf.c: config.yaml $(TRACEDIR) + $(BARECTF) $< -m $(TRACEDIR) + +barectf-$(VERSION).o: barectf.c + $(CC) -o $@ $(CFLAGS) -c $< + +barectf-platform-$(VERSION).o: barectf-platform-$(VERSION).c + $(CC) $(CFLAGS) -c $< + +$(TARGET).o: barectf-tracepoint.c barectf-tracepoint-$(VERSION).h barectf.h barectf-bitfield.h + $(CC) -o $@ $(CFLAGS) -c $< + +clean: + $(RM) $(TARGET) $(OBJS) $(TRACEDIR) + $(RM) barectf.h barectf-bitfield.h barectf.c + +sim: $(TARGET) + ./barectf-tracepoint-barectf-qemu-arm-uart.sh diff --git a/doc/examples/barectf-tracepoint/README.md b/doc/examples/barectf-tracepoint/README.md index ba5a9a9..5093d50 100644 --- a/doc/examples/barectf-tracepoint/README.md +++ b/doc/examples/barectf-tracepoint/README.md @@ -1,31 +1,32 @@ # Example using `barectf-tracepoint.h` -This example is based on the [linux-fs-simple example](../linux-fs-simple), -but it uses the `tracepoint()` macro defined in +This example is based on the [linux-fs-simple example](../linux-fs-simple) +example, but it uses the `tracepoint()` macro defined in [`barectf-tracepoint.h`](../../../extra/barectf-tracepoint.h) instead of calling the generated tracing functions directly. This example also shows the compatibility with [LTTng-UST](http://lttng.org/) that this `barectf-tracepoint.h` allows. +This example also includes a QEMU ARM target to simulate barectf used by +a true bare-metal application. -## Building +All the targets of this example use the same application source: +[`barectf-tracepoint.c`](barectf-tracepoint.c). -To build both barectf and LTTng-UST targets, make sure both tools are -installed, and do: - make +## barectf tracing -To build only the example using barectf: +### linux-fs platform - make -f Makefile.barectf-linux-fs +#### Building -To build only the example using LTTng-UST: +Do: - make -f Makefile.lttng-ust + make -f Makefile.barectf-linux-fs -## barectf tracing +#### Running Run this example: @@ -39,8 +40,79 @@ as string fields in the events of the binary stream, e.g.: ./barectf-tracepoint-barectf-linux-fs this argument and this one will be recorded +### QEMU ARM platform + +#### Building + +To build this example, you need an ARM cross-compiler toolchain +(`gcc-arm-none-eabi`, `binutils-arm-none-eabi`, and +`libnewlib-arm-none-eabi` Ubuntu packages), then do: + + make -f Makefile.barectf-qemu-arm-uart + + +#### Running + +To run this example, you need `qemu-system-arm` (`qemu-system-arm` +Ubuntu package). + +Run this example: + + make -f Makefile.barectf-qemu-arm-uart sim + +The complete CTF trace is written to the `ctf-qemu-arm-uart` directory. + + +#### What happens when running? + +When you run this example, here's what happens: + + 1. The `barectf-tracepoint-barectf-qemu-arm-uart.sh` Bash script + is executed. + 2. This Bash script executes `qemu-system-arm` with the appropriate + options to simulate the bare-metal application on an ARM system. + The simulated board is a Versatile platform baseboard from ARM. The + simulated CPU is an ARM926EJ-S. This is a 2001 ARM9 core + implementing the ARMv5TE architecture. QEMU is set to execute the + `barectf-tracepoint-barectf-qemu-arm-uart` ELF file (previously + built), and to connect the board's first UART with QEMU's standard + input/output streams, and the board's second UART to the + `ctf-qemu-arm-uart/stream` file (output only). The Bash script + reads each line printed by QEMU, and kills the QEMU process when + it reads the ending line written by the bare-metal application. + 3. QEMU starts. Eventually, the bare-metal application's + `main()` function is called. + 4. `main()` calls `init_tracing()`, which for this example, calls + `barectf_platform_qemu_arm_uart_init()`. This is a custom barectf + platform created specifically for this example. The platform + initializes a barectf context to get its clock source from a timer + on the simulated board, and to flush its packets by writing the + bytes to the second UART (which is connected to the + `ctf-qemu-arm-uart/stream` file by QEMU). The platform uses a + global buffer of 4 kiB to hold the current packet. + 5. `main()` calls `trace_stuff()` which contains the `tracepoint()` + macro invocations. Events are recorded to the current packet by + the barectf machinery. When this packet is full, it is flushed + by the platform to the second UART. + 6. `main()` calls `fini_tracing()`, which calls + `barectf_platform_qemu_arm_uart_fini()`, which prints the + ending line that `barectf-tracepoint-barectf-qemu-arm-uart.sh` + is waiting for to kill QEMU. + + ## LTTng-UST tracing +### Building + +Make sure [LTTng-UST](http://lttng.org/) is installed. + +Do: + + make -f Makefile.lttng-ust + + +### Running + Create an LTTng tracing session: lttng create my-session diff --git a/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.c b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.c new file mode 100644 index 0000000..352d0aa --- /dev/null +++ b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.c @@ -0,0 +1,107 @@ +#include +#include +#include + +#include "barectf-platform-qemu-arm-uart.h" + +#define BUF_SIZE 4096 +#define TIMER_CTRL_32BIT (1 << 1) +#define TIMER_CTRL_ENABLE (1 << 7) + +volatile uint32_t * const uart0 = (uint32_t *) 0x101f1000; +volatile uint32_t * const uart1 = (uint32_t *) 0x101f2000; +volatile uint32_t * const timer0_ctrl = (uint32_t *) 0x101e2008; +volatile uint32_t * const timer0_value = (uint32_t *) 0x101e2004; + +static struct barectf_default_ctx barectf_ctx; + +static uint8_t buf[BUF_SIZE]; + +static uint64_t get_clock(void* data) +{ + return (uint64_t) -*timer0_value; +} + +static void flush_packet(void) +{ + size_t i; + + /* flush packet to UART 1 */ + for (i = 0; i < BUF_SIZE; ++i) { + *uart1 = (uint32_t) buf[i]; + } +} + +static int is_backend_full(void *data) +{ + return 0; +} + +static void open_packet(void *data) +{ + barectf_default_open_packet(&barectf_ctx); +} + +static void close_packet(void *data) +{ + /* close packet now */ + barectf_default_close_packet(&barectf_ctx); + + /* flush current packet */ + flush_packet(); +} + +void barectf_platform_qemu_arm_uart_init(void) +{ + struct barectf_platform_callbacks cbs = { + .default_clock_get_value = get_clock, + .is_backend_full = is_backend_full, + .open_packet = open_packet, + .close_packet = close_packet, + }; + + /* enable/start timer (clock source) */ + *timer0_ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE; + + /* initialize barectf context */ + barectf_init(&barectf_ctx, buf, BUF_SIZE, cbs, NULL); + + /* open first packet */ + open_packet(NULL); + + /* indicate that tracing is starting */ + puts("tracing: starting"); +} + +void barectf_platform_qemu_arm_uart_fini(void) +{ + /* close last packet if it contains at least one event */ + if (barectf_packet_is_open(&barectf_ctx) && + !barectf_packet_is_empty(&barectf_ctx)) { + close_packet(NULL); + } + + /* indicate that tracing is done */ + puts("tracing: done"); +} + +struct barectf_default_ctx *barectf_platform_qemu_arm_uart_get_barectf_ctx() +{ + return &barectf_ctx; +} + +#define STDOUT 1 +#define STDERR 2 + +/* custom write "syscall" for newlib's stdio: write to UART 0 */ +int _write(int file, char *ptr, int len) { + if (file == STDOUT || file == STDERR) { + int i; + + for (i = 0; i < len; i++) { + *uart0 = (uint32_t) ptr[i]; + } + } + + return 0; +} diff --git a/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.h b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.h new file mode 100644 index 0000000..5bf31c0 --- /dev/null +++ b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.h @@ -0,0 +1,10 @@ +#ifndef _BARECTF_PLATFORM_QEMU_ARM_UART +#define _BARECTF_PLATFORM_QEMU_ARM_UART + +#include + +void barectf_platform_qemu_arm_uart_init(void); +void barectf_platform_qemu_arm_uart_fini(void); +struct barectf_default_ctx *barectf_platform_qemu_arm_uart_get_barectf_ctx(void); + +#endif /* _BARECTF_PLATFORM_QEMU_ARM_UART */ diff --git a/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.ld b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.ld new file mode 100644 index 0000000..5e80b8e --- /dev/null +++ b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.ld @@ -0,0 +1,38 @@ +MEMORY { + SDRAM (XRW) : ORIGIN = 0x00000000, LENGTH = 0x08000000 +} + +/* heap size */ +heap_size = 0x10000; + +/* define stack base (grows downwards), used in newlib's crt0.S */ +__stack = ORIGIN(SDRAM) + LENGTH(SDRAM); + +/* libc's entry point */ +ENTRY(_mainCRTStartup); + +SECTIONS { + /* QEMU starts executing at 0x10000 */ + . = 0x10000; + + .text : { + *(.text) + *(.text.*) + } > SDRAM + + .data : { + *(.data) + *(.data.*) + } > SDRAM + + .bss : { + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + __bss_end__ = .; + } > SDRAM + + /* "end" symbol needed by newlib's _sbrk */ + end = .; +} diff --git a/doc/examples/barectf-tracepoint/barectf-tracepoint-barectf-qemu-arm-uart.sh b/doc/examples/barectf-tracepoint/barectf-tracepoint-barectf-qemu-arm-uart.sh new file mode 100755 index 0000000..f70eb79 --- /dev/null +++ b/doc/examples/barectf-tracepoint/barectf-tracepoint-barectf-qemu-arm-uart.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +qemu-system-arm -M versatilepb -m 128M -nographic -monitor none \ + -kernel barectf-tracepoint-barectf-qemu-arm-uart \ + -serial stdio -serial file:ctf-qemu-arm-uart/stream | +{ + while read line; do + echo "$line" + + if [ x"$line" = x"tracing: done" ]; then + pkill -nf file:ctf-qemu-arm-uart + fi + done +} diff --git a/doc/examples/barectf-tracepoint/barectf-tracepoint-qemu-arm-uart.h b/doc/examples/barectf-tracepoint/barectf-tracepoint-qemu-arm-uart.h new file mode 100644 index 0000000..aeae485 --- /dev/null +++ b/doc/examples/barectf-tracepoint/barectf-tracepoint-qemu-arm-uart.h @@ -0,0 +1,36 @@ +#ifndef _BARECTF_TRACEPOINT_QEMU_ARM_UART +#define _BARECTF_TRACEPOINT_QEMU_ARM_UART + +#include + +/* + * Include generated barectf header file: this contains the prefix and + * default stream name to be used by the tracepoint() macro. + */ +#include "barectf.h" + +/* define how the context is to be found by tracepoint() calls */ +#define BARECTF_TRACEPOINT_CTX (global_barectf_ctx) + +/* then include this: */ +#include + +/* global barectf context (default stream) */ +static struct barectf_default_ctx *global_barectf_ctx; + +/* init function for this version */ +static void init_tracing(void) +{ + /* initialize platform */ + barectf_platform_qemu_arm_uart_init(); + global_barectf_ctx = barectf_platform_qemu_arm_uart_get_barectf_ctx(); +} + +/* finalization function for this version */ +static void fini_tracing(void) +{ + /* finalize platform */ + barectf_platform_qemu_arm_uart_fini(); +} + +#endif /* _BARECTF_TRACEPOINT_QEMU_ARM_UART */ diff --git a/doc/examples/barectf-tracepoint/barectf-tracepoint.c b/doc/examples/barectf-tracepoint/barectf-tracepoint.c index 41708d2..ca0f794 100644 --- a/doc/examples/barectf-tracepoint/barectf-tracepoint.c +++ b/doc/examples/barectf-tracepoint/barectf-tracepoint.c @@ -5,6 +5,8 @@ #if defined(WITH_LTTNG_UST) #include "barectf-tracepoint-lttng-ust.h" +#elif defined(WITH_QEMU_ARM_UART) +#include "barectf-tracepoint-qemu-arm-uart.h" #else #include "barectf-tracepoint-linux-fs.h" #endif @@ -24,16 +26,10 @@ static void trace_stuff(int argc, char *argv[]) /* record 40000 events */ for (i = 0; i < 5000; ++i) { + str = argv[i % argc]; tracepoint(barectf_tp, simple_uint32, i * 1500); tracepoint(barectf_tp, simple_int16, -i * 2); tracepoint(barectf_tp, simple_float, (float) i / 1.23); - - if (argc > 0) { - str = argv[i % argc]; - } else { - str = "hello there!"; - } - tracepoint(barectf_tp, simple_string, str); tracepoint(barectf_tp, simple_enum, RUNNING); tracepoint(barectf_tp, a_few_fields, -1, 301, -3.14159, @@ -44,9 +40,26 @@ static void trace_stuff(int argc, char *argv[]) } } +#define NUM_STRINGS 5 + +static char *strings[] = { + "orange", + "mandarine", + "lemon", + "lime", + "grapefruit", +}; + int main(int argc, char *argv[]) { init_tracing(); + + if (argc <= 1) { + /* use static strings if there's nothing interesting in argv */ + argc = NUM_STRINGS; + argv = strings; + } + trace_stuff(argc, argv); fini_tracing();