diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/genwqe/card_dev.c | 2 | ||||
-rw-r--r-- | drivers/misc/genwqe/card_utils.c | 4 | ||||
-rw-r--r-- | drivers/misc/habanalabs/context.c | 6 | ||||
-rw-r--r-- | drivers/misc/habanalabs/debugfs.c | 65 | ||||
-rw-r--r-- | drivers/misc/habanalabs/device.c | 2 | ||||
-rw-r--r-- | drivers/misc/habanalabs/goya/goya.c | 3 | ||||
-rw-r--r-- | drivers/misc/habanalabs/goya/goyaP.h | 1 | ||||
-rw-r--r-- | drivers/misc/habanalabs/goya/goya_coresight.c | 31 | ||||
-rw-r--r-- | drivers/misc/habanalabs/habanalabs.h | 2 | ||||
-rw-r--r-- | drivers/misc/habanalabs/memory.c | 6 | ||||
-rw-r--r-- | drivers/misc/habanalabs/mmu.c | 8 | ||||
-rw-r--r-- | drivers/misc/lkdtm/bugs.c | 23 | ||||
-rw-r--r-- | drivers/misc/lkdtm/core.c | 6 | ||||
-rw-r--r-- | drivers/misc/lkdtm/lkdtm.h | 2 | ||||
-rw-r--r-- | drivers/misc/lkdtm/usercopy.c | 10 |
15 files changed, 98 insertions, 73 deletions
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index 8c1b63a4337b..d2098b4d2945 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c @@ -780,6 +780,8 @@ static int genwqe_pin_mem(struct genwqe_file *cfile, struct genwqe_mem *m) if ((m->addr == 0x0) || (m->size == 0)) return -EINVAL; + if (m->size > ULONG_MAX - PAGE_SIZE - (m->addr & ~PAGE_MASK)) + return -EINVAL; map_addr = (m->addr & PAGE_MASK); map_size = round_up(m->size + (m->addr & ~PAGE_MASK), PAGE_SIZE); diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 89cff9d1012b..7571700abc6e 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -586,6 +586,10 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr, /* determine space needed for page_list. */ data = (unsigned long)uaddr; offs = offset_in_page(data); + if (size > ULONG_MAX - PAGE_SIZE - offs) { + m->size = 0; /* mark unused and not added */ + return -EINVAL; + } m->nr_pages = DIV_ROUND_UP(offs + size, PAGE_SIZE); m->page_list = kcalloc(m->nr_pages, diff --git a/drivers/misc/habanalabs/context.c b/drivers/misc/habanalabs/context.c index 4804cdcf4c48..f4c92f110a72 100644 --- a/drivers/misc/habanalabs/context.c +++ b/drivers/misc/habanalabs/context.c @@ -26,6 +26,12 @@ static void hl_ctx_fini(struct hl_ctx *ctx) dma_fence_put(ctx->cs_pending[i]); if (ctx->asid != HL_KERNEL_ASID_ID) { + /* + * The engines are stopped as there is no executing CS, but the + * Coresight might be still working by accessing addresses + * related to the stopped engines. Hence stop it explicitly. + */ + hdev->asic_funcs->halt_coresight(hdev); hl_vm_ctx_fini(ctx); hl_asid_free(hdev, ctx->asid); } diff --git a/drivers/misc/habanalabs/debugfs.c b/drivers/misc/habanalabs/debugfs.c index a4447699ff4e..ba418aaa404c 100644 --- a/drivers/misc/habanalabs/debugfs.c +++ b/drivers/misc/habanalabs/debugfs.c @@ -459,41 +459,31 @@ static ssize_t mmu_write(struct file *file, const char __user *buf, struct hl_debugfs_entry *entry = s->private; struct hl_dbg_device_entry *dev_entry = entry->dev_entry; struct hl_device *hdev = dev_entry->hdev; - char kbuf[MMU_KBUF_SIZE], asid_kbuf[MMU_ASID_BUF_SIZE], - addr_kbuf[MMU_ADDR_BUF_SIZE]; + char kbuf[MMU_KBUF_SIZE]; char *c; ssize_t rc; if (!hdev->mmu_enable) return count; - memset(kbuf, 0, sizeof(kbuf)); - memset(asid_kbuf, 0, sizeof(asid_kbuf)); - memset(addr_kbuf, 0, sizeof(addr_kbuf)); - + if (count > sizeof(kbuf) - 1) + goto err; if (copy_from_user(kbuf, buf, count)) goto err; - - kbuf[MMU_KBUF_SIZE - 1] = 0; + kbuf[count] = 0; c = strchr(kbuf, ' '); if (!c) goto err; + *c = '\0'; - memcpy(asid_kbuf, kbuf, c - kbuf); - - rc = kstrtouint(asid_kbuf, 10, &dev_entry->mmu_asid); + rc = kstrtouint(kbuf, 10, &dev_entry->mmu_asid); if (rc) goto err; - c = strstr(kbuf, " 0x"); - if (!c) + if (strncmp(c+1, "0x", 2)) goto err; - - c += 3; - memcpy(addr_kbuf, c, (kbuf + count) - c); - - rc = kstrtoull(addr_kbuf, 16, &dev_entry->mmu_addr); + rc = kstrtoull(c+3, 16, &dev_entry->mmu_addr); if (rc) goto err; @@ -510,6 +500,7 @@ static int device_va_to_pa(struct hl_device *hdev, u64 virt_addr, { struct hl_ctx *ctx = hdev->user_ctx; u64 hop_addr, hop_pte_addr, hop_pte; + u64 offset_mask = HOP4_MASK | OFFSET_MASK; int rc = 0; if (!ctx) { @@ -552,12 +543,14 @@ static int device_va_to_pa(struct hl_device *hdev, u64 virt_addr, goto not_mapped; hop_pte_addr = get_hop4_pte_addr(ctx, hop_addr, virt_addr); hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr); + + offset_mask = OFFSET_MASK; } if (!(hop_pte & PAGE_PRESENT_MASK)) goto not_mapped; - *phys_addr = (hop_pte & PTE_PHYS_ADDR_MASK) | (virt_addr & OFFSET_MASK); + *phys_addr = (hop_pte & ~offset_mask) | (virt_addr & offset_mask); goto out; @@ -600,10 +593,8 @@ static ssize_t hl_data_read32(struct file *f, char __user *buf, } sprintf(tmp_buf, "0x%08x\n", val); - rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, - strlen(tmp_buf) + 1); - - return rc; + return simple_read_from_buffer(buf, count, ppos, tmp_buf, + strlen(tmp_buf)); } static ssize_t hl_data_write32(struct file *f, const char __user *buf, @@ -645,7 +636,6 @@ static ssize_t hl_get_power_state(struct file *f, char __user *buf, struct hl_dbg_device_entry *entry = file_inode(f)->i_private; struct hl_device *hdev = entry->hdev; char tmp_buf[200]; - ssize_t rc; int i; if (*ppos) @@ -660,10 +650,8 @@ static ssize_t hl_get_power_state(struct file *f, char __user *buf, sprintf(tmp_buf, "current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i); - rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, - strlen(tmp_buf) + 1); - - return rc; + return simple_read_from_buffer(buf, count, ppos, tmp_buf, + strlen(tmp_buf)); } static ssize_t hl_set_power_state(struct file *f, const char __user *buf, @@ -716,8 +704,8 @@ static ssize_t hl_i2c_data_read(struct file *f, char __user *buf, } sprintf(tmp_buf, "0x%02x\n", val); - rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, - strlen(tmp_buf) + 1); + rc = simple_read_from_buffer(buf, count, ppos, tmp_buf, + strlen(tmp_buf)); return rc; } @@ -806,18 +794,9 @@ static ssize_t hl_led2_write(struct file *f, const char __user *buf, static ssize_t hl_device_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { - char tmp_buf[200]; - ssize_t rc; - - if (*ppos) - return 0; - - sprintf(tmp_buf, - "Valid values: disable, enable, suspend, resume, cpu_timeout\n"); - rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, - strlen(tmp_buf) + 1); - - return rc; + static const char *help = + "Valid values: disable, enable, suspend, resume, cpu_timeout\n"; + return simple_read_from_buffer(buf, count, ppos, help, strlen(help)); } static ssize_t hl_device_write(struct file *f, const char __user *buf, @@ -825,7 +804,7 @@ static ssize_t hl_device_write(struct file *f, const char __user *buf, { struct hl_dbg_device_entry *entry = file_inode(f)->i_private; struct hl_device *hdev = entry->hdev; - char data[30]; + char data[30] = {0}; /* don't allow partial writes */ if (*ppos != 0) diff --git a/drivers/misc/habanalabs/device.c b/drivers/misc/habanalabs/device.c index 91a9e47a3482..0b19d3eefb98 100644 --- a/drivers/misc/habanalabs/device.c +++ b/drivers/misc/habanalabs/device.c @@ -231,6 +231,7 @@ static int device_early_init(struct hl_device *hdev) mutex_init(&hdev->fd_open_cnt_lock); mutex_init(&hdev->send_cpu_message_lock); + mutex_init(&hdev->mmu_cache_lock); INIT_LIST_HEAD(&hdev->hw_queues_mirror_list); spin_lock_init(&hdev->hw_queues_mirror_lock); atomic_set(&hdev->in_reset, 0); @@ -260,6 +261,7 @@ early_fini: */ static void device_early_fini(struct hl_device *hdev) { + mutex_destroy(&hdev->mmu_cache_lock); mutex_destroy(&hdev->send_cpu_message_lock); hl_cb_mgr_fini(hdev, &hdev->kernel_cb_mgr); diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index a582e29c1ee4..02d116b01a1a 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -4819,7 +4819,8 @@ static const struct hl_asic_funcs goya_funcs = { .set_dram_bar_base = goya_set_ddr_bar_base, .init_iatu = goya_init_iatu, .rreg = hl_rreg, - .wreg = hl_wreg + .wreg = hl_wreg, + .halt_coresight = goya_halt_coresight }; /* diff --git a/drivers/misc/habanalabs/goya/goyaP.h b/drivers/misc/habanalabs/goya/goyaP.h index 14e216cb3668..c83cab0d641e 100644 --- a/drivers/misc/habanalabs/goya/goyaP.h +++ b/drivers/misc/habanalabs/goya/goyaP.h @@ -202,6 +202,7 @@ void goya_add_device_attr(struct hl_device *hdev, struct attribute_group *dev_attr_grp); int goya_armcp_info_get(struct hl_device *hdev); int goya_debug_coresight(struct hl_device *hdev, void *data); +void goya_halt_coresight(struct hl_device *hdev); void goya_mmu_prepare(struct hl_device *hdev, u32 asid); int goya_mmu_clear_pgt_range(struct hl_device *hdev); diff --git a/drivers/misc/habanalabs/goya/goya_coresight.c b/drivers/misc/habanalabs/goya/goya_coresight.c index 1ac951f52d1e..d7ec7ad84cc6 100644 --- a/drivers/misc/habanalabs/goya/goya_coresight.c +++ b/drivers/misc/habanalabs/goya/goya_coresight.c @@ -425,8 +425,18 @@ static int goya_config_etr(struct hl_device *hdev, WREG32(base_reg + 0x28, 0); WREG32(base_reg + 0x304, 0); - if (params->output_size >= sizeof(u32)) - *(u32 *) params->output = RREG32(base_reg + 0x18); + if (params->output_size >= sizeof(u64)) { + u32 rwp, rwphi; + + /* + * The trace buffer address is 40 bits wide. The end of + * the buffer is set in the RWP register (lower 32 + * bits), and in the RWPHI register (upper 8 bits). + */ + rwp = RREG32(base_reg + 0x18); + rwphi = RREG32(base_reg + 0x3c) & 0xff; + *(u64 *) params->output = ((u64) rwphi << 32) | rwp; + } } return 0; @@ -626,3 +636,20 @@ int goya_debug_coresight(struct hl_device *hdev, void *data) return rc; } + +void goya_halt_coresight(struct hl_device *hdev) +{ + struct hl_debug_params params = {}; + int i, rc; + + for (i = GOYA_ETF_FIRST ; i <= GOYA_ETF_LAST ; i++) { + params.reg_idx = i; + rc = goya_config_etf(hdev, ¶ms); + if (rc) + dev_err(hdev->dev, "halt ETF failed, %d/%d\n", rc, i); + } + + rc = goya_config_etr(hdev, ¶ms); + if (rc) + dev_err(hdev->dev, "halt ETR failed, %d\n", rc); +} diff --git a/drivers/misc/habanalabs/habanalabs.h b/drivers/misc/habanalabs/habanalabs.h index 71243b319920..adef7d9d7488 100644 --- a/drivers/misc/habanalabs/habanalabs.h +++ b/drivers/misc/habanalabs/habanalabs.h @@ -501,6 +501,7 @@ enum hl_pll_frequency { * @init_iatu: Initialize the iATU unit inside the PCI controller. * @rreg: Read a register. Needed for simulator support. * @wreg: Write a register. Needed for simulator support. + * @halt_coresight: stop the ETF and ETR traces. */ struct hl_asic_funcs { int (*early_init)(struct hl_device *hdev); @@ -578,6 +579,7 @@ struct hl_asic_funcs { int (*init_iatu)(struct hl_device *hdev); u32 (*rreg)(struct hl_device *hdev, u32 reg); void (*wreg)(struct hl_device *hdev, u32 reg, u32 val); + void (*halt_coresight)(struct hl_device *hdev); }; diff --git a/drivers/misc/habanalabs/memory.c b/drivers/misc/habanalabs/memory.c index d67d24c13efd..693877e37fd8 100644 --- a/drivers/misc/habanalabs/memory.c +++ b/drivers/misc/habanalabs/memory.c @@ -675,11 +675,6 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx, total_npages += npages; - if (first) { - first = false; - dma_addr &= PAGE_MASK_2MB; - } - if ((npages % PGS_IN_2MB_PAGE) || (dma_addr & (PAGE_SIZE_2MB - 1))) is_huge_page_opt = false; @@ -704,7 +699,6 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx, phys_pg_pack->total_size = total_npages * page_size; j = 0; - first = true; for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) { npages = get_sg_info(sg, &dma_addr); diff --git a/drivers/misc/habanalabs/mmu.c b/drivers/misc/habanalabs/mmu.c index 533d9315b6fb..10aee3141444 100644 --- a/drivers/misc/habanalabs/mmu.c +++ b/drivers/misc/habanalabs/mmu.c @@ -404,15 +404,12 @@ int hl_mmu_init(struct hl_device *hdev) /* MMU H/W init was already done in device hw_init() */ - mutex_init(&hdev->mmu_cache_lock); - hdev->mmu_pgt_pool = gen_pool_create(__ffs(prop->mmu_hop_table_size), -1); if (!hdev->mmu_pgt_pool) { dev_err(hdev->dev, "Failed to create page gen pool\n"); - rc = -ENOMEM; - goto err_pool_create; + return -ENOMEM; } rc = gen_pool_add(hdev->mmu_pgt_pool, prop->mmu_pgt_addr + @@ -436,8 +433,6 @@ int hl_mmu_init(struct hl_device *hdev) err_pool_add: gen_pool_destroy(hdev->mmu_pgt_pool); -err_pool_create: - mutex_destroy(&hdev->mmu_cache_lock); return rc; } @@ -459,7 +454,6 @@ void hl_mmu_fini(struct hl_device *hdev) kvfree(hdev->mmu_shadow_hop0); gen_pool_destroy(hdev->mmu_pgt_pool); - mutex_destroy(&hdev->mmu_cache_lock); /* MMU H/W fini will be done in device hw_fini() */ } diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c index 7eebbdfbcacd..17f839dee976 100644 --- a/drivers/misc/lkdtm/bugs.c +++ b/drivers/misc/lkdtm/bugs.c @@ -32,12 +32,20 @@ static int recur_count = REC_NUM_DEFAULT; static DEFINE_SPINLOCK(lock_me_up); -static int recursive_loop(int remaining) +/* + * Make sure compiler does not optimize this function or stack frame away: + * - function marked noinline + * - stack variables are marked volatile + * - stack variables are written (memset()) and read (pr_info()) + * - function has external effects (pr_info()) + * */ +static int noinline recursive_loop(int remaining) { - char buf[REC_STACK_SIZE]; + volatile char buf[REC_STACK_SIZE]; - /* Make sure compiler does not optimize this away. */ - memset(buf, (remaining & 0xff) | 0x1, REC_STACK_SIZE); + memset((void *)buf, remaining & 0xFF, sizeof(buf)); + pr_info("loop %d/%d ...\n", (int)buf[remaining % sizeof(buf)], + recur_count); if (!remaining) return 0; else @@ -81,9 +89,12 @@ void lkdtm_LOOP(void) ; } -void lkdtm_OVERFLOW(void) +void lkdtm_EXHAUST_STACK(void) { - (void) recursive_loop(recur_count); + pr_info("Calling function with %d frame size to depth %d ...\n", + REC_STACK_SIZE, recur_count); + recursive_loop(recur_count); + pr_info("FAIL: survived without exhausting stack?!\n"); } static noinline void __lkdtm_CORRUPT_STACK(void *stack) diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index 1972dad966f5..8a1428d4f138 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -106,12 +106,12 @@ static const struct crashtype crashtypes[] = { CRASHTYPE(WARNING), CRASHTYPE(EXCEPTION), CRASHTYPE(LOOP), - CRASHTYPE(OVERFLOW), + CRASHTYPE(EXHAUST_STACK), + CRASHTYPE(CORRUPT_STACK), + CRASHTYPE(CORRUPT_STACK_STRONG), CRASHTYPE(CORRUPT_LIST_ADD), CRASHTYPE(CORRUPT_LIST_DEL), CRASHTYPE(CORRUPT_USER_DS), - CRASHTYPE(CORRUPT_STACK), - CRASHTYPE(CORRUPT_STACK_STRONG), CRASHTYPE(STACK_GUARD_PAGE_LEADING), CRASHTYPE(STACK_GUARD_PAGE_TRAILING), CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE), diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h index b69ee004a3f7..23dc565b4307 100644 --- a/drivers/misc/lkdtm/lkdtm.h +++ b/drivers/misc/lkdtm/lkdtm.h @@ -13,7 +13,7 @@ void lkdtm_BUG(void); void lkdtm_WARNING(void); void lkdtm_EXCEPTION(void); void lkdtm_LOOP(void); -void lkdtm_OVERFLOW(void); +void lkdtm_EXHAUST_STACK(void); void lkdtm_CORRUPT_STACK(void); void lkdtm_CORRUPT_STACK_STRONG(void); void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void); diff --git a/drivers/misc/lkdtm/usercopy.c b/drivers/misc/lkdtm/usercopy.c index d5a0e7f1813b..e172719dd86d 100644 --- a/drivers/misc/lkdtm/usercopy.c +++ b/drivers/misc/lkdtm/usercopy.c @@ -324,14 +324,16 @@ free_user: void lkdtm_USERCOPY_KERNEL_DS(void) { - char __user *user_ptr = (char __user *)ERR_PTR(-EINVAL); + char __user *user_ptr = + (char __user *)(0xFUL << (sizeof(unsigned long) * 8 - 4)); mm_segment_t old_fs = get_fs(); char buf[10] = {0}; - pr_info("attempting copy_to_user on unmapped kernel address\n"); + pr_info("attempting copy_to_user() to noncanonical address: %px\n", + user_ptr); set_fs(KERNEL_DS); - if (copy_to_user(user_ptr, buf, sizeof(buf))) - pr_info("copy_to_user un unmapped kernel address failed\n"); + if (copy_to_user(user_ptr, buf, sizeof(buf)) == 0) + pr_err("copy_to_user() to noncanonical address succeeded!?\n"); set_fs(old_fs); } |