/** * Submit the 8401 workaround job. * * Important for BASE_HW_ISSUE_8987: This job always uses 16 RMUs * - Therefore, on slot[1] it will always use the same number of RMUs as another * GLES job. * - On slot[2], no other job (GLES or otherwise) will be running on the * cores, by virtue of it being slot[2]. Therefore, any value of RMUs is * acceptable. */ void kbasep_8401_submit_dummy_job(kbase_device *kbdev, int js) { u32 cfg; mali_addr64 jc; /* While this workaround is active we reserve the last address space just for submitting the dummy jobs */ int as = kbdev->nr_hw_address_spaces; /* Don't issue compute jobs on job slot 0 */ OSK_ASSERT(js != 0); OSK_ASSERT(js < KBASE_8401_WORKAROUND_COMPUTEJOB_COUNT); /* Job chain GPU address */ jc = (js+WORKAROUND_PAGE_OFFSET)*OSK_PAGE_SIZE; /* GPU phys address (see kbase_mmu_insert_pages call in kbasep_8401_workaround_init*/ /* Clear the job status words which may contain values from a previous job completion */ memset(kbdev->workaround_compute_job_va[js], 0, 4*sizeof(u32)); /* Get the affinity of the previous job */ dummy_job_atom[js].affinity = ((u64)kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_LO), NULL)) | (((u64)kbase_reg_read(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_HI), NULL)) << 32); /* Don't submit a compute job if the affinity was previously zero (i.e. no jobs have run yet on this slot) */ if(!dummy_job_atom[js].affinity) { return; } /* Ensure that our page tables are programmed into the MMU */ kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_TRANSTAB_LO), (kbdev->workaround_kctx->pgd & ASn_TRANSTAB_ADDR_SPACE_MASK) | ASn_TRANSTAB_READ_INNER | ASn_TRANSTAB_ADRMODE_TABLE, NULL); kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_TRANSTAB_HI), (kbdev->workaround_kctx->pgd >> 32), NULL); kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_MEMATTR_LO), ASn_MEMATTR_IMPL_DEF_CACHE_POLICY, NULL); kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_MEMATTR_HI), ASn_MEMATTR_IMPL_DEF_CACHE_POLICY, NULL); kbase_reg_write(kbdev, MMU_AS_REG(as, ASn_COMMAND), ASn_COMMAND_UPDATE, NULL); kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_LO), jc & 0xFFFFFFFF, NULL); kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_HEAD_NEXT_HI), jc >> 32, NULL); kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_NEXT_LO), dummy_job_atom[js].affinity & 0xFFFFFFFF, NULL); kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_AFFINITY_NEXT_HI), dummy_job_atom[js].affinity >> 32, NULL); /* start MMU, medium priority, cache clean/flush on end, clean/flush on start */ cfg = as | JSn_CONFIG_END_FLUSH_CLEAN_INVALIDATE | JSn_CONFIG_START_MMU | JSn_CONFIG_START_FLUSH_CLEAN_INVALIDATE | JSn_CONFIG_THREAD_PRI(8); kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_CONFIG_NEXT), cfg, NULL); KBASE_TRACE_ADD_SLOT( kbdev, JM_SUBMIT, NULL, 0, jc, js ); kbase_reg_write(kbdev, JOB_SLOT_REG(js, JSn_COMMAND_NEXT), JSn_COMMAND_START, NULL); /* Report that the job has been submitted */ kbasep_jm_enqueue_submit_slot(&kbdev->jm_slots[js], &dummy_job_atom[js]); }
bool kbase_debug_job_fault_reg_snapshot_init(struct kbase_context *kctx, int reg_range) { int i, j; int offset = 0; int slot_number; int as_number; if (kctx->reg_dump == NULL) return false; slot_number = kctx->kbdev->gpu_props.num_job_slots; as_number = kctx->kbdev->gpu_props.num_address_spaces; /* get the GPU control registers*/ for (i = 0; i < sizeof(gpu_control_reg_snapshot)/4; i++) { kctx->reg_dump[offset] = GPU_CONTROL_REG(gpu_control_reg_snapshot[i]); offset += 2; } /* get the Job control registers*/ for (i = 0; i < sizeof(job_control_reg_snapshot)/4; i++) { kctx->reg_dump[offset] = JOB_CONTROL_REG(job_control_reg_snapshot[i]); offset += 2; } /* get the Job Slot registers*/ for (j = 0; j < slot_number; j++) { for (i = 0; i < sizeof(job_slot_reg_snapshot)/4; i++) { kctx->reg_dump[offset] = JOB_SLOT_REG(j, job_slot_reg_snapshot[i]); offset += 2; } } /* get the MMU registers*/ for (i = 0; i < sizeof(mmu_reg_snapshot)/4; i++) { kctx->reg_dump[offset] = MMU_REG(mmu_reg_snapshot[i]); offset += 2; } /* get the Address space registers*/ for (j = 0; j < as_number; j++) { for (i = 0; i < sizeof(as_reg_snapshot)/4; i++) { kctx->reg_dump[offset] = MMU_AS_REG(j, as_reg_snapshot[i]); offset += 2; } } WARN_ON(offset >= (reg_range*2/4)); /* set the termination flag*/ kctx->reg_dump[offset] = REGISTER_DUMP_TERMINATION_FLAG; kctx->reg_dump[offset + 1] = REGISTER_DUMP_TERMINATION_FLAG; dev_dbg(kctx->kbdev->dev, "kbase_job_fault_reg_snapshot_init:%d\n", offset); return true; }