From 062881a4846623d3ac467da734890b11d89871ca Mon Sep 17 00:00:00 2001 From: Johannes Schlatow Date: Fri, 20 May 2022 15:28:21 +0200 Subject: [PATCH] trace: add types for ctf tracing genodelabs/genode#4352 --- repos/gems/include/ctf/event_header.h | 45 +++++++++ repos/gems/include/ctf/events/named.h | 34 +++++++ repos/gems/include/ctf/packet_types.h | 133 ++++++++++++++++++++++++++ repos/gems/include/ctf/timestamp.h | 40 ++++++++ repos/gems/recipes/api/ctf/content.mk | 8 ++ repos/gems/recipes/api/ctf/hash | 1 + 6 files changed, 261 insertions(+) create mode 100644 repos/gems/include/ctf/event_header.h create mode 100644 repos/gems/include/ctf/events/named.h create mode 100644 repos/gems/include/ctf/packet_types.h create mode 100644 repos/gems/include/ctf/timestamp.h create mode 100644 repos/gems/recipes/api/ctf/content.mk create mode 100644 repos/gems/recipes/api/ctf/hash diff --git a/repos/gems/include/ctf/event_header.h b/repos/gems/include/ctf/event_header.h new file mode 100644 index 0000000000..3a1bd972b6 --- /dev/null +++ b/repos/gems/include/ctf/event_header.h @@ -0,0 +1,45 @@ +/* + * \brief Generic type for CTF event headers + * \author Johannes Schlatow + * \date 2021-08-03 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _CTF__EVENT_HEADER_H_ +#define _CTF__EVENT_HEADER_H_ + +#include +#include +#include + +namespace Ctf { + using namespace Genode::Trace; + + struct Event_header_base; +} + +/** + * Base type for CTF trace events. The event type is identifed by its id. + */ +struct Ctf::Event_header_base +{ + const uint8_t _id; + Timestamp_base _timestamp { (Timestamp_base)Trace::timestamp() }; + + Timestamp_base timestamp() const { return _timestamp; } + void timestamp(Timestamp_base ts) { _timestamp = ts; } + + Event_header_base(uint8_t id) + : _id(id) + { } + +} __attribute__((packed)); + + +#endif /* _CTF__EVENT_HEADER_H_ */ diff --git a/repos/gems/include/ctf/events/named.h b/repos/gems/include/ctf/events/named.h new file mode 100644 index 0000000000..13efdef9ef --- /dev/null +++ b/repos/gems/include/ctf/events/named.h @@ -0,0 +1,34 @@ +/* + * \brief Ctf trace event for logging names + * \author Johannes Schlatow + * \date 2021-08-03 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _CTF__EVENTS__NAMED_H_ +#define _CTF__EVENTS__NAMED_H_ + +#include + +namespace Ctf { + struct Named_event; +} + +/** + * Base type for CTF trace events with a string as payload. + */ +struct Ctf::Named_event +{ + char _name[0]; + + Named_event(const char *name, size_t len) { + Genode::copy_cstring(_name, name, len); } +} __attribute__((packed)); + +#endif /* _CTF__EVENTS__NAMED_H_ */ diff --git a/repos/gems/include/ctf/packet_types.h b/repos/gems/include/ctf/packet_types.h new file mode 100644 index 0000000000..5e4d7a6ed8 --- /dev/null +++ b/repos/gems/include/ctf/packet_types.h @@ -0,0 +1,133 @@ +/* + * \brief Packet header and context types + * \author Johannes Schlatow + * \date 2021-08-04 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _CTF__PACKET_TYPES_H_ +#define _CTF__PACKET_TYPES_H_ + +#include +#include +#include + +namespace Ctf { + using namespace Genode; + using Genode::Trace::Thread_name; + struct Packet_header; +} + +/** + * Definition of our CTF packet header. A CTF stream may contain multiple + * packets that bundle an arbitrary number of events. In order to reduce the + * payload for every CTF event, we put shared information (such as session and + * thread name) into the packet header. + * + * See https://diamon.org/ctf/ for the CTF spec. + */ +struct Ctf::Packet_header +{ + uint32_t _magic { 0xC1FC1FC1 }; + uint32_t _stream_id { }; + Timestamp_base _timestamp_start { }; + Timestamp_base _timestamp_end { }; + uint32_t _total_length { }; + uint16_t _hdr_length { sizeof(Packet_header) * 8 }; + uint16_t _affinity { }; + uint8_t _priority { }; + char _session_and_thread[0] { }; + + struct Affinity : Register<16> + { + struct Xpos : Bitfield<0,4> { }; + struct Ypos : Bitfield<4,4> { }; + struct Width : Bitfield<8,4> { }; + struct Height : Bitfield<12,4> { }; + }; + + Packet_header(Session_label const &label, + Thread_name const &thread, + Genode::Affinity::Location const &affinity, + unsigned priority, + Genode::size_t buflen, + unsigned streamid=0) + : _stream_id(streamid), + _affinity(Affinity::Xpos::bits((uint16_t)affinity.xpos()) | + Affinity::Ypos::bits((uint16_t)affinity.ypos()) | + Affinity::Width::bits((uint16_t)affinity.width()) | + Affinity::Height::bits((uint16_t)affinity.height())), + _priority((uint8_t)priority) + { + Genode::size_t char_offset = 0; + + if (_hdr_length/8 < buflen) { + Genode::size_t sess_len = Genode::min(label.length(), buflen - _hdr_length/8); + Genode::copy_cstring(&_session_and_thread[char_offset], label.string(), sess_len); + _hdr_length += (uint16_t)(sess_len * 8); + char_offset = sess_len; + } + + if (_hdr_length/8 < buflen) { + Genode::size_t thread_len = Genode::min(thread.length(), buflen - _hdr_length/8); + Genode::copy_cstring(&_session_and_thread[char_offset], thread.string(), thread_len); + _hdr_length += (uint16_t)(thread_len * 8); + } + + _total_length = _hdr_length; + } + + void reset() + { + _total_length = _hdr_length; + _timestamp_start = 0; + _timestamp_end = 0; + } + + /** + * If event fits into provided buffer, update struct with timestamp and + * length of new event. Makes sure that timestamps are monotonically + * increasing and calls the provided functor(char * ptr, Timestamp_base ts), + * where ptr is the target address and ts is the updated timestamp. + */ + template + void append_event(char * buffer, + Genode::size_t bufsz, + Timestamp_base timestamp, + Genode::size_t length, + FUNC && fn) + { + using Ctf::Timestamp; + + /* check whether event fits into buffer */ + if (total_length_bytes()+length > bufsz) + return; + + /* update timestamps */ + if (_timestamp_start == 0) + _timestamp_start = timestamp; + else if (Timestamp::extended() && + Timestamp::Base::get(_timestamp_end) > Timestamp::Base::get(timestamp)) { + /* timer wrapped, increase manually managed offset */ + Timestamp::Extension::set(_timestamp_end, Timestamp::Extension::get(_timestamp_end)+1); + } + Timestamp::Base::set(_timestamp_end, timestamp); + + /* call provided functor with target address and modified timestamp */ + fn(&buffer[total_length_bytes()], _timestamp_end); + + _total_length += (uint32_t)(length * 8); + } + + uint32_t total_length_bytes() const { return _total_length / 8; } + bool empty() const { return _total_length <= _hdr_length; } + +} __attribute__((packed)); + +#endif /* _CTF__PACKET_TYPES_H_ */ diff --git a/repos/gems/include/ctf/timestamp.h b/repos/gems/include/ctf/timestamp.h new file mode 100644 index 0000000000..96bbc7ece7 --- /dev/null +++ b/repos/gems/include/ctf/timestamp.h @@ -0,0 +1,40 @@ +/* + * \brief Generic timestamp for CTF traces + * \author Johannes Schlatow + * \date 2021-08-04 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _CTF__TIMESTAMP_H_ +#define _CTF__TIMESTAMP_H_ + +#include +#include + +namespace Ctf { + using namespace Genode; + + /* generic fixed-width timestamp type for different Trace::Timestamp widths */ + template + struct _Timestamp : Register<64> { + static constexpr bool extended() { return PWIDTH < 64; } + + /* define _PWIDTH to get a valid Extension Bitfield even for 64-bit */ + enum { _PWIDTH = PWIDTH < 64 ? PWIDTH : 0 }; + + struct Base : Bitfield<0, PWIDTH> { }; + struct Extension : Bitfield<_PWIDTH, 64-_PWIDTH> { }; + }; + + typedef _Timestamp Timestamp; + + typedef uint64_t __attribute__((aligned(1))) Timestamp_base; +} + +#endif /* _CTF__TIMESTAMP_H_ */ diff --git a/repos/gems/recipes/api/ctf/content.mk b/repos/gems/recipes/api/ctf/content.mk new file mode 100644 index 0000000000..7719c2ad68 --- /dev/null +++ b/repos/gems/recipes/api/ctf/content.mk @@ -0,0 +1,8 @@ +content: include/ctf LICENSE + +include/ctf: + $(mirror_from_rep_dir) + +LICENSE: + cp $(GENODE_DIR)/LICENSE $@ + diff --git a/repos/gems/recipes/api/ctf/hash b/repos/gems/recipes/api/ctf/hash new file mode 100644 index 0000000000..e59df5832b --- /dev/null +++ b/repos/gems/recipes/api/ctf/hash @@ -0,0 +1 @@ +2022-05-11 73fe945a53926f04e8062293aa2c2ce39541fc85