From e9d5e7dfca6ac2fa7af380ceea0a0ca4ac3827c6 Mon Sep 17 00:00:00 2001 From: Mahantesh Kumbar Date: Mon, 23 May 2016 16:12:11 +0530 Subject: gpu: nvgpu: secure boot HAL update Updated/added secure boot HAL with methods required to support multiple GPU chips. JIRA DNVGPU-10 Change-Id: I343b289f2236fd6a6b0ecf9115367ce19990e7d5 Signed-off-by: Mahantesh Kumbar Reviewed-on: http://git-master/r/1151784 Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/gk20a.h | 19 +++++ drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 13 ++- drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 153 ++++++++++++++++++++++++++++-------- drivers/gpu/nvgpu/gm20b/acr_gm20b.h | 12 +-- drivers/gpu/nvgpu/gm20b/gr_gm20b.c | 10 ++- 5 files changed, 163 insertions(+), 44 deletions(-) (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index d131862b..d96ce3d8 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -534,6 +534,25 @@ struct gpu_ops { (struct gk20a *g, u32 mask); void (*dump_secure_fuses)(struct gk20a *g); int (*reset)(struct gk20a *g); + int (*falcon_wait_for_halt)(struct gk20a *g, + unsigned int timeout); + int (*falcon_clear_halt_interrupt_status)(struct gk20a *g, + unsigned int timeout); + int (*init_falcon_setup_hw)(struct gk20a *g, + struct flcn_bl_dmem_desc *desc, u32 bl_sz); + bool (*is_lazy_bootstrap)(u32 falcon_id); + bool (*is_priv_load)(u32 falcon_id); + void (*get_wpr)(struct gk20a *g, u64 *base, u64 *size); + int (*alloc_blob_space)(struct gk20a *g, + size_t size, struct mem_desc *mem); + int (*pmu_populate_loader_cfg)(struct gk20a *g, + struct lsfm_managed_ucode_img *lsfm, + union flcn_bl_generic_desc *p_bl_gen_desc, + u32 *p_bl_gen_desc_size); + int (*flcn_populate_bl_dmem_desc)(struct gk20a *g, + struct lsfm_managed_ucode_img *lsfm, + union flcn_bl_generic_desc *p_bl_gen_desc, + u32 *p_bl_gen_desc_size, u32 falconid); u32 lspmuwprinitdone; u32 lsfloadedfalconid; bool fecsbootstrapdone; diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 08ef7738..a8ebaf7a 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c @@ -2758,9 +2758,12 @@ static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr) int gk20a_pmu_reset(struct gk20a *g) { - gk20a_reset(g, mc_enable_pwr_enabled_f()); + int err; + struct pmu_gk20a *pmu = &g->pmu; - return 0; + err = pmu_reset(pmu); + + return err; } void gk20a_init_pmu_ops(struct gpu_ops *gops) @@ -2776,6 +2779,12 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops) gops->pmu.pmu_pg_grinit_param = NULL; gops->pmu.send_lrf_tex_ltc_dram_overide_en_dis_cmd = NULL; gops->pmu.dump_secure_fuses = NULL; + gops->pmu.is_lazy_bootstrap = NULL; + gops->pmu.is_priv_load = NULL; + gops->pmu.get_wpr = NULL; + gops->pmu.alloc_blob_space = NULL; + gops->pmu.pmu_populate_loader_cfg = NULL; + gops->pmu.flcn_populate_bl_dmem_desc = NULL; gops->pmu.reset = gk20a_pmu_reset; } diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c index 3ac2cec8..ea4500eb 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c @@ -36,6 +36,14 @@ typedef int (*get_ucode_details)(struct gk20a *g, struct flcn_ucode_img *udata); /*Externs*/ /*Forwards*/ +static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); +static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); +static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); +static int gm20b_bootstrap_hs_flcn(struct gk20a *g); +static int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout); +static int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout); +static int gm20b_init_pmu_setup_hw1(struct gk20a *g, + struct flcn_bl_dmem_desc *desc, u32 bl_sz); static int lsfm_discover_ucode_images(struct gk20a *g, struct ls_flcn_mgr *plsfm); static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm, @@ -45,13 +53,18 @@ static void lsfm_free_nonpmu_ucode_img_res(struct flcn_ucode_img *p_img); static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm); static void lsfm_init_wpr_contents(struct gk20a *g, struct ls_flcn_mgr *plsfm, struct mem_desc *nonwpr); -static int acr_ucode_patch_sig(struct gk20a *g, - unsigned int *p_img, - unsigned int *p_prod_sig, - unsigned int *p_dbg_sig, - unsigned int *p_patch_loc, - unsigned int *p_patch_ind); static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm); +static int gm20b_pmu_populate_loader_cfg(struct gk20a *g, + struct lsfm_managed_ucode_img *lsfm, + union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size); +static int gm20b_flcn_populate_bl_dmem_desc(struct gk20a *g, + struct lsfm_managed_ucode_img *lsfm, + union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size, + u32 falconid); +static int gm20b_alloc_blob_space(struct gk20a *g, + size_t size, struct mem_desc *mem); +static bool gm20b_is_priv_load(u32 falcon_id); +static bool gm20b_is_lazy_bootstrap(u32 falcon_id); /*Globals*/ static get_ucode_details pmu_acr_supp_ucode_list[] = { @@ -72,14 +85,33 @@ static void start_gm20b_pmu(struct gk20a *g) pwr_falcon_cpuctl_startcpu_f(1)); } +void gm20b_wpr_info(struct gk20a *g, u64 *base, u64 *size) +{ + struct mc_carveout_info inf; + + mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2); + *base = inf.base; + *size = inf.size; +} + void gm20b_init_secure_pmu(struct gpu_ops *gops) { gops->pmu.prepare_ucode = prepare_ucode_blob; gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn; + gops->pmu.is_lazy_bootstrap = gm20b_is_lazy_bootstrap; + gops->pmu.is_priv_load = gm20b_is_priv_load; + gops->pmu.get_wpr = gm20b_wpr_info; + gops->pmu.alloc_blob_space = gm20b_alloc_blob_space; + gops->pmu.pmu_populate_loader_cfg = gm20b_pmu_populate_loader_cfg; + gops->pmu.flcn_populate_bl_dmem_desc = gm20b_flcn_populate_bl_dmem_desc; + gops->pmu.falcon_wait_for_halt = pmu_wait_for_halt; + gops->pmu.falcon_clear_halt_interrupt_status = + clear_halt_interrupt_status; + gops->pmu.init_falcon_setup_hw = gm20b_init_pmu_setup_hw1; } /* TODO - check if any free blob res needed*/ -int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) +static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) { const struct firmware *pmu_fw, *pmu_desc, *pmu_sig; struct pmu_gk20a *pmu = &g->pmu; @@ -143,7 +175,7 @@ release_img_fw: return err; } -int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) +static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) { struct lsf_ucode_desc *lsf_desc; const struct firmware *fecs_sig; @@ -210,7 +242,7 @@ rel_sig: release_firmware(fecs_sig); return err; } -int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) +static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) { struct lsf_ucode_desc *lsf_desc; const struct firmware *gpccs_sig; @@ -282,6 +314,52 @@ rel_sig: return err; } +static bool gm20b_is_lazy_bootstrap(u32 falcon_id) +{ + bool enable_status = false; + + switch (falcon_id) { + case LSF_FALCON_ID_FECS: + enable_status = false; + break; + case LSF_FALCON_ID_GPCCS: + enable_status = false; + break; + default: + break; + } + + return enable_status; +} + +static bool gm20b_is_priv_load(u32 falcon_id) +{ + bool enable_status = false; + + switch (falcon_id) { + case LSF_FALCON_ID_FECS: + enable_status = false; + break; + case LSF_FALCON_ID_GPCCS: + enable_status = false; + break; + default: + break; + } + + return enable_status; +} + +static int gm20b_alloc_blob_space(struct gk20a *g, + size_t size, struct mem_desc *mem) +{ + int err; + + err = gk20a_gmmu_alloc(g, size, mem); + + return err; +} + int prepare_ucode_blob(struct gk20a *g) { @@ -312,11 +390,12 @@ int prepare_ucode_blob(struct gk20a *g) gm20b_mm_mmu_vpr_info_fetch(g); gr_gk20a_init_ctxsw_ucode(g); - mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2); - gm20b_dbg_pmu("wpr carveout base:%llx\n", inf.base); + g->ops.pmu.get_wpr(g, &inf.base, &inf.size); wpr_addr = (phys_addr_t)inf.base; - gm20b_dbg_pmu("wpr carveout size :%llx\n", inf.size); wprsize = (u32)inf.size; + gm20b_dbg_pmu("wpr carveout base:%llx\n", inf.base); + gm20b_dbg_pmu("wpr carveout size :%x\n", wprsize); + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); if (!sgt) { gk20a_err(dev_from_gk20a(g), "failed to allocate memory\n"); @@ -349,7 +428,8 @@ int prepare_ucode_blob(struct gk20a *g) goto free_sgt; /*Alloc memory to hold ucode blob contents*/ - err = gk20a_gmmu_alloc(g, plsfm->wpr_size, &g->acr.ucode_blob); + err = g->ops.pmu.alloc_blob_space(g, plsfm->wpr_size + , &g->acr.ucode_blob); if (err) goto free_sgt; @@ -458,7 +538,7 @@ static int lsfm_discover_ucode_images(struct gk20a *g, } -static int pmu_populate_loader_cfg(struct gk20a *g, +static int gm20b_pmu_populate_loader_cfg(struct gk20a *g, struct lsfm_managed_ucode_img *lsfm, union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size) { @@ -485,7 +565,7 @@ static int pmu_populate_loader_cfg(struct gk20a *g, physical addresses of each respective segment. */ addr_base = lsfm->lsb_header.ucode_off; - mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2); + g->ops.pmu.get_wpr(g, &inf.base, &inf.size); addr_base += inf.base; gm20b_dbg_pmu("pmu loader cfg u32 addrbase %x\n", (u32)addr_base); /*From linux*/ @@ -530,7 +610,7 @@ static int pmu_populate_loader_cfg(struct gk20a *g, return 0; } -static int flcn_populate_bl_dmem_desc(struct gk20a *g, +static int gm20b_flcn_populate_bl_dmem_desc(struct gk20a *g, struct lsfm_managed_ucode_img *lsfm, union flcn_bl_generic_desc *p_bl_gen_desc, u32 *p_bl_gen_desc_size, u32 falconid) @@ -557,13 +637,13 @@ static int flcn_populate_bl_dmem_desc(struct gk20a *g, physical addresses of each respective segment. */ addr_base = lsfm->lsb_header.ucode_off; - mc_get_carveout_info(&inf, NULL, MC_SECURITY_CARVEOUT2); + g->ops.pmu.get_wpr(g, &inf.base, &inf.size); if (falconid == LSF_FALCON_ID_GPCCS) addr_base += g->pmu.wpr_buf.gpu_va; else addr_base += inf.base; gm20b_dbg_pmu("gen loader cfg %x u32 addrbase %x ID\n", (u32)addr_base, - lsfm->wpr_header.falcon_id); + lsfm->wpr_header.falcon_id); addr_code = u64_lo32((addr_base + desc->app_start_offset + desc->app_resident_code_offset) >> 8); @@ -595,16 +675,17 @@ static int lsfm_fill_flcn_bl_gen_desc(struct gk20a *g, struct pmu_gk20a *pmu = &g->pmu; if (pnode->wpr_header.falcon_id != pmu->falcon_id) { gm20b_dbg_pmu("non pmu. write flcn bl gen desc\n"); - flcn_populate_bl_dmem_desc(g, pnode, &pnode->bl_gen_desc, - &pnode->bl_gen_desc_size, - pnode->wpr_header.falcon_id); + g->ops.pmu.flcn_populate_bl_dmem_desc(g, + pnode, &pnode->bl_gen_desc, + &pnode->bl_gen_desc_size, + pnode->wpr_header.falcon_id); return 0; } if (pmu->pmu_mode & PMU_LSFM_MANAGED) { gm20b_dbg_pmu("pmu write flcn bl gen desc\n"); if (pnode->wpr_header.falcon_id == pmu->falcon_id) - return pmu_populate_loader_cfg(g, pnode, + return g->ops.pmu.pmu_populate_loader_cfg(g, pnode, &pnode->bl_gen_desc, &pnode->bl_gen_desc_size); } @@ -808,7 +889,8 @@ static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g, data = NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX_TRUE; pnode->lsb_header.flags = data; } - if (falcon_id == LSF_FALCON_ID_GPCCS) { + + if (g->ops.pmu.is_priv_load(falcon_id)) { pnode->lsb_header.flags |= NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE; } @@ -833,8 +915,8 @@ static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm, pnode->wpr_header.bootstrap_owner = LSF_BOOTSTRAP_OWNER_DEFAULT; pnode->wpr_header.status = LSF_IMAGE_STATUS_COPY; - if (falcon_id == LSF_FALCON_ID_GPCCS) - pnode->wpr_header.lazy_bootstrap = 1; + pnode->wpr_header.lazy_bootstrap = + g->ops.pmu.is_lazy_bootstrap(falcon_id); /*TODO to check if PDB_PROP_FLCN_LAZY_BOOTSTRAP is to be supported by Android */ @@ -1090,8 +1172,7 @@ static u8 pmu_is_debug_mode_en(struct gk20a *g) /* * @brief Patch signatures into ucode image */ -static int -acr_ucode_patch_sig(struct gk20a *g, +int acr_ucode_patch_sig(struct gk20a *g, unsigned int *p_img, unsigned int *p_prod_sig, unsigned int *p_dbg_sig, @@ -1231,7 +1312,7 @@ static int gm20b_init_pmu_setup_hw1(struct gk20a *g, gk20a_dbg_fn(""); mutex_lock(&pmu->isr_mutex); - pmu_reset(pmu); + g->ops.pmu.reset(g); pmu->isr_enabled = true; mutex_unlock(&pmu->isr_mutex); @@ -1346,20 +1427,24 @@ int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) * to PMU halt */ - if (clear_halt_interrupt_status(g, gk20a_get_gr_idle_timeout(g))) + if (g->ops.pmu.falcon_clear_halt_interrupt_status(g, + gk20a_get_gr_idle_timeout(g))) goto err_unmap_bl; gm20b_dbg_pmu("phys sec reg %x\n", gk20a_readl(g, pwr_falcon_mmu_phys_sec_r())); gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r())); - gm20b_init_pmu_setup_hw1(g, desc, acr->hsbl_ucode.size); + g->ops.pmu.init_falcon_setup_hw(g, desc, acr->hsbl_ucode.size); + /* Poll for HALT */ if (b_wait_for_halt) { - err = pmu_wait_for_halt(g, ACR_COMPLETION_TIMEOUT_MS); + err = g->ops.pmu.falcon_wait_for_halt(g, + ACR_COMPLETION_TIMEOUT_MS); if (err == 0) { /* Clear the HALT interrupt */ - if (clear_halt_interrupt_status(g, gk20a_get_gr_idle_timeout(g))) + if (g->ops.pmu.falcon_clear_halt_interrupt_status(g, + gk20a_get_gr_idle_timeout(g))) goto err_unmap_bl; } else @@ -1387,7 +1472,7 @@ err_done: * @param[in] timeout Timeout in msec for PMU to halt * @return '0' if PMU halts */ -int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout) +static int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout) { u32 data = 0; int completion = -EBUSY; @@ -1424,7 +1509,7 @@ int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout) * @param[in] timeout_us Timeout in msec for halt to clear * @return '0' if PMU halt irq status is clear */ -int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout) +static int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout) { u32 data = 0; unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.h b/drivers/gpu/nvgpu/gm20b/acr_gm20b.h index 414e22b6..179345b9 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.h @@ -406,13 +406,13 @@ struct acr_gm20b { void gm20b_init_secure_pmu(struct gpu_ops *gops); int prepare_ucode_blob(struct gk20a *g); -int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); -int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); -int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img); -int gm20b_bootstrap_hs_flcn(struct gk20a *g); int gm20b_pmu_setup_sw(struct gk20a *g); int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt); -int pmu_wait_for_halt(struct gk20a *g, unsigned int timeout_us); -int clear_halt_interrupt_status(struct gk20a *g, unsigned int timeout); int gm20b_init_nspmu_setup_hw1(struct gk20a *g); +int acr_ucode_patch_sig(struct gk20a *g, + unsigned int *p_img, + unsigned int *p_prod_sig, + unsigned int *p_dbg_sig, + unsigned int *p_patch_loc, + unsigned int *p_patch_ind); #endif /*__ACR_GM20B_H_*/ diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c index 84b36232..d5131b7a 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c @@ -708,6 +708,7 @@ static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) u32 err, flags; u32 reg_offset = gr_gpcs_gpccs_falcon_hwcfg_r() - gr_fecs_falcon_hwcfg_r(); + u8 falcon_id_mask = 0; gk20a_dbg_fn(""); @@ -747,8 +748,13 @@ static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) } else { /* bind WPR VA inst block */ gr_gk20a_load_falcon_bind_instblk(g); - err = g->ops.pmu.load_lsfalcon_ucode(g, - (1 << LSF_FALCON_ID_GPCCS)); + if (g->ops.pmu.is_lazy_bootstrap(LSF_FALCON_ID_FECS)) + falcon_id_mask |= (1 << LSF_FALCON_ID_FECS); + if (g->ops.pmu.is_lazy_bootstrap(LSF_FALCON_ID_GPCCS)) + falcon_id_mask |= (1 << LSF_FALCON_ID_GPCCS); + + err = g->ops.pmu.load_lsfalcon_ucode(g, falcon_id_mask); + if (err) { gk20a_err(dev_from_gk20a(g), "Unable to boot GPCCS\n"); -- cgit v1.2.2