[PATCH v2][makedumpfile 14/14] Introducing 2 eppic scripts to test the dwarf/btf eppic extension

Tao Liu ltao at redhat.com
Mon Oct 20 15:24:10 PDT 2025


This patch will introduce 2 eppic scripts. One is for filtering out amdgpu
mm pages, the other is for printing all tasks VMAs. dwarf & btf eppic
extension should produce the same result for every eppic script, mainly
for test use.

Signed-off-by: Tao Liu <ltao at redhat.com>
---
 eppic_scripts/filter_amdgpu_mm_pages.c | 255 +++++++++++++++++++++++++
 eppic_scripts/print_all_vma.c          | 244 +++++++++++++++++++++++
 2 files changed, 499 insertions(+)
 create mode 100644 eppic_scripts/filter_amdgpu_mm_pages.c
 create mode 100644 eppic_scripts/print_all_vma.c

diff --git a/eppic_scripts/filter_amdgpu_mm_pages.c b/eppic_scripts/filter_amdgpu_mm_pages.c
new file mode 100644
index 0000000..8fe6d52
--- /dev/null
+++ b/eppic_scripts/filter_amdgpu_mm_pages.c
@@ -0,0 +1,255 @@
+enum {
+	maple_dense_enum,
+	maple_leaf_64_enum,
+	maple_range_64_enum,
+	maple_arange_64_enum,
+};
+
+#define MAPLE_NODE_MASK		255UL
+#define MAPLE_NODE_TYPE_MASK	0x0F
+#define MAPLE_NODE_TYPE_SHIFT	0x03
+#define XA_ZERO_ENTRY		xa_mk_internal(257)
+#define bool			int
+
+unsigned long mt_max;
+
+static unsigned long xa_mk_internal(unsigned long v)
+{
+	return (v << 2) | 2;
+}
+
+static bool xa_is_internal(unsigned long entry)
+{
+	return (entry & 3) == 2;
+}
+
+static bool xa_is_node(unsigned long entry)
+{
+	return xa_is_internal(entry) && entry > 4096;
+}
+
+static bool xa_is_value(unsigned long entry)
+{
+	return entry & 1;
+}
+
+static bool xa_is_zero(unsigned long entry)
+{
+	return entry == XA_ZERO_ENTRY;
+}
+
+static unsigned long xa_to_internal(unsigned long entry)
+{
+	return entry >> 2;
+}
+
+static unsigned long xa_to_value(unsigned long entry)
+{
+	return entry >> 1;
+}
+
+static struct maple_node *mte_to_node(void *entry)
+{
+        return (struct maple_node *)((unsigned long)entry & ~MAPLE_NODE_MASK);
+}
+
+static unsigned long mte_node_type(unsigned long maple_enode_entry)
+{
+	return (maple_enode_entry >> MAPLE_NODE_TYPE_SHIFT) &
+		MAPLE_NODE_TYPE_MASK;
+}
+
+static unsigned long mt_slot(void **slots, unsigned char offset)
+{
+	return *((unsigned long *)slots + offset);
+}
+
+static bool ma_is_leaf(unsigned long type)
+{
+	return type < maple_range_64_enum;
+}
+
+static bool mte_is_leaf(unsigned long maple_enode_entry)
+{
+       return ma_is_leaf(mte_node_type(maple_enode_entry));
+}
+
+static void mt_dump_entry(unsigned long entry, unsigned long min,
+			unsigned long max, unsigned int depth, unsigned long array_out)
+{
+	int i;
+	if (entry == 0)
+		return;
+	for (i in array_out) {
+		if (array_out[i] == 0) {
+			array_out[i] = entry;
+			return;
+		}
+	}
+	array_out[i + 1] = entry;
+}
+
+static void mt_dump_range64(void *entry, unsigned long min,
+			unsigned long max, unsigned int depth, unsigned long array_out)
+{
+	struct maple_range_64 *node = &mte_to_node(entry)->mr64;
+
+	bool leaf = mte_is_leaf((unsigned long)entry);
+	unsigned long first = min;
+	int i;
+
+	for (i = 0; i < *((char *)(&mt_slots) + maple_range_64_enum); i++) {
+		unsigned long last = max;
+
+		if (i < (*((char *)(&mt_slots) + maple_range_64_enum) - 1))
+			last  = *((unsigned long *)&(node->pivot) + i);
+		else if (!*((unsigned long *)&(node->slot) + i) &&
+			max != mt_max[mte_node_type((unsigned long)entry)])
+			break;
+		if (last == 0 && i > 0)
+			break;
+		if (leaf)
+			mt_dump_entry(mt_slot(&(node->slot), i),
+					first, last, depth + 1, array_out);
+		else if (*((unsigned long *)&(node->slot) + i))
+			mt_dump_node(mt_slot(&(node->slot), i),
+					first, last, depth + 1, array_out);
+
+		if (last == max)
+			break;
+		if (last > max) {
+			printf("node %p last (%lu) > max (%lu) at pivot %d!\n",
+				node, last, max, i);
+			break;
+		}
+		first = last + 1;
+	}
+}
+
+static void mt_dump_arange64(void *entry, unsigned long min,
+				unsigned long max, unsigned int depth, unsigned long array_out)
+{
+	struct maple_arange_64 *node = &mte_to_node(entry)->ma64;
+	unsigned long first = min;
+	int i;
+
+	for (i = 0; i < *((char *)(&mt_slots) + maple_arange_64_enum); i++) {
+		unsigned long last = max;
+		if (i < (*((char *)(&mt_slots) + maple_arange_64_enum) - 1))
+			last  = *((unsigned long *)&(node->pivot) + i);
+		else if (!*((unsigned long *)&(node->slot) + i))
+			break;
+		if (last == 0 && i > 0)
+			break;
+		if (*((unsigned long *)&(node->slot) + i))
+			mt_dump_node((void *)mt_slot(&(node->slot), i),
+					first, last, depth + 1, array_out);
+
+		if (last == max)
+			break;
+		if (last > max) {
+			printf("node %p last (%lu) > max (%lu) at pivot %d!\n",
+				node, last, max, i);
+			break;
+		}
+		first = last + 1;
+	}
+}
+
+static void mt_dump_node(void *entry, unsigned long min,
+			unsigned long max, unsigned int depth, unsigned long array_out)
+{
+	struct maple_node *node = mte_to_node(entry);
+	unsigned int type = mte_node_type((unsigned long)entry);
+	unsigned int i;
+
+	switch (type) {
+	case maple_dense_enum:
+		for (i = 0; i < *((char *)(&mt_slots) + maple_dense_enum); i++) {
+			if (min + i > max)
+				printf("OUT OF RANGE: ");
+			mt_dump_entry(mt_slot(&(node->slot), i),
+					min + i, min + i, depth, array_out);
+		}
+		break;
+	case maple_leaf_64_enum:
+	case maple_range_64_enum:
+		mt_dump_range64(entry, min, max, depth, array_out);
+		break;
+	case maple_arange_64_enum:
+		mt_dump_arange64(entry, min, max, depth, array_out);
+		break;
+
+	default:
+		printf(" UNKNOWN TYPE\n");
+	}
+}
+
+void mt_dump(const struct maple_tree *mt, unsigned long array_out)
+{
+	unsigned long entry = (unsigned long)(mt->ma_root);
+
+	/* init mt_max array */
+	mt_max[maple_dense_enum]           = *((char *)(&mt_slots) + maple_dense_enum);
+	mt_max[maple_leaf_64_enum]         = (unsigned long)(-1);
+	mt_max[maple_range_64_enum]        = (unsigned long)(-1);
+	mt_max[maple_arange_64_enum]       = (unsigned long)(-1);
+	/* done */
+
+	if (xa_is_node(entry))
+		mt_dump_node((void *)entry, 0, mt_max[mte_node_type(entry)], 0, array_out);
+	else if (entry)
+		mt_dump_entry((void *)entry, 0, 0, 0, array_out);
+	else
+		printf("(empty)\n");
+}
+
+int main()
+{
+	struct task_struct *p;
+	unsigned long p_off;
+	int i, c;
+	struct vm_area_struct *vma;
+	struct ttm_buffer_object *tbo;
+	unsigned long pfn, num;
+	struct maple_tree *mt;
+	unsigned long tmp;
+
+	p = (struct task_struct *)&init_task;
+	p_off = (unsigned long)&(p->tasks) - (unsigned long)p;
+
+	do {
+		unsigned long array_out;
+		array_out[0] = 0;
+
+		if (!(p->mm)) {
+			p = (struct task_struct *)
+				((unsigned long)(p->tasks.next) - p_off);
+			continue;
+		}
+
+		mt = &(p->mm->mm_mt);
+
+		mt_dump(mt, array_out);
+
+		for (i in array_out) {
+			if (((struct vm_area_struct *)array_out[i])->vm_ops ==
+			    &amdgpu_gem_vm_ops) {
+				    tbo = (struct ttm_buffer_object *)
+				    (((struct vm_area_struct *)array_out[i])->
+				    vm_private_data);
+				if (tbo->ttm) {
+					num = (unsigned long)(tbo->ttm->num_pages);
+					pfn = ((unsigned long)(tbo->ttm->pages[0]) -
+						*(unsigned long *)&vmemmap_base) /
+					      sizeof(struct page);
+					filter_pages(pfn, num);
+				}
+			}
+		}
+		p = (struct task_struct *)
+			((unsigned long)(p->tasks.next) - p_off);
+	} while(p != &init_task);
+
+	return 0;
+}
diff --git a/eppic_scripts/print_all_vma.c b/eppic_scripts/print_all_vma.c
new file mode 100644
index 0000000..f100c78
--- /dev/null
+++ b/eppic_scripts/print_all_vma.c
@@ -0,0 +1,244 @@
+enum {
+	maple_dense_enum,
+	maple_leaf_64_enum,
+	maple_range_64_enum,
+	maple_arange_64_enum,
+};
+
+#define MAPLE_NODE_MASK		255UL
+#define MAPLE_NODE_TYPE_MASK	0x0F
+#define MAPLE_NODE_TYPE_SHIFT	0x03
+#define XA_ZERO_ENTRY		xa_mk_internal(257)
+#define bool			int
+
+unsigned long mt_max;
+
+static unsigned long xa_mk_internal(unsigned long v)
+{
+	return (v << 2) | 2;
+}
+
+static bool xa_is_internal(unsigned long entry)
+{
+	return (entry & 3) == 2;
+}
+
+static bool xa_is_node(unsigned long entry)
+{
+	return xa_is_internal(entry) && entry > 4096;
+}
+
+static bool xa_is_value(unsigned long entry)
+{
+	return entry & 1;
+}
+
+static bool xa_is_zero(unsigned long entry)
+{
+	return entry == XA_ZERO_ENTRY;
+}
+
+static unsigned long xa_to_internal(unsigned long entry)
+{
+	return entry >> 2;
+}
+
+static unsigned long xa_to_value(unsigned long entry)
+{
+	return entry >> 1;
+}
+
+static struct maple_node *mte_to_node(void *entry)
+{
+        return (struct maple_node *)((unsigned long)entry & ~MAPLE_NODE_MASK);
+}
+
+static unsigned long mte_node_type(unsigned long maple_enode_entry)
+{
+	return (maple_enode_entry >> MAPLE_NODE_TYPE_SHIFT) &
+		MAPLE_NODE_TYPE_MASK;
+}
+
+static unsigned long mt_slot(void **slots, unsigned char offset)
+{
+	return *((unsigned long *)slots + offset);
+}
+
+static bool ma_is_leaf(unsigned long type)
+{
+	return type < maple_range_64_enum;
+}
+
+static bool mte_is_leaf(unsigned long maple_enode_entry)
+{
+       return ma_is_leaf(mte_node_type(maple_enode_entry));
+}
+
+static void mt_dump_entry(unsigned long entry, unsigned long min,
+			unsigned long max, unsigned int depth, unsigned long array_out)
+{
+	int i;
+	if (entry == 0)
+		return;
+	for (i in array_out) {
+		if (array_out[i] == 0) {
+			array_out[i] = entry;
+			return;
+		}
+	}
+	array_out[i + 1] = entry;
+}
+
+static void mt_dump_range64(void *entry, unsigned long min,
+			unsigned long max, unsigned int depth, unsigned long array_out)
+{
+	struct maple_range_64 *node = &mte_to_node(entry)->mr64;
+
+	bool leaf = mte_is_leaf((unsigned long)entry);
+	unsigned long first = min;
+	int i;
+
+	for (i = 0; i < *((char *)(&mt_slots) + maple_range_64_enum); i++) {
+		unsigned long last = max;
+
+		if (i < (*((char *)(&mt_slots) + maple_range_64_enum) - 1))
+			last  = *((unsigned long *)&(node->pivot) + i);
+		else if (!*((unsigned long *)&(node->slot) + i) &&
+			max != mt_max[mte_node_type((unsigned long)entry)])
+			break;
+		if (last == 0 && i > 0)
+			break;
+		if (leaf)
+			mt_dump_entry(mt_slot(&(node->slot), i),
+					first, last, depth + 1, array_out);
+		else if (*((unsigned long *)&(node->slot) + i))
+			mt_dump_node(mt_slot(&(node->slot), i),
+					first, last, depth + 1, array_out);
+
+		if (last == max)
+			break;
+		if (last > max) {
+			printf("node %p last (%lu) > max (%lu) at pivot %d!\n",
+				node, last, max, i);
+			break;
+		}
+		first = last + 1;
+	}
+}
+
+static void mt_dump_arange64(void *entry, unsigned long min,
+				unsigned long max, unsigned int depth, unsigned long array_out)
+{
+	struct maple_arange_64 *node = &mte_to_node(entry)->ma64;
+	unsigned long first = min;
+	int i;
+
+	for (i = 0; i < *((char *)(&mt_slots) + maple_arange_64_enum); i++) {
+		unsigned long last = max;
+		if (i < (*((char *)(&mt_slots) + maple_arange_64_enum) - 1))
+			last  = *((unsigned long *)&(node->pivot) + i);
+		else if (!*((unsigned long *)&(node->slot) + i))
+			break;
+		if (last == 0 && i > 0)
+			break;
+		if (*((unsigned long *)&(node->slot) + i))
+			mt_dump_node((void *)mt_slot(&(node->slot), i),
+					first, last, depth + 1, array_out);
+
+		if (last == max)
+			break;
+		if (last > max) {
+			printf("node %p last (%lu) > max (%lu) at pivot %d!\n",
+				node, last, max, i);
+			break;
+		}
+		first = last + 1;
+	}
+}
+
+static void mt_dump_node(void *entry, unsigned long min,
+			unsigned long max, unsigned int depth, unsigned long array_out)
+{
+	struct maple_node *node = mte_to_node(entry);
+	unsigned int type = mte_node_type((unsigned long)entry);
+	unsigned int i;
+
+	switch (type) {
+	case maple_dense_enum:
+		for (i = 0; i < *((char *)(&mt_slots) + maple_dense_enum); i++) {
+			if (min + i > max)
+				printf("OUT OF RANGE: ");
+			mt_dump_entry(mt_slot(&(node->slot), i),
+					min + i, min + i, depth, array_out);
+		}
+		break;
+	case maple_leaf_64_enum:
+	case maple_range_64_enum:
+		mt_dump_range64(entry, min, max, depth, array_out);
+		break;
+	case maple_arange_64_enum:
+		mt_dump_arange64(entry, min, max, depth, array_out);
+		break;
+
+	default:
+		printf(" UNKNOWN TYPE\n");
+	}
+}
+
+void mt_dump(const struct maple_tree *mt, unsigned long array_out)
+{
+	unsigned long entry = (unsigned long)(mt->ma_root);
+
+	/* init mt_max array */
+	mt_max[maple_dense_enum]           = *((char *)(&mt_slots) + maple_dense_enum);
+	mt_max[maple_leaf_64_enum]         = (unsigned long)(-1);
+	mt_max[maple_range_64_enum]        = (unsigned long)(-1);
+	mt_max[maple_arange_64_enum]       = (unsigned long)(-1);
+	/* done */
+
+	if (xa_is_node(entry))
+		mt_dump_node((void *)entry, 0, mt_max[mte_node_type(entry)], 0, array_out);
+	else if (entry)
+		mt_dump_entry((void *)entry, 0, 0, 0, array_out);
+	else
+		printf("(empty)\n");
+}
+
+int main()
+{
+	struct task_struct *p;
+	unsigned long p_off;
+	int i, c;
+	struct vm_area_struct *vma;
+	struct ttm_buffer_object *tbo;
+	unsigned long pfn, num;
+	struct maple_tree *mt;
+	unsigned long tmp;
+
+	p = (struct task_struct *)&init_task;
+	p_off = (unsigned long)&(p->tasks) - (unsigned long)p;
+
+	do {
+		unsigned long array_out;
+		array_out[0] = 0;
+
+		if (!(p->mm)) {
+			p = (struct task_struct *)
+				((unsigned long)(p->tasks.next) - p_off);
+			continue;
+		}
+
+		mt = &(p->mm->mm_mt);
+
+		mt_dump(mt, array_out);
+		printf("PID: %d\n", (int)(p->pid));
+
+		for (i in array_out) {
+			printf("%lx\n", array_out[i]);
+		}
+		p = (struct task_struct *)
+			((unsigned long)(p->tasks.next) - p_off);
+	} while(p != &init_task);
+
+	return 0;
+}
-- 
2.47.0




More information about the kexec mailing list