Commit 89b21365 authored by Yuri Nudelman's avatar Yuri Nudelman Committed by Oded Gabbay

habanalabs: add userptr_lookup node in debugfs

It is useful to have the ability to see which user address was pinned
to which physical address during the initial mapping. We already have
all that info stored, but no means to search this data (which may be
quite large).
Signed-off-by: default avatarYuri Nudelman <ynudelman@habana.ai>
Reviewed-by: default avatarOded Gabbay <ogabbay@kernel.org>
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent 816a6c6d
...@@ -241,6 +241,14 @@ Description: Displays a list with information about the currently user ...@@ -241,6 +241,14 @@ Description: Displays a list with information about the currently user
pointers (user virtual addresses) that are pinned and mapped pointers (user virtual addresses) that are pinned and mapped
to DMA addresses to DMA addresses
What: /sys/kernel/debug/habanalabs/hl<n>/userptr_lookup
Date: Aug 2021
KernelVersion: 5.15
Contact: ogabbay@kernel.org
Description: Allows to search for specific user pointers (user virtual
addresses) that are pinned and mapped to DMA addresses, and see
their resolution to the specific dma address.
What: /sys/kernel/debug/habanalabs/hl<n>/vm What: /sys/kernel/debug/habanalabs/hl<n>/vm
Date: Jan 2019 Date: Jan 2019
KernelVersion: 5.1 KernelVersion: 5.1
......
...@@ -320,6 +320,77 @@ static int vm_show(struct seq_file *s, void *data) ...@@ -320,6 +320,77 @@ static int vm_show(struct seq_file *s, void *data)
return 0; return 0;
} }
static int userptr_lookup_show(struct seq_file *s, void *data)
{
struct hl_debugfs_entry *entry = s->private;
struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
struct scatterlist *sg;
struct hl_userptr *userptr;
bool first = true;
u64 total_npages, npages, sg_start, sg_end;
dma_addr_t dma_addr;
int i;
spin_lock(&dev_entry->userptr_spinlock);
list_for_each_entry(userptr, &dev_entry->userptr_list, debugfs_list) {
if (dev_entry->userptr_lookup >= userptr->addr &&
dev_entry->userptr_lookup < userptr->addr + userptr->size) {
total_npages = 0;
for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents,
i) {
npages = hl_get_sg_info(sg, &dma_addr);
sg_start = userptr->addr +
total_npages * PAGE_SIZE;
sg_end = userptr->addr +
(total_npages + npages) * PAGE_SIZE;
if (dev_entry->userptr_lookup >= sg_start &&
dev_entry->userptr_lookup < sg_end) {
dma_addr += (dev_entry->userptr_lookup -
sg_start);
if (first) {
first = false;
seq_puts(s, "\n");
seq_puts(s, " user virtual address dma address pid region start region size\n");
seq_puts(s, "---------------------------------------------------------------------------------------\n");
}
seq_printf(s, " 0x%-18llx 0x%-16llx %-8u 0x%-16llx %-12llu\n",
dev_entry->userptr_lookup,
(u64)dma_addr, userptr->pid,
userptr->addr, userptr->size);
}
total_npages += npages;
}
}
}
spin_unlock(&dev_entry->userptr_spinlock);
if (!first)
seq_puts(s, "\n");
return 0;
}
static ssize_t userptr_lookup_write(struct file *file, const char __user *buf,
size_t count, loff_t *f_pos)
{
struct seq_file *s = file->private_data;
struct hl_debugfs_entry *entry = s->private;
struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
ssize_t rc;
u64 value;
rc = kstrtoull_from_user(buf, count, 16, &value);
if (rc)
return rc;
dev_entry->userptr_lookup = value;
return count;
}
static int mmu_show(struct seq_file *s, void *data) static int mmu_show(struct seq_file *s, void *data)
{ {
struct hl_debugfs_entry *entry = s->private; struct hl_debugfs_entry *entry = s->private;
...@@ -1175,6 +1246,7 @@ static const struct hl_info_list hl_debugfs_list[] = { ...@@ -1175,6 +1246,7 @@ static const struct hl_info_list hl_debugfs_list[] = {
{"command_submission_jobs", command_submission_jobs_show, NULL}, {"command_submission_jobs", command_submission_jobs_show, NULL},
{"userptr", userptr_show, NULL}, {"userptr", userptr_show, NULL},
{"vm", vm_show, NULL}, {"vm", vm_show, NULL},
{"userptr_lookup", userptr_lookup_show, userptr_lookup_write},
{"mmu", mmu_show, mmu_asid_va_write}, {"mmu", mmu_show, mmu_asid_va_write},
{"engines", engines_show, NULL} {"engines", engines_show, NULL}
}; };
......
...@@ -1816,6 +1816,7 @@ struct hl_debugfs_entry { ...@@ -1816,6 +1816,7 @@ struct hl_debugfs_entry {
* @state_dump_sem: protects state_dump. * @state_dump_sem: protects state_dump.
* @addr: next address to read/write from/to in read/write32. * @addr: next address to read/write from/to in read/write32.
* @mmu_addr: next virtual address to translate to physical address in mmu_show. * @mmu_addr: next virtual address to translate to physical address in mmu_show.
* @userptr_lookup: the target user ptr to look up for on demand.
* @mmu_asid: ASID to use while translating in mmu_show. * @mmu_asid: ASID to use while translating in mmu_show.
* @state_dump_head: index of the latest state dump * @state_dump_head: index of the latest state dump
* @i2c_bus: generic u8 debugfs file for bus value to use in i2c_data_read. * @i2c_bus: generic u8 debugfs file for bus value to use in i2c_data_read.
...@@ -1843,6 +1844,7 @@ struct hl_dbg_device_entry { ...@@ -1843,6 +1844,7 @@ struct hl_dbg_device_entry {
struct rw_semaphore state_dump_sem; struct rw_semaphore state_dump_sem;
u64 addr; u64 addr;
u64 mmu_addr; u64 mmu_addr;
u64 userptr_lookup;
u32 mmu_asid; u32 mmu_asid;
u32 state_dump_head; u32 state_dump_head;
u8 i2c_bus; u8 i2c_bus;
...@@ -2647,6 +2649,23 @@ struct hl_ioctl_desc { ...@@ -2647,6 +2649,23 @@ struct hl_ioctl_desc {
* Kernel module functions that can be accessed by entire module * Kernel module functions that can be accessed by entire module
*/ */
/**
* hl_get_sg_info() - get number of pages and the DMA address from SG list.
* @sg: the SG list.
* @dma_addr: pointer to DMA address to return.
*
* Calculate the number of consecutive pages described by the SG list. Take the
* offset of the address in the first page, add to it the length and round it up
* to the number of needed pages.
*/
static inline u32 hl_get_sg_info(struct scatterlist *sg, dma_addr_t *dma_addr)
{
*dma_addr = sg_dma_address(sg);
return ((((*dma_addr) & (PAGE_SIZE - 1)) + sg_dma_len(sg)) +
(PAGE_SIZE - 1)) >> PAGE_SHIFT;
}
/** /**
* hl_mem_area_inside_range() - Checks whether address+size are inside a range. * hl_mem_area_inside_range() - Checks whether address+size are inside a range.
* @address: The start address of the area we want to validate. * @address: The start address of the area we want to validate.
......
...@@ -796,23 +796,6 @@ int hl_unreserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx, ...@@ -796,23 +796,6 @@ int hl_unreserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx,
return rc; return rc;
} }
/**
* get_sg_info() - get number of pages and the DMA address from SG list.
* @sg: the SG list.
* @dma_addr: pointer to DMA address to return.
*
* Calculate the number of consecutive pages described by the SG list. Take the
* offset of the address in the first page, add to it the length and round it up
* to the number of needed pages.
*/
static u32 get_sg_info(struct scatterlist *sg, dma_addr_t *dma_addr)
{
*dma_addr = sg_dma_address(sg);
return ((((*dma_addr) & (PAGE_SIZE - 1)) + sg_dma_len(sg)) +
(PAGE_SIZE - 1)) >> PAGE_SHIFT;
}
/** /**
* init_phys_pg_pack_from_userptr() - initialize physical page pack from host * init_phys_pg_pack_from_userptr() - initialize physical page pack from host
* memory * memory
...@@ -863,7 +846,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx, ...@@ -863,7 +846,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
*/ */
total_npages = 0; total_npages = 0;
for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) { for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) {
npages = get_sg_info(sg, &dma_addr); npages = hl_get_sg_info(sg, &dma_addr);
total_npages += npages; total_npages += npages;
...@@ -892,7 +875,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx, ...@@ -892,7 +875,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
j = 0; j = 0;
for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) { for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) {
npages = get_sg_info(sg, &dma_addr); npages = hl_get_sg_info(sg, &dma_addr);
/* align down to physical page size and save the offset */ /* align down to physical page size and save the offset */
if (first) { if (first) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment