[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