Commit a4371c1a authored by Sagiv Ozeri's avatar Sagiv Ozeri Committed by Oded Gabbay

habanalabs: support HW blocks vm show

Improve "vm" debugfs node to print also the virtual addresses which are
currently mapped to HW blocks in the device.
Signed-off-by: default avatarSagiv Ozeri <sozeri@habana.ai>
Reviewed-by: default avatarOded Gabbay <ogabbay@kernel.org>
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent 6a2f5d70
...@@ -174,7 +174,7 @@ Date: Jan 2019 ...@@ -174,7 +174,7 @@ Date: Jan 2019
KernelVersion: 5.1 KernelVersion: 5.1
Contact: ogabbay@kernel.org Contact: ogabbay@kernel.org
Description: Displays a list with information about all the active virtual Description: Displays a list with information about all the active virtual
address mappings per ASID address mappings per ASID and all user mappings of HW blocks
What: /sys/kernel/debug/habanalabs/hl<n>/stop_on_err What: /sys/kernel/debug/habanalabs/hl<n>/stop_on_err
Date: Mar 2020 Date: Mar 2020
......
...@@ -20,6 +20,11 @@ static void hl_ctx_fini(struct hl_ctx *ctx) ...@@ -20,6 +20,11 @@ static void hl_ctx_fini(struct hl_ctx *ctx)
*/ */
hl_pending_cb_list_flush(ctx); hl_pending_cb_list_flush(ctx);
/* Release all allocated HW block mapped list entries and destroy
* the mutex.
*/
hl_hw_block_mem_fini(ctx);
/* /*
* If we arrived here, there are no jobs waiting for this context * If we arrived here, there are no jobs waiting for this context
* on its queues so we can safely remove it. * on its queues so we can safely remove it.
...@@ -160,13 +165,15 @@ int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx) ...@@ -160,13 +165,15 @@ int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx)
if (!ctx->cs_pending) if (!ctx->cs_pending)
return -ENOMEM; return -ENOMEM;
hl_hw_block_mem_init(ctx);
if (is_kernel_ctx) { if (is_kernel_ctx) {
ctx->asid = HL_KERNEL_ASID_ID; /* Kernel driver gets ASID 0 */ ctx->asid = HL_KERNEL_ASID_ID; /* Kernel driver gets ASID 0 */
rc = hl_vm_ctx_init(ctx); rc = hl_vm_ctx_init(ctx);
if (rc) { if (rc) {
dev_err(hdev->dev, "Failed to init mem ctx module\n"); dev_err(hdev->dev, "Failed to init mem ctx module\n");
rc = -ENOMEM; rc = -ENOMEM;
goto err_free_cs_pending; goto err_hw_block_mem_fini;
} }
rc = hdev->asic_funcs->ctx_init(ctx); rc = hdev->asic_funcs->ctx_init(ctx);
...@@ -179,7 +186,7 @@ int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx) ...@@ -179,7 +186,7 @@ int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx)
if (!ctx->asid) { if (!ctx->asid) {
dev_err(hdev->dev, "No free ASID, failed to create context\n"); dev_err(hdev->dev, "No free ASID, failed to create context\n");
rc = -ENOMEM; rc = -ENOMEM;
goto err_free_cs_pending; goto err_hw_block_mem_fini;
} }
rc = hl_vm_ctx_init(ctx); rc = hl_vm_ctx_init(ctx);
...@@ -214,7 +221,8 @@ int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx) ...@@ -214,7 +221,8 @@ int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx)
err_asid_free: err_asid_free:
if (ctx->asid != HL_KERNEL_ASID_ID) if (ctx->asid != HL_KERNEL_ASID_ID)
hl_asid_free(hdev, ctx->asid); hl_asid_free(hdev, ctx->asid);
err_free_cs_pending: err_hw_block_mem_fini:
hl_hw_block_mem_fini(ctx);
kfree(ctx->cs_pending); kfree(ctx->cs_pending);
return rc; return rc;
......
...@@ -229,6 +229,7 @@ static int vm_show(struct seq_file *s, void *data) ...@@ -229,6 +229,7 @@ static int vm_show(struct seq_file *s, void *data)
{ {
struct hl_debugfs_entry *entry = s->private; struct hl_debugfs_entry *entry = s->private;
struct hl_dbg_device_entry *dev_entry = entry->dev_entry; struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
struct hl_vm_hw_block_list_node *lnode;
struct hl_ctx *ctx; struct hl_ctx *ctx;
struct hl_vm *vm; struct hl_vm *vm;
struct hl_vm_hash_node *hnode; struct hl_vm_hash_node *hnode;
...@@ -272,6 +273,21 @@ static int vm_show(struct seq_file *s, void *data) ...@@ -272,6 +273,21 @@ static int vm_show(struct seq_file *s, void *data)
} }
mutex_unlock(&ctx->mem_hash_lock); mutex_unlock(&ctx->mem_hash_lock);
if (ctx->asid != HL_KERNEL_ASID_ID &&
!list_empty(&ctx->hw_block_mem_list)) {
seq_puts(s, "\nhw_block mappings:\n\n");
seq_puts(s, " virtual address size HW block id\n");
seq_puts(s, "-------------------------------------------\n");
mutex_lock(&ctx->hw_block_list_lock);
list_for_each_entry(lnode, &ctx->hw_block_mem_list,
node) {
seq_printf(s,
" 0x%-14lx %-6u %-9u\n",
lnode->vaddr, lnode->size, lnode->id);
}
mutex_unlock(&ctx->hw_block_list_lock);
}
vm = &ctx->hdev->vm; vm = &ctx->hdev->vm;
spin_lock(&vm->idr_lock); spin_lock(&vm->idr_lock);
......
...@@ -1103,9 +1103,11 @@ struct hl_pending_cb { ...@@ -1103,9 +1103,11 @@ struct hl_pending_cb {
* @mem_hash_lock: protects the mem_hash. * @mem_hash_lock: protects the mem_hash.
* @mmu_lock: protects the MMU page tables. Any change to the PGT, modifying the * @mmu_lock: protects the MMU page tables. Any change to the PGT, modifying the
* MMU hash or walking the PGT requires talking this lock. * MMU hash or walking the PGT requires talking this lock.
* @hw_block_list_lock: protects the HW block memory list.
* @debugfs_list: node in debugfs list of contexts. * @debugfs_list: node in debugfs list of contexts.
* pending_cb_list: list of pending command buffers waiting to be sent upon * pending_cb_list: list of pending command buffers waiting to be sent upon
* next user command submission context. * next user command submission context.
* @hw_block_mem_list: list of HW block virtual mapped addresses.
* @cs_counters: context command submission counters. * @cs_counters: context command submission counters.
* @cb_va_pool: device VA pool for command buffers which are mapped to the * @cb_va_pool: device VA pool for command buffers which are mapped to the
* device's MMU. * device's MMU.
...@@ -1142,8 +1144,10 @@ struct hl_ctx { ...@@ -1142,8 +1144,10 @@ struct hl_ctx {
struct hl_va_range *va_range[HL_VA_RANGE_TYPE_MAX]; struct hl_va_range *va_range[HL_VA_RANGE_TYPE_MAX];
struct mutex mem_hash_lock; struct mutex mem_hash_lock;
struct mutex mmu_lock; struct mutex mmu_lock;
struct mutex hw_block_list_lock;
struct list_head debugfs_list; struct list_head debugfs_list;
struct list_head pending_cb_list; struct list_head pending_cb_list;
struct list_head hw_block_mem_list;
struct hl_cs_counters_atomic cs_counters; struct hl_cs_counters_atomic cs_counters;
struct gen_pool *cb_va_pool; struct gen_pool *cb_va_pool;
u64 cs_sequence; u64 cs_sequence;
...@@ -1362,6 +1366,23 @@ struct hl_vm_hash_node { ...@@ -1362,6 +1366,23 @@ struct hl_vm_hash_node {
void *ptr; void *ptr;
}; };
/**
* struct hl_vm_hw_block_list_node - list element from user virtual address to
* HW block id.
* @node: node to hang on the list in context object.
* @ctx: the context this node belongs to.
* @vaddr: virtual address of the HW block.
* @size: size of the block.
* @id: HW block id (handle).
*/
struct hl_vm_hw_block_list_node {
struct list_head node;
struct hl_ctx *ctx;
unsigned long vaddr;
u32 size;
u32 id;
};
/** /**
* struct hl_vm_phys_pg_pack - physical page pack. * struct hl_vm_phys_pg_pack - physical page pack.
* @vm_type: describes the type of the virtual area descriptor. * @vm_type: describes the type of the virtual area descriptor.
...@@ -2278,6 +2299,9 @@ void hl_vm_ctx_fini(struct hl_ctx *ctx); ...@@ -2278,6 +2299,9 @@ void hl_vm_ctx_fini(struct hl_ctx *ctx);
int hl_vm_init(struct hl_device *hdev); int hl_vm_init(struct hl_device *hdev);
void hl_vm_fini(struct hl_device *hdev); void hl_vm_fini(struct hl_device *hdev);
void hl_hw_block_mem_init(struct hl_ctx *ctx);
void hl_hw_block_mem_fini(struct hl_ctx *ctx);
u64 hl_reserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx, u64 hl_reserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx,
enum hl_va_range_type type, u32 size, u32 alignment); enum hl_va_range_type type, u32 size, u32 alignment);
int hl_unreserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx, int hl_unreserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx,
......
...@@ -1305,9 +1305,15 @@ static int map_block(struct hl_device *hdev, u64 address, u64 *handle, ...@@ -1305,9 +1305,15 @@ static int map_block(struct hl_device *hdev, u64 address, u64 *handle,
static void hw_block_vm_close(struct vm_area_struct *vma) static void hw_block_vm_close(struct vm_area_struct *vma)
{ {
struct hl_ctx *ctx = (struct hl_ctx *) vma->vm_private_data; struct hl_vm_hw_block_list_node *lnode =
(struct hl_vm_hw_block_list_node *) vma->vm_private_data;
struct hl_ctx *ctx = lnode->ctx;
mutex_lock(&ctx->hw_block_list_lock);
list_del(&lnode->node);
mutex_unlock(&ctx->hw_block_list_lock);
hl_ctx_put(ctx); hl_ctx_put(ctx);
kfree(lnode);
vma->vm_private_data = NULL; vma->vm_private_data = NULL;
} }
...@@ -1325,7 +1331,9 @@ static const struct vm_operations_struct hw_block_vm_ops = { ...@@ -1325,7 +1331,9 @@ static const struct vm_operations_struct hw_block_vm_ops = {
*/ */
int hl_hw_block_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma) int hl_hw_block_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
{ {
struct hl_vm_hw_block_list_node *lnode;
struct hl_device *hdev = hpriv->hdev; struct hl_device *hdev = hpriv->hdev;
struct hl_ctx *ctx = hpriv->ctx;
u32 block_id, block_size; u32 block_id, block_size;
int rc; int rc;
...@@ -1351,17 +1359,31 @@ int hl_hw_block_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma) ...@@ -1351,17 +1359,31 @@ int hl_hw_block_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
return -EINVAL; return -EINVAL;
} }
lnode = kzalloc(sizeof(*lnode), GFP_KERNEL);
if (!lnode)
return -ENOMEM;
vma->vm_ops = &hw_block_vm_ops; vma->vm_ops = &hw_block_vm_ops;
vma->vm_private_data = hpriv->ctx; vma->vm_private_data = lnode;
hl_ctx_get(hdev, hpriv->ctx); hl_ctx_get(hdev, ctx);
rc = hdev->asic_funcs->hw_block_mmap(hdev, vma, block_id, block_size); rc = hdev->asic_funcs->hw_block_mmap(hdev, vma, block_id, block_size);
if (rc) { if (rc) {
hl_ctx_put(hpriv->ctx); hl_ctx_put(ctx);
kfree(lnode);
return rc; return rc;
} }
lnode->ctx = ctx;
lnode->vaddr = vma->vm_start;
lnode->size = block_size;
lnode->id = block_id;
mutex_lock(&ctx->hw_block_list_lock);
list_add_tail(&lnode->node, &ctx->hw_block_mem_list);
mutex_unlock(&ctx->hw_block_list_lock);
vma->vm_pgoff = block_id; vma->vm_pgoff = block_id;
return 0; return 0;
...@@ -2122,3 +2144,38 @@ void hl_vm_fini(struct hl_device *hdev) ...@@ -2122,3 +2144,38 @@ void hl_vm_fini(struct hl_device *hdev)
vm->init_done = false; vm->init_done = false;
} }
/**
* hl_hw_block_mem_init() - HW block memory initialization.
* @ctx: pointer to the habanalabs context structure.
*
* This function initializes the HW block virtual mapped addresses list and
* it's lock.
*/
void hl_hw_block_mem_init(struct hl_ctx *ctx)
{
mutex_init(&ctx->hw_block_list_lock);
INIT_LIST_HEAD(&ctx->hw_block_mem_list);
}
/**
* hl_hw_block_mem_fini() - HW block memory teardown.
* @ctx: pointer to the habanalabs context structure.
*
* This function clears the HW block virtual mapped addresses list and destroys
* it's lock.
*/
void hl_hw_block_mem_fini(struct hl_ctx *ctx)
{
struct hl_vm_hw_block_list_node *lnode, *tmp;
if (!list_empty(&ctx->hw_block_mem_list))
dev_crit(ctx->hdev->dev, "HW block mem list isn't empty\n");
list_for_each_entry_safe(lnode, tmp, &ctx->hw_block_mem_list, node) {
list_del(&lnode->node);
kfree(lnode);
}
mutex_destroy(&ctx->hw_block_list_lock);
}
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