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 <[email protected]> --- 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
