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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ Date: Jan 2019
KernelVersion:  5.1
Contact:        ogabbay@kernel.org
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
Date:           Mar 2020
+11 −3
Original line number Diff line number Diff line
@@ -20,6 +20,11 @@ static void hl_ctx_fini(struct hl_ctx *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
	 * 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)
	if (!ctx->cs_pending)
		return -ENOMEM;

	hl_hw_block_mem_init(ctx);

	if (is_kernel_ctx) {
		ctx->asid = HL_KERNEL_ASID_ID; /* Kernel driver gets ASID 0 */
		rc = hl_vm_ctx_init(ctx);
		if (rc) {
			dev_err(hdev->dev, "Failed to init mem ctx module\n");
			rc = -ENOMEM;
			goto err_free_cs_pending;
			goto err_hw_block_mem_fini;
		}

		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)
		if (!ctx->asid) {
			dev_err(hdev->dev, "No free ASID, failed to create context\n");
			rc = -ENOMEM;
			goto err_free_cs_pending;
			goto err_hw_block_mem_fini;
		}

		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)
err_asid_free:
	if (ctx->asid != HL_KERNEL_ASID_ID)
		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);

	return rc;
+16 −0
Original line number Diff line number Diff line
@@ -229,6 +229,7 @@ static int vm_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 hl_vm_hw_block_list_node *lnode;
	struct hl_ctx *ctx;
	struct hl_vm *vm;
	struct hl_vm_hash_node *hnode;
@@ -272,6 +273,21 @@ static int vm_show(struct seq_file *s, void *data)
		}
		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;
		spin_lock(&vm->idr_lock);

+24 −0
Original line number Diff line number Diff line
@@ -1103,9 +1103,11 @@ struct hl_pending_cb {
 * @mem_hash_lock: protects the mem_hash.
 * @mmu_lock: protects the MMU page tables. Any change to the PGT, modifying the
 *            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.
 * pending_cb_list: list of pending command buffers waiting to be sent upon
 *                  next user command submission context.
 * @hw_block_mem_list: list of HW block virtual mapped addresses.
 * @cs_counters: context command submission counters.
 * @cb_va_pool: device VA pool for command buffers which are mapped to the
 *              device's MMU.
@@ -1142,8 +1144,10 @@ struct hl_ctx {
	struct hl_va_range		*va_range[HL_VA_RANGE_TYPE_MAX];
	struct mutex			mem_hash_lock;
	struct mutex			mmu_lock;
	struct mutex			hw_block_list_lock;
	struct list_head		debugfs_list;
	struct list_head		pending_cb_list;
	struct list_head		hw_block_mem_list;
	struct hl_cs_counters_atomic	cs_counters;
	struct gen_pool			*cb_va_pool;
	u64				cs_sequence;
@@ -1362,6 +1366,23 @@ struct hl_vm_hash_node {
	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.
 * @vm_type: describes the type of the virtual area descriptor.
@@ -2278,6 +2299,9 @@ void hl_vm_ctx_fini(struct hl_ctx *ctx);
int hl_vm_init(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,
		enum hl_va_range_type type, u32 size, u32 alignment);
int hl_unreserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx,
+61 −4
Original line number Diff line number Diff line
@@ -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)
{
	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);
	kfree(lnode);
	vma->vm_private_data = NULL;
}

@@ -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)
{
	struct hl_vm_hw_block_list_node *lnode;
	struct hl_device *hdev = hpriv->hdev;
	struct hl_ctx *ctx = hpriv->ctx;
	u32 block_id, block_size;
	int rc;

@@ -1351,17 +1359,31 @@ int hl_hw_block_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
		return -EINVAL;
	}

	lnode = kzalloc(sizeof(*lnode), GFP_KERNEL);
	if (!lnode)
		return -ENOMEM;

	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);
	if (rc) {
		hl_ctx_put(hpriv->ctx);
		hl_ctx_put(ctx);
		kfree(lnode);
		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;

	return 0;
@@ -2122,3 +2144,38 @@ void hl_vm_fini(struct hl_device *hdev)

	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);
}