[PATCH v5 23/23] [RFC] tools/scmi: Add SCMI Telemetry testing tool

Cristian Marussi cristian.marussi at arm.com
Fri Jul 3 05:36:01 PDT 2026


Add a testing tool that exercises the SCMI ioctls UAPI interface: as of
now the tool simply queries the initial state of the SCMI Telemetry
subsystem, tries to enable all the existent Data Events and dumps all
the Telemetry data.

Signed-off-by: Cristian Marussi <cristian.marussi at arm.com>
---
Basic implementation just to exercise a few IOCTls: to be refined and
extended to support a more interactive usage.

v4 --> v5
 - changes to adapt to new chardev/IOCTLs ABI
 - change IOCTLs param to avoid flexible arrays
 - added SHMTIs mmap dump
v3 --> v4
 - added generation file support
---
 tools/testing/scmi/Makefile |  25 ++
 tools/testing/scmi/stlm.c   | 648 ++++++++++++++++++++++++++++++++++++
 2 files changed, 673 insertions(+)
 create mode 100644 tools/testing/scmi/Makefile
 create mode 100644 tools/testing/scmi/stlm.c

diff --git a/tools/testing/scmi/Makefile b/tools/testing/scmi/Makefile
new file mode 100644
index 000000000000..a6a101f8398b
--- /dev/null
+++ b/tools/testing/scmi/Makefile
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+CC?=$(CROSS_COMPILE)gcc
+OBJS = stlm.o
+
+CFLAGS=-Wall -static -std=gnu11 -I ../../../include/uapi/
+ifneq ($(DEBUG), )
+	CFLAGS+=-O0 -g -ggdb
+else
+	CFLAGS+=-static
+endif
+
+all: stlm
+
+stlm: $(OBJS)
+	$(CC) $(CFLAGS) $^ -o $@
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c $<
+
+clean:
+	rm -f *.o
+	rm -f stlm
+
+.PHONY: clean
diff --git a/tools/testing/scmi/stlm.c b/tools/testing/scmi/stlm.c
new file mode 100644
index 000000000000..4d7d19899d5c
--- /dev/null
+++ b/tools/testing/scmi/stlm.c
@@ -0,0 +1,648 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <unistd.h>
+
+#include <linux/scmi.h>
+
+#define SLEEP_MS	3000
+
+#define IOCTL_ERR_STR(_ioctl)	"IOCTL:" #_ioctl
+
+struct tlm_de {
+	struct scmi_tlm_de_info *info;
+	struct scmi_tlm_de_config cfg;
+	struct scmi_tlm_de_sample sample;
+};
+
+struct tlm_group {
+	int fd;
+	struct scmi_tlm_grp_info *info;
+	struct scmi_tlm_grp_desc *desc;
+	struct scmi_tlm_intervals *ivs;
+};
+
+struct tlm_state {
+	int dfd;
+	int fd;
+	int g_dfd;
+	const char *path;
+	struct scmi_tlm_base_info info;
+	struct scmi_tlm_config cfg;
+	struct scmi_tlm_intervals *ivs;
+	struct scmi_tlm_shmtis_list *ssl;
+	unsigned int num_des;
+	struct tlm_de *des;
+	unsigned int num_groups;
+	struct tlm_group *grps;
+};
+
+static inline void dump_state(struct tlm_state *st)
+{
+	uint32_t *uuid32 = st->info.de_impl_version;
+	uint16_t *uuid16 = (uint16_t *)&st->info.de_impl_version[1];
+	struct scmi_tlm_update_interval *intervals;
+	struct scmi_tlm_shmti_info *shinfo;
+
+	fprintf(stdout, "- SYSTEM TELEMETRY @instance: %s\n\n", st->path);
+	fprintf(stdout, "+ Version: 0x%08X\n", st->info.version);
+	fprintf(stdout, "+ DEs#: %d\n", st->info.num_des);
+	fprintf(stdout, "+ GRPS#: %d\n", st->info.num_groups);
+	fprintf(stdout, "+ INTRV#: %d\n", st->info.num_intervals);
+	fprintf(stdout, "+ SHMTIS#: %d\n", st->info.num_shmtis);
+
+	fprintf(stdout, "+ UUID: ");
+	fprintf(stdout, "%X-", uuid32[0]);
+	fprintf(stdout, "%X-", uuid16[0]);
+	fprintf(stdout, "%X-", uuid16[1]);
+	fprintf(stdout, "%X", uuid16[2]);
+	fprintf(stdout, "%X\n", uuid32[3]);
+
+	fprintf(stdout, "\n+ TLM_ENABLED: %d\n", st->cfg.enable);
+	fprintf(stdout, "+ CURRENT_UPDATE_INTERVAL: %u,%d\n",
+		st->cfg.active.secs, st->cfg.active.exp);
+
+	fprintf(stdout, "+ Found #%u Global Update Intervals\n",
+		st->ivs->num_intervals);
+	intervals = (struct scmi_tlm_update_interval *)st->ivs->intervals;
+	for (int i = 0; i < st->ivs->num_intervals; i++)
+		fprintf(stdout, "\t[%d]::%u,%d\n", i,
+			intervals[i].secs, intervals[i].exp);
+
+	fprintf(stdout, "+ Found #%u SHMTI areas\n", st->ssl->num_shmtis);
+	shinfo = (struct scmi_tlm_shmti_info *)st->ssl->shmtis;
+	for (int i = 0; i < st->ssl->num_shmtis; i++)
+		fprintf(stdout, "\t[%d]:: FD:%u  LEN:%u\n",
+			shinfo[i].sid, shinfo[i].fd, shinfo[i].len);
+
+	if (st->info.num_des != st->num_des) {
+		fprintf(stdout, "\n++++++ DES NOT FULLY_ENUMERATED ++++++\n");
+		fprintf(stdout, "+++ DECLARED:%u  ENUMERATED:%u +++\n",
+			st->info.num_des, st->num_des);
+	}
+
+	fprintf(stdout, "\n+ Found #%d DEs:\n", st->num_des);
+	for (int i = 0; i < st->num_des; i++) {
+		fprintf(stdout, "\t[0x%08X][%s]\n",
+			st->des[i].info->id, st->des[i].info->name);
+		fprintf(stdout, "\t\tGRP_ID:0x%08X  SZ:%u  TYPE:%u  UNIT:%u  UNIT_EXP:%d  TS_RATE:%d\n",
+			st->des[i].info->grp_id, st->des[i].info->data_sz,
+			st->des[i].info->type, st->des[i].info->unit,
+			st->des[i].info->unit_exp, st->des[i].info->ts_rate);
+		fprintf(stdout, "\t\tINST_ID:%u  COMPO_ID:%u  COMPO_TYPE:%u  PERSIST:%u\n\n",
+			st->des[i].info->instance_id, st->des[i].info->compo_instance_id,
+			st->des[i].info->compo_type, st->des[i].info->persistent);
+	}
+	fprintf(stdout, "\n");
+
+	for (int i = 0; i < st->num_des; i++) {
+		fprintf(stdout, "\t[0x%08X][%s]\t\t%s %s\n\t\t-->> TS:%16llu %016llX\n",
+			st->des[i].info->id,st->des[i].info->name,
+			st->des[i].cfg.enable ? "ON" : "OFF",
+			st->des[i].cfg.t_enable ? "/TS_ON " : "/TS_OFF",
+			st->des[i].sample.tstamp, st->des[i].sample.val);
+	}
+	fprintf(stdout, "\n");
+
+	fprintf(stdout, "+ Found %d GRPs: ", st->num_groups);
+	for (int i = 0; i < st->num_groups; i++) {
+		struct scmi_tlm_update_interval *grp_intrvs;
+		struct tlm_group *grp = &st->grps[i];
+		uint32_t *composing_des;
+
+		fprintf(stdout, "\n\tGRP_ID:%d  DES#:%d  INTRVS#:%d\n",
+			grp->info->grp_id, grp->info->num_des,
+			grp->info->num_intervals);
+
+		fprintf(stdout, "\tGRP Intervals:\n");
+		grp_intrvs = (struct scmi_tlm_update_interval *)grp->ivs->intervals;
+		for (int j = 0; j < grp->ivs->num_intervals; j++)
+			fprintf(stdout, "\t[%d]::%u,%d\n", j,
+				grp_intrvs[j].secs, grp_intrvs[j].exp);
+
+		composing_des = (uint32_t *)grp->desc->composing_des;
+		fprintf(stdout, "\tCOMPOSING_DES:");
+		for (int j = 0; j < grp->desc->num_des; j++)
+			fprintf(stdout, "0x%08X ", composing_des[j]);
+		fprintf(stdout, "\n");
+	}
+}
+
+static int discover_base_info(int fd, struct scmi_tlm_base_info *info)
+{
+	int ret;
+
+	ret = ioctl(fd, SCMI_TLM_GET_INFO, info);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_GET_INFO));
+		return ret;
+	}
+
+	return ret;
+}
+
+static struct scmi_tlm_des_list *scmi_get_des_list(int fd, int num_des)
+{
+	struct scmi_tlm_des_list *dsl;
+	struct scmi_tlm_de_info *dei;
+	size_t sz, d_sz;
+	int ret;
+
+	sz = sizeof(*dsl);
+	dsl = malloc(sz);
+	if (!dsl)
+		return NULL;
+
+	bzero(dsl, sz);
+
+	d_sz = sizeof(*dei) * num_des;
+	dei = malloc(d_sz);
+	if (!dei) {
+		free(dsl);
+		return NULL;
+	}
+
+	bzero(dei, d_sz);
+
+	dsl->num_des = num_des;
+	dsl->des = (uint64_t)dei;
+	ret = ioctl(fd, SCMI_TLM_GET_DE_LIST, dsl);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_GET_DE_LIST));
+		return NULL;
+	}
+
+	return dsl;
+}
+
+static struct tlm_de *enumerate_des(struct tlm_state *st)
+{
+	struct scmi_tlm_des_list *dsl;
+	struct tlm_de *des;
+
+	dsl = scmi_get_des_list(st->fd, st->info.num_des);
+	if (!dsl)
+		return NULL;
+
+	st->num_des = dsl->num_des;
+	des = malloc(sizeof(*des) * st->num_des);
+	if (!des)
+		return NULL;
+
+	bzero(des, sizeof(*des) * st->num_des);
+	for (int i = 0; i < st->num_des; i++) {
+		struct tlm_de *de = &des[i];
+		int ret;
+
+		de->info = &(((struct scmi_tlm_de_info *)dsl->des)[i]);
+		de->cfg.id = de->info->id;
+		ret = ioctl(st->fd, SCMI_TLM_GET_DE_CFG, &de->cfg);
+		if (ret) {
+			perror(IOCTL_ERR_STR(SCMI_TLM_GET_DE_CFG));
+			continue;
+		}
+
+		if (!de->cfg.enable)
+			continue;
+
+		/* Collect initial sample */
+		de->sample.id = de->info->id;
+		ret = ioctl(st->fd, SCMI_TLM_GET_DE_VALUE, &de->sample);
+		if (ret) {
+			perror(IOCTL_ERR_STR(SCMI_TLM_GET_DE_VALUE));
+			continue;
+		}
+	}
+
+	return des;
+}
+
+static int get_current_config(int fd, struct scmi_tlm_config *cfg)
+{
+	int ret;
+
+	ret = ioctl(fd, SCMI_TLM_GET_CFG, cfg);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_GET_CFG));
+		return ret;
+	}
+
+	return ret;
+}
+
+static struct scmi_tlm_grps_list *scmi_get_grps_list(int fd, int num_groups)
+{
+	struct scmi_tlm_grps_list *gsl;
+	struct scmi_tlm_grp_info *grps;
+	size_t sz, grps_sz;
+	int ret;
+
+	sz = sizeof(*gsl);
+	gsl = malloc(sz);
+	if (!gsl)
+		return NULL;
+
+	bzero(gsl, sz);
+	grps_sz = sizeof(*grps) * num_groups;
+	grps = malloc(grps_sz);
+	if (!grps) {
+		free(gsl);
+		return NULL;
+	}
+
+	gsl->num_grps = num_groups;
+	gsl->grps = (uint64_t)grps;
+	ret = ioctl(fd, SCMI_TLM_GET_GRP_LIST, gsl);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_GET_GRP_LIST));
+		free(grps);
+		free(gsl);
+		return NULL;
+	}
+
+	return gsl;
+}
+
+static struct scmi_tlm_intervals *
+enumerate_intervals(int fd, int num_intervals, unsigned *grp_id)
+{
+	struct scmi_tlm_update_interval *intervs;
+	struct scmi_tlm_intervals *ivs;
+	size_t sz, i_sz;
+	int ret;
+
+	sz = sizeof(*ivs);
+	ivs = malloc(sz);
+	if (!ivs)
+		return NULL;
+
+	bzero(ivs, sz);
+
+	i_sz = sizeof(*intervs) * num_intervals;
+	intervs = malloc(i_sz);
+	if (!intervs) {
+		free(ivs);
+		return NULL;
+	}
+
+	bzero(intervs, i_sz);
+
+	ivs->num_intervals = num_intervals;
+	ivs->intervals = (uint64_t)intervs;
+	if (grp_id) {
+		ivs->grp_id = *grp_id;
+		ivs->flags = SCMI_TLM_INTERV_GROUP;
+	}
+
+	ret = ioctl(fd, SCMI_TLM_GET_INTRVS, ivs);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_GET_INTRVS));
+		free(ivs);
+		free(intervs);
+		return NULL;
+	}
+
+	return ivs;
+}
+
+static struct scmi_tlm_shmtis_list *enumerate_shmtis(struct tlm_state *st)
+{
+	struct scmi_tlm_shmti_info *shmtis;
+	struct scmi_tlm_shmtis_list *ssl;
+	size_t sz, shmtis_sz;
+	int ret;
+
+	sz = sizeof(*ssl);
+	ssl = malloc(sz);
+	if (!ssl)
+		return NULL;
+
+	bzero(ssl, sz);
+	shmtis_sz = sizeof(*shmtis) * st->info.num_shmtis;
+	shmtis = malloc(shmtis_sz);
+	if (!shmtis) {
+		free(ssl);
+		return NULL;
+	}
+
+	ssl->num_shmtis = st->info.num_shmtis;
+	ssl->shmtis = (uint64_t)shmtis;
+	ret = ioctl(st->fd, SCMI_TLM_GET_SHMTI_LIST, ssl);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_GET_SHMTI_LIST));
+		free(shmtis);
+		free(ssl);
+		return NULL;
+	}
+
+	return ssl;
+}
+
+static struct tlm_group *enumerate_groups(struct tlm_state *st)
+{
+	struct scmi_tlm_grps_list *gsl;
+	struct tlm_group *grps;
+
+	gsl = scmi_get_grps_list(st->fd, st->info.num_groups);
+	if (!gsl)
+		return NULL;
+
+	st->num_groups = gsl->num_grps;
+	grps = malloc(sizeof(*grps) * st->num_groups);
+	if (!grps)
+		return NULL;
+
+	bzero(grps, sizeof(*grps) * st->num_groups);
+	for (int i = 0; i < st->num_groups; i++) {
+		struct tlm_group *grp = &grps[i];
+		size_t size, composing_sz;
+		uint32_t *composing_des;
+		int ret;
+
+		grp->info = &(((struct scmi_tlm_grp_info *)gsl->grps)[i]);
+		size = sizeof(*grp->desc);
+		grp->desc = malloc(size);
+		if (!grp->desc)
+			return NULL;
+
+		bzero(grp->desc, size);
+		composing_sz = sizeof(uint32_t) * grp->info->num_des;
+		composing_des = malloc(composing_sz);
+		if (!composing_des) //XXX BAD Cleanup
+			return NULL;
+
+		grp->desc->grp_id = grp->info->grp_id;
+		grp->desc->num_des = grp->info->num_des;
+		grp->desc->composing_des = (uint64_t)composing_des;
+		ret = ioctl(st->fd, SCMI_TLM_GET_GRP_DESC, grp->desc);
+		if (ret) {
+			perror(IOCTL_ERR_STR(SCMI_TLM_GET_GRP_DESC));
+			continue;
+		}
+
+		grp->ivs = enumerate_intervals(st->fd, grp->info->num_intervals,
+					       &grp->info->grp_id);
+	}
+
+	return grps;
+}
+
+static int get_tlm_state(const char *path, struct tlm_state *st)
+{
+	int ret;
+
+	st->dfd = open(path, O_RDONLY);
+	if (st->dfd < 0) {
+		perror("open");
+		return st->dfd;
+	}
+
+	st->fd = openat(st->dfd, "tlm_0", O_RDWR);
+	if (st->fd < 0) {
+		perror("openat");
+		return st->fd;
+	}
+
+	ret = discover_base_info(st->fd, &st->info);
+	if (ret)
+		return ret;
+
+	st->ivs = enumerate_intervals(st->fd, st->info.num_intervals, NULL);
+	if (!st->ivs)
+		return -1;
+
+	ret = get_current_config(st->fd, &st->cfg);
+	if (ret)
+		return ret;
+
+	if (st->info.num_des)
+		st->des = enumerate_des(st);
+
+	if (st->info.num_groups)
+		st->grps = enumerate_groups(st);
+
+	if (st->info.num_shmtis)
+		st->ssl = enumerate_shmtis(st);
+
+	st->path = path;
+
+	return 0;
+}
+
+#define MAX_GENERATIONS		5
+
+static void get_tlm_generation(struct tlm_state *st)
+{
+	int fd, i = 0;
+	struct pollfd pfds[1];
+
+	fd = openat(st->dfd, "generation", O_RDONLY);
+	if (fd < 0) {
+		perror("openat");
+		return ;
+	}
+
+	pfds[0].fd = fd;
+	pfds[0].events = POLLIN;
+
+	do {
+		int ret;
+
+		pfds[0].revents = 0;
+		ret = poll(pfds, 1, -1);
+		if (ret < 0 ) {
+			perror("poll generation");
+			break;;
+		}
+
+		if (!pfds[0].revents)
+			continue;
+
+		if (pfds[0].revents & POLLIN) {
+			int n;
+			char buf[32] = {};
+
+			n = read(fd, buf, 32);
+			if (n < 0) {
+				perror("read generation");
+				break;
+			}
+
+			fprintf(stdout, "Generation[%u]: %s\n", i, buf);
+		}
+	} while (i++ < MAX_GENERATIONS);
+
+	close(fd);
+}
+
+static int dump_shmti(struct scmi_tlm_shmti_info *shmti)
+{
+	void *tdcf;
+	ssize_t bytes = 0;
+
+	tdcf = mmap(NULL, shmti->len, PROT_READ, MAP_SHARED, shmti->fd, 0);
+	if (tdcf == MAP_FAILED) {
+		fprintf(stderr, "%s\n", strerror(errno));
+		return -1;
+	}
+
+	tdcf += shmti->offset;
+	do {
+		bytes += write(1, tdcf + bytes, shmti->len - bytes);
+		if (bytes < 0)
+			return -1;
+	} while (bytes < shmti->len);
+
+	return bytes;
+}
+
+int main(int argc, char **argv)
+{
+	const char *tlm_root_instance = "/dev/scmi/";
+	struct scmi_tlm_data_read *bulk;
+	struct scmi_tlm_de_config de_cfg = {};
+	struct scmi_tlm_de_sample *samples;
+	struct scmi_tlm_shmti_info *shmtis;
+	size_t bulk_sz, samples_sz;
+	struct tlm_state st = {};
+	int ret;
+
+	ret = get_tlm_state(tlm_root_instance, &st);
+	if (ret)
+		return ret;
+
+	if (argc > 1) {
+		struct scmi_tlm_shmti_info *shmti;
+		int ret, sid = atoi(argv[1]);
+
+		if (sid >= st.ssl->num_shmtis)
+			return -1;
+
+		shmti = &(((struct scmi_tlm_shmti_info *)(st.ssl->shmtis))[sid]);
+
+		fprintf(stderr, "Binary DUMP of SHMTI[%u] LEN:%u\n",
+			shmti->sid, shmti->len);
+
+		ret = dump_shmti(shmti);
+		if (ret < 0)
+			return ret;
+
+		return 0;
+	}
+
+	dump_state(&st);
+
+	//get_tlm_generation(&st);
+	bulk_sz = sizeof(*bulk);
+	bulk = malloc(bulk_sz);
+	if (!bulk)
+		return -1;
+
+	bzero(bulk, bulk_sz);
+	samples_sz = st.info.num_des * sizeof(*samples);
+	samples = malloc(samples_sz);
+	if (!samples)
+		return -1;
+
+	bzero(samples, samples_sz);
+	bulk->samples = (uint64_t)samples;
+	bulk->num_samples = st.info.num_des;
+	ret = ioctl(st.fd, SCMI_TLM_SINGLE_SAMPLE, bulk);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_SINGLE_SAMPLE));
+		return -1;
+	}
+
+	fprintf(stdout, "\n- Single ASYNC read -\n-------------------\n");
+	for (int i = 0; i < bulk->num_samples; i++)
+		fprintf(stdout, "0x%08X %016llu %016llX\n",
+			samples[i].id, samples[i].tstamp, samples[i].val);
+
+	fprintf(stdout, "\n--- Enabling ALL DEs with timestamp...\n");
+	de_cfg.enable = 1;
+	de_cfg.t_enable = 1;
+	ret = ioctl(st.fd, SCMI_TLM_SET_ALL_CFG, &de_cfg);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_SET_ALL_CFG));
+		return ret;
+	}
+
+	bzero(samples, samples_sz);
+	bulk->num_samples = st.info.num_des;
+	ret = ioctl(st.fd, SCMI_TLM_BULK_READ, bulk);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_BULK_READ));
+		return -1;
+	}
+
+	fprintf(stdout, "\n- BULK read -\n-------------------\n");
+	for (int i = 0; i < bulk->num_samples; i++)
+		fprintf(stdout, "0x%08X %016llu %016llX\n",
+			samples[i].id, samples[i].tstamp, samples[i].val);
+
+	bzero(samples, samples_sz);
+	bulk->num_samples = 5;
+	samples[0].id = 0x1010;
+	samples[1].id = 0xA001;
+	samples[2].id = 0xA005;
+	samples[3].id = 0x2020;
+	samples[4].id = 0x0003;
+	ret = ioctl(st.fd, SCMI_TLM_BATCH_READ, bulk);
+	if (ret) {
+		perror(IOCTL_ERR_STR(SCMI_TLM_BATCH_READ));
+		return -1;
+	}
+
+	fprintf(stdout, "\n- BATCH read -\n-------------------\n");
+	for (int i = 0; i < bulk->num_samples; i++)
+		fprintf(stdout, "0x%08X %016llu %016llX\n",
+			samples[i].id, samples[i].tstamp, samples[i].val);
+
+	fprintf(stdout, "\n- SHMTI mmap dump -\n-------------------\n");
+	shmtis = (struct scmi_tlm_shmti_info *)st.ssl->shmtis;
+	for (int i = 0; i < st.ssl->num_shmtis; i++) {
+		unsigned long *start, *end;
+		void *tdcf;
+		char *buf;
+
+		fprintf(stdout, "Mapping SHMTI[%u] - SID:%u  LEN:%u  FD:%u  OFFS:%u\n",
+			i, shmtis[i].sid, shmtis[i].len, shmtis[i].fd, shmtis[i].offset);
+
+		tdcf = mmap(NULL, shmtis[i].len, PROT_READ, MAP_SHARED,
+			    shmtis[i].fd, 0);
+		if (tdcf == MAP_FAILED) {
+			fprintf(stderr, "%s\n", strerror(errno));
+			return -1;
+		}
+
+		start = tdcf + shmtis[i].offset;
+		end = tdcf + shmtis[i].offset + shmtis[i].len;
+
+		fprintf(stdout, "-----------------------------------------------------\n");
+		fprintf(stdout, "Mapped SHMTI - SID:%u  %u@%p\n",
+			shmtis[i].sid, shmtis[i].offset, tdcf);
+
+		buf = (char *)start;
+		for (int j = 0; j < 4; j++)
+			fprintf(stdout, "%c ", buf[j]);
+
+		fprintf(stdout, " ===> ");
+
+		buf = ((char *)end) - 4;
+		for (int j = 0 ; j < 4; j++)
+			fprintf(stdout, "%c ", buf[j]);
+		fprintf(stdout, "\n-----------------------------------------------------\n");
+	}
+
+	return 0;
+}
-- 
2.54.0




More information about the linux-arm-kernel mailing list