diff --git a/MAINTAINERS b/MAINTAINERS
index b71a8c99a..49a97e592 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -199,6 +199,7 @@ M: Jerin Jacob <jerinj@marvell.com>
 M: Sunil Kumar Kori <skori@marvell.com>
 F: lib/librte_eal/include/rte_trace*.h
 F: lib/librte_eal/common/eal_common_trace*.c
+F: lib/librte_eal/common/eal_trace.h
 
 Memory Allocation
 M: Anatoly Burakov <anatoly.burakov@intel.com>
diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c
index e18ba1c95..abb656838 100644
--- a/lib/librte_eal/common/eal_common_trace.c
+++ b/lib/librte_eal/common/eal_common_trace.c
@@ -2,5 +2,102 @@
  * Copyright(C) 2020 Marvell International Ltd.
  */
 
-#include <rte_trace.h>
+#include <inttypes.h>
+#include <sys/queue.h>
 
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_string_fns.h>
+
+#include "eal_trace.h"
+
+RTE_DEFINE_PER_LCORE(volatile int, trace_point_sz);
+RTE_DEFINE_PER_LCORE(char, ctf_field[TRACE_CTF_FIELD_SIZE]);
+RTE_DEFINE_PER_LCORE(int, ctf_count);
+
+static struct trace_point_head tp_list = STAILQ_HEAD_INITIALIZER(tp_list);
+static struct trace trace;
+
+int
+__rte_trace_point_register(rte_trace_t *handle, const char *name,
+			   void (*register_fn)(void))
+{
+	char *field = RTE_PER_LCORE(ctf_field);
+	struct trace_point *tp;
+	uint16_t sz;
+
+	/* Sanity checks of arguments */
+	if (name == NULL || register_fn == NULL || handle == NULL) {
+		trace_err("invalid arguments");
+		rte_errno = EINVAL; goto fail;
+	}
+
+	/* Check the size of the trace point object */
+	RTE_PER_LCORE(trace_point_sz) = 0;
+	RTE_PER_LCORE(ctf_count) = 0;
+	register_fn();
+	if (RTE_PER_LCORE(trace_point_sz) == 0) {
+		trace_err("missing rte_trace_emit_header() in register fn");
+		rte_errno = EBADF; goto fail;
+	}
+
+	/* Is size overflowed */
+	if (RTE_PER_LCORE(trace_point_sz) > UINT16_MAX) {
+		trace_err("trace point size overflowed");
+		rte_errno = ENOSPC; goto fail;
+	}
+
+	/* Are we running out of space to store trace points? */
+	if (trace.nb_trace_points > UINT16_MAX) {
+		trace_err("trace point exceeds the max count");
+		rte_errno = ENOSPC; goto fail;
+	}
+
+	/* Get the size of the trace point */
+	sz = RTE_PER_LCORE(trace_point_sz);
+	tp = calloc(1, sizeof(struct trace_point));
+	if (tp == NULL) {
+		trace_err("fail to allocate trace point memory");
+		rte_errno = ENOMEM; goto fail;
+	}
+
+	/* Initialize the trace point */
+	if (rte_strscpy(tp->name, name, TRACE_POINT_NAME_SIZE) < 0) {
+		trace_err("name is too long");
+		rte_errno = E2BIG;
+		goto free;
+	}
+
+	/* Copy the field data for future use */
+	if (rte_strscpy(tp->ctf_field, field, TRACE_CTF_FIELD_SIZE) < 0) {
+		trace_err("CTF field size is too long");
+		rte_errno = E2BIG;
+		goto free;
+	}
+
+	/* Clear field memory for the next event */
+	memset(field, 0, TRACE_CTF_FIELD_SIZE);
+
+	/* Form the trace handle */
+	*handle = sz;
+	*handle |= trace.nb_trace_points << __RTE_TRACE_FIELD_ID_SHIFT;
+
+	trace.nb_trace_points++;
+	tp->handle = handle;
+
+	/* Add the trace point at tail */
+	STAILQ_INSERT_TAIL(&tp_list, tp, next);
+	__atomic_thread_fence(__ATOMIC_RELEASE);
+
+	/* All Good !!! */
+	return 0;
+free:
+	free(tp);
+fail:
+	if (trace.register_errno == 0)
+		trace.register_errno = rte_errno;
+
+	return -rte_errno;
+}
diff --git a/lib/librte_eal/common/eal_trace.h b/lib/librte_eal/common/eal_trace.h
new file mode 100644
index 000000000..7665bd6be
--- /dev/null
+++ b/lib/librte_eal/common/eal_trace.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#ifndef __EAL_TRACE_H
+#define __EAL_TRACE_H
+
+#include <rte_trace.h>
+
+#define trace_err(fmt, args...)\
+	RTE_LOG(ERR, EAL, "%s():%u " fmt "\n",\
+		__func__, __LINE__, ## args)
+
+#define trace_crit(fmt, args...)\
+	RTE_LOG(CRIT, EAL, "%s():%u " fmt "\n",\
+		__func__, __LINE__, ## args)
+
+#define TRACE_CTF_FIELD_SIZE 384
+#define TRACE_POINT_NAME_SIZE 64
+
+struct trace_point {
+	STAILQ_ENTRY(trace_point) next;
+	rte_trace_t *handle;
+	char name[TRACE_POINT_NAME_SIZE];
+	char ctf_field[TRACE_CTF_FIELD_SIZE];
+};
+
+struct trace {
+	int register_errno;
+	uint32_t nb_trace_points;
+};
+
+/* Trace point list functions */
+STAILQ_HEAD(trace_point_head, trace_point);
+
+#endif /* __EAL_TRACE_H */
diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build
index 37dcb02fa..037a4ae63 100644
--- a/lib/librte_eal/include/meson.build
+++ b/lib/librte_eal/include/meson.build
@@ -41,6 +41,8 @@ headers += files(
 	'rte_tailq.h',
 	'rte_time.h',
 	'rte_trace.h',
+	'rte_trace_provider.h',
+	'rte_trace_register.h',
 	'rte_uuid.h',
 	'rte_version.h',
 	'rte_vfio.h',
diff --git a/lib/librte_eal/include/rte_trace.h b/lib/librte_eal/include/rte_trace.h
index 83105c980..1c8010f08 100644
--- a/lib/librte_eal/include/rte_trace.h
+++ b/lib/librte_eal/include/rte_trace.h
@@ -359,6 +359,32 @@ _tp _args \
 
 #endif /* __DOXYGEN__ */
 
+/**
+ * @internal
+ *
+ * Helper function to register a dynamic tracepoint.
+ * Use RTE_TRACE_POINT_REGISTER macro for tracepoint registration.
+ *
+ * @param trace
+ *   The tracepoint object created using RTE_TRACE_POINT_DEFINE.
+ * @param name
+ *   The name of the tracepoint object.
+ * @param register_fn
+ *   Trace registration function.
+ * @return
+ *   - 0: Successfully registered the tracepoint.
+ *   - <0: Failure to register the tracepoint.
+ */
+__rte_experimental
+int __rte_trace_point_register(rte_trace_t *trace, const char *name,
+			       void (*register_fn)(void));
+
+#ifdef RTE_TRACE_POINT_REGISTER_SELECT
+#include <rte_trace_register.h>
+#else
+#include <rte_trace_provider.h>
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/include/rte_trace_provider.h b/lib/librte_eal/include/rte_trace_provider.h
new file mode 100644
index 000000000..d1b45a4c7
--- /dev/null
+++ b/lib/librte_eal/include/rte_trace_provider.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#ifndef _RTE_TRACE_H_
+#error do not include this file directly, use <rte_trace.h> instead
+#endif
+
+#ifndef _RTE_TRACE_PROVIDER_H_
+#define _RTE_TRACE_PROVIDER_H_
+
+#define __RTE_TRACE_EVENT_HEADER_ID_SHIFT (48)
+
+#define __RTE_TRACE_FIELD_SIZE_SHIFT 0
+#define __RTE_TRACE_FIELD_SIZE_MASK (0xffffULL << __RTE_TRACE_FIELD_SIZE_SHIFT)
+#define __RTE_TRACE_FIELD_ID_SHIFT (16)
+#define __RTE_TRACE_FIELD_ID_MASK (0xffffULL << __RTE_TRACE_FIELD_ID_SHIFT)
+#define __RTE_TRACE_FIELD_ENABLE_MASK (1ULL << 63)
+#define __RTE_TRACE_FIELD_ENABLE_DISCARD (1ULL << 62)
+
+
+#endif /* _RTE_TRACE_PROVIDER_H_ */
diff --git a/lib/librte_eal/include/rte_trace_register.h b/lib/librte_eal/include/rte_trace_register.h
new file mode 100644
index 000000000..b36c00827
--- /dev/null
+++ b/lib/librte_eal/include/rte_trace_register.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#ifndef _RTE_TRACE_H_
+#error do not include this file directly, use <rte_trace.h> instead
+#endif
+
+#ifndef _RTE_TRACE_REGISTER_H_
+#define _RTE_TRACE_REGISTER_H_
+
+#include <rte_per_lcore.h>
+
+RTE_DECLARE_PER_LCORE(volatile int, trace_point_sz);
+
+#define RTE_TRACE_POINT_REGISTER(trace, name)\
+	__rte_trace_point_register(&__##trace, RTE_STR(name),\
+				   (void (*)(void)) trace)
+
+#endif /* _RTE_TRACE_REGISTER_H_ */
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index 71098581f..3a1be3e3f 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -339,4 +339,5 @@ EXPERIMENTAL {
 	# added in 20.05
 	rte_log_can_log;
 	rte_thread_getname;
+	__rte_trace_point_register;
 };
