gpu: nvgpu: Boot FECS to secure mode

Boot FECS to secure mode if ACR is enabled.

Bug 200006956

Change-Id: Ifc107704a6456af837b7f6c513c04d152b2f4d3a
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/424251
This commit is contained in:
Terje Bergstrom
2014-06-23 09:56:45 +03:00
committed by Dan Willemsen
parent b57c6501c7
commit 20408d5b32
9 changed files with 201 additions and 43 deletions

View File

@@ -897,6 +897,12 @@ static int gk20a_pm_finalize_poweron(struct device *dev)
goto done; goto done;
} }
err = gk20a_enable_gr_hw(g);
if (err) {
gk20a_err(dev, "failed to enable gr");
goto done;
}
err = g->ops.pmu.prepare_ucode(g); err = g->ops.pmu.prepare_ucode(g);
if (err) { if (err) {
gk20a_err(dev, "failed to init pmu ucode"); gk20a_err(dev, "failed to init pmu ucode");

View File

@@ -128,6 +128,7 @@ struct gpu_ops {
u64 addr_base, u64 addr_base,
struct gk20a_ctxsw_ucode_segments *segments, struct gk20a_ctxsw_ucode_segments *segments,
u32 reg_offset); u32 reg_offset);
int (*load_ctxsw_ucode)(struct gk20a *g);
} gr; } gr;
const char *name; const char *name;
struct { struct {

View File

@@ -1867,7 +1867,7 @@ static int gr_gk20a_copy_ctxsw_ucode_segments(
return 0; return 0;
} }
static int gr_gk20a_init_ctxsw_ucode(struct gk20a *g) int gr_gk20a_init_ctxsw_ucode(struct gk20a *g)
{ {
struct device *d = dev_from_gk20a(g); struct device *d = dev_from_gk20a(g);
struct mm_gk20a *mm = &g->mm; struct mm_gk20a *mm = &g->mm;
@@ -1992,7 +1992,7 @@ static int gr_gk20a_init_ctxsw_ucode(struct gk20a *g)
return err; return err;
} }
static void gr_gk20a_load_falcon_bind_instblk(struct gk20a *g) void gr_gk20a_load_falcon_bind_instblk(struct gk20a *g)
{ {
struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info; struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info;
int retries = 20; int retries = 20;
@@ -2149,9 +2149,8 @@ static void gr_gk20a_load_falcon_with_bootloader(struct gk20a *g)
gr_fecs_falcon_hwcfg_r()); gr_fecs_falcon_hwcfg_r());
} }
static int gr_gk20a_load_ctxsw_ucode(struct gk20a *g, struct gr_gk20a *gr) int gr_gk20a_load_ctxsw_ucode(struct gk20a *g)
{ {
u32 ret;
gk20a_dbg_fn(""); gk20a_dbg_fn("");
@@ -2171,11 +2170,20 @@ static int gr_gk20a_load_ctxsw_ucode(struct gk20a *g, struct gr_gk20a *gr)
gr_gk20a_load_falcon_imem(g); gr_gk20a_load_falcon_imem(g);
gr_gk20a_start_falcon_ucode(g); gr_gk20a_start_falcon_ucode(g);
} else { } else {
if (!gr->skip_ucode_init) if (!g->gr.skip_ucode_init)
gr_gk20a_init_ctxsw_ucode(g); gr_gk20a_init_ctxsw_ucode(g);
gr_gk20a_load_falcon_with_bootloader(g); gr_gk20a_load_falcon_with_bootloader(g);
gr->skip_ucode_init = true; g->gr.skip_ucode_init = true;
} }
gk20a_dbg_fn("done");
return 0;
}
static int gr_gk20a_wait_ctxsw_ready(struct gk20a *g)
{
u32 ret;
gk20a_dbg_fn("");
ret = gr_gk20a_ctx_wait_ucode(g, 0, 0, ret = gr_gk20a_ctx_wait_ucode(g, 0, 0,
GR_IS_UCODE_OP_EQUAL, GR_IS_UCODE_OP_EQUAL,
@@ -4449,9 +4457,36 @@ static int gr_gk20a_wait_mem_scrubbing(struct gk20a *g)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static int gk20a_init_gr_reset_enable_hw(struct gk20a *g) int gr_gk20a_init_ctxsw(struct gk20a *g)
{ {
struct gr_gk20a *gr = &g->gr; struct gr_gk20a *gr = &g->gr;
u32 err = 0;
err = g->ops.gr.load_ctxsw_ucode(g);
if (err)
goto out;
err = gr_gk20a_wait_ctxsw_ready(g);
if (err)
goto out;
/* this appears query for sw states but fecs actually init
ramchain, etc so this is hw init */
err = gr_gk20a_init_ctx_state(g, gr);
if (err)
goto out;
out:
if (err)
gk20a_err(dev_from_gk20a(g), "fail");
else
gk20a_dbg_fn("done");
return 0;
}
int gk20a_init_gr_reset_enable_hw(struct gk20a *g)
{
struct av_list_gk20a *sw_non_ctx_load = &g->gr.ctx_vars.sw_non_ctx_load; struct av_list_gk20a *sw_non_ctx_load = &g->gr.ctx_vars.sw_non_ctx_load;
unsigned long end_jiffies = jiffies + unsigned long end_jiffies = jiffies +
msecs_to_jiffies(gk20a_get_gr_idle_timeout(g)); msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
@@ -4483,16 +4518,6 @@ static int gk20a_init_gr_reset_enable_hw(struct gk20a *g)
if (err) if (err)
goto out; goto out;
err = gr_gk20a_load_ctxsw_ucode(g, gr);
if (err)
goto out;
/* this appears query for sw states but fecs actually init
ramchain, etc so this is hw init */
err = gr_gk20a_init_ctx_state(g, gr);
if (err)
goto out;
out: out:
if (err) if (err)
gk20a_err(dev_from_gk20a(g), "fail"); gk20a_err(dev_from_gk20a(g), "fail");
@@ -4624,14 +4649,10 @@ int gk20a_init_gr_support(struct gk20a *g)
gk20a_dbg_fn(""); gk20a_dbg_fn("");
err = gk20a_init_gr_prepare(g);
if (err)
return err;
/* this is required before gr_gk20a_init_ctx_state */ /* this is required before gr_gk20a_init_ctx_state */
mutex_init(&g->gr.fecs_mutex); mutex_init(&g->gr.fecs_mutex);
err = gk20a_init_gr_reset_enable_hw(g); err = gr_gk20a_init_ctxsw(g);
if (err) if (err)
return err; return err;
@@ -4817,10 +4838,11 @@ static void gk20a_gr_set_alpha_circular_buffer_size(struct gk20a *g, u32 data)
} }
} }
int gk20a_gr_reset(struct gk20a *g) int gk20a_enable_gr_hw(struct gk20a *g)
{ {
int err; int err;
u32 size;
gk20a_dbg_fn("");
err = gk20a_init_gr_prepare(g); err = gk20a_init_gr_prepare(g);
if (err) if (err)
@@ -4830,10 +4852,28 @@ int gk20a_gr_reset(struct gk20a *g)
if (err) if (err)
return err; return err;
gk20a_dbg_fn("done");
return 0;
}
int gk20a_gr_reset(struct gk20a *g)
{
int err;
u32 size;
err = gk20a_enable_gr_hw(g);
if (err)
return err;
err = gk20a_init_gr_setup_hw(g); err = gk20a_init_gr_setup_hw(g);
if (err) if (err)
return err; return err;
err = gr_gk20a_init_ctxsw(g);
if (err)
return err;
size = 0; size = 0;
err = gr_gk20a_fecs_get_reglist_img_size(g, &size); err = gr_gk20a_fecs_get_reglist_img_size(g, &size);
if (err) { if (err) {
@@ -6934,4 +6974,5 @@ void gk20a_init_gr_ops(struct gpu_ops *gops)
gops->gr.set_hww_esr_report_mask = gr_gk20a_set_hww_esr_report_mask; gops->gr.set_hww_esr_report_mask = gr_gk20a_set_hww_esr_report_mask;
gops->gr.setup_alpha_beta_tables = gr_gk20a_setup_alpha_beta_tables; gops->gr.setup_alpha_beta_tables = gr_gk20a_setup_alpha_beta_tables;
gops->gr.falcon_load_ucode = gr_gk20a_load_ctxsw_ucode_segments; gops->gr.falcon_load_ucode = gr_gk20a_load_ctxsw_ucode_segments;
gops->gr.load_ctxsw_ucode = gr_gk20a_load_ctxsw_ucode;
} }

View File

@@ -319,6 +319,7 @@ struct gpu_ops;
void gk20a_init_gr(struct gk20a *g); void gk20a_init_gr(struct gk20a *g);
void gk20a_init_gr_ops(struct gpu_ops *gops); void gk20a_init_gr_ops(struct gpu_ops *gops);
int gk20a_init_gr_support(struct gk20a *g); int gk20a_init_gr_support(struct gk20a *g);
int gk20a_enable_gr_hw(struct gk20a *g);
int gk20a_gr_reset(struct gk20a *g); int gk20a_gr_reset(struct gk20a *g);
void gk20a_gr_wait_initialized(struct gk20a *g); void gk20a_gr_wait_initialized(struct gk20a *g);
@@ -415,6 +416,9 @@ void gr_gk20a_get_sm_dsm_perf_ctrl_regs(struct gk20a *g,
u32 **sm_dsm_perf_regs, u32 **sm_dsm_perf_regs,
u32 *perf_register_stride); u32 *perf_register_stride);
int gr_gk20a_setup_rop_mapping(struct gk20a *g, struct gr_gk20a *gr); int gr_gk20a_setup_rop_mapping(struct gk20a *g, struct gr_gk20a *gr);
int gr_gk20a_init_ctxsw_ucode(struct gk20a *g);
int gr_gk20a_load_ctxsw_ucode(struct gk20a *g);
void gr_gk20a_load_falcon_bind_instblk(struct gk20a *g);
void gr_gk20a_free_tsg_gr_ctx(struct tsg_gk20a *c); void gr_gk20a_free_tsg_gr_ctx(struct tsg_gk20a *c);
#endif /*__GR_GK20A_H__*/ #endif /*__GR_GK20A_H__*/

View File

@@ -487,6 +487,17 @@ static void *get_pmu_sequence_out_alloc_ptr_v0(struct pmu_sequence *seq)
int gk20a_init_pmu(struct pmu_gk20a *pmu) int gk20a_init_pmu(struct pmu_gk20a *pmu)
{ {
struct gk20a *g = gk20a_from_pmu(pmu); struct gk20a *g = gk20a_from_pmu(pmu);
mutex_init(&pmu->elpg_mutex);
mutex_init(&pmu->isr_mutex);
mutex_init(&pmu->pmu_copy_lock);
mutex_init(&pmu->pmu_seq_lock);
pmu->perfmon_counter.index = 3; /* GR & CE2 */
pmu->perfmon_counter.group_id = PMU_DOMAIN_GROUP_PSTATE;
pmu->remove_support = gk20a_remove_pmu_support;
switch (pmu->desc->app_version) { switch (pmu->desc->app_version) {
case APP_VERSION_GM20B_1: case APP_VERSION_GM20B_1:
case APP_VERSION_GM20B: case APP_VERSION_GM20B:
@@ -1700,25 +1711,9 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g)
pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE; pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE;
gk20a_free_sgtable(&sgt_seq_buf); gk20a_free_sgtable(&sgt_seq_buf);
pmu->sw_ready = true; pmu->sw_ready = true;
skip_init: skip_init:
mutex_init(&pmu->elpg_mutex);
mutex_init(&pmu->isr_mutex);
mutex_init(&pmu->pmu_copy_lock);
mutex_init(&pmu->pmu_seq_lock);
pmu->perfmon_counter.index = 3; /* GR & CE2 */
pmu->perfmon_counter.group_id = PMU_DOMAIN_GROUP_PSTATE;
pmu->remove_support = gk20a_remove_pmu_support;
err = gk20a_init_pmu(pmu);
if (err) {
gk20a_err(d, "failed to set function pointers\n");
return err;
}
gk20a_dbg_fn("done"); gk20a_dbg_fn("done");
return 0; return 0;
@@ -1773,7 +1768,6 @@ int gk20a_init_pmu_setup_hw1(struct gk20a *g)
int err; int err;
gk20a_dbg_fn(""); gk20a_dbg_fn("");
pmu_reset(pmu); pmu_reset(pmu);
/* setup apertures - virtual */ /* setup apertures - virtual */
@@ -3770,4 +3764,5 @@ err_out:
debugfs_remove_recursive(platform->debugfs); debugfs_remove_recursive(platform->debugfs);
return -ENOMEM; return -ENOMEM;
} }
#endif #endif

View File

@@ -1103,4 +1103,7 @@ void pmu_dump_falcon_stats(struct pmu_gk20a *pmu);
void gk20a_remove_pmu_support(struct pmu_gk20a *pmu); void gk20a_remove_pmu_support(struct pmu_gk20a *pmu);
void pmu_setup_hw(struct work_struct *work); void pmu_setup_hw(struct work_struct *work);
void pmu_seq_init(struct pmu_gk20a *pmu); void pmu_seq_init(struct pmu_gk20a *pmu);
int gk20a_init_pmu(struct pmu_gk20a *pmu);
#endif /*__PMU_GK20A_H__*/ #endif /*__PMU_GK20A_H__*/

View File

@@ -55,8 +55,9 @@ static int acr_ucode_patch_sig(struct gk20a *g,
/*Globals*/ /*Globals*/
static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE); static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
get_ucode_details pmu_acr_supp_ucode_list[MAX_SUPPORTED_LSFM] = { get_ucode_details pmu_acr_supp_ucode_list[] = {
pmu_ucode_details, pmu_ucode_details,
fecs_ucode_details,
}; };
/*Once is LS mode, cpuctl_alias is only accessible*/ /*Once is LS mode, cpuctl_alias is only accessible*/
@@ -116,6 +117,57 @@ int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
return 0; return 0;
} }
int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
{
int err = 0;
struct lsf_ucode_desc *lsf_desc;
lsf_desc = kzalloc(sizeof(struct lsf_ucode_desc), GFP_KERNEL);
if (!lsf_desc)
return -ENOMEM;
lsf_desc->falcon_id = LSF_FALCON_ID_FECS;
p_img->desc = kzalloc(sizeof(struct pmu_ucode_desc), GFP_KERNEL);
if (p_img->desc == NULL) {
kfree(lsf_desc);
return -ENOMEM;
}
p_img->desc->bootloader_start_offset =
g->ctxsw_ucode_info.fecs.boot.offset;
p_img->desc->bootloader_size =
g->ctxsw_ucode_info.fecs.boot.size;
p_img->desc->bootloader_imem_offset =
g->ctxsw_ucode_info.fecs.boot_imem_offset;
p_img->desc->bootloader_entry_point =
g->ctxsw_ucode_info.fecs.boot_entry;
p_img->desc->image_size = g->ctxsw_ucode_info.fecs.boot.size +
g->ctxsw_ucode_info.fecs.code.size +
g->ctxsw_ucode_info.fecs.data.size;
p_img->desc->app_size = 0;
p_img->desc->app_start_offset = 0;
p_img->desc->app_imem_offset = 0;
p_img->desc->app_imem_entry = 0;
p_img->desc->app_dmem_offset = 0;
p_img->desc->app_resident_code_offset =
g->ctxsw_ucode_info.fecs.code.offset;
p_img->desc->app_resident_code_size =
g->ctxsw_ucode_info.fecs.code.size;
p_img->desc->app_resident_data_offset =
g->ctxsw_ucode_info.fecs.data.offset;
p_img->desc->app_resident_data_size =
g->ctxsw_ucode_info.fecs.data.size;
p_img->data = g->ctxsw_ucode_info.surface_desc.cpuva;
p_img->data_size = p_img->desc->image_size;
p_img->fw_ver = NULL;
p_img->header = NULL;
p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc;
gm20b_dbg_pmu("fecs fw loaded 2\n");
return 0;
}
int prepare_ucode_blob(struct gk20a *g) int prepare_ucode_blob(struct gk20a *g)
{ {
struct device *d = dev_from_gk20a(g); struct device *d = dev_from_gk20a(g);
@@ -132,6 +184,7 @@ int prepare_ucode_blob(struct gk20a *g)
memset((void *)plsfm, 0, sizeof(struct ls_flcn_mgr)); memset((void *)plsfm, 0, sizeof(struct ls_flcn_mgr));
gm20b_dbg_pmu("fetching GMMU regs\n"); gm20b_dbg_pmu("fetching GMMU regs\n");
gm20b_mm_mmu_vpr_info_fetch(g); gm20b_mm_mmu_vpr_info_fetch(g);
gr_gk20a_init_ctxsw_ucode(g);
/* Discover all managed falcons*/ /* Discover all managed falcons*/
status = lsfm_discover_ucode_images(g, plsfm); status = lsfm_discover_ucode_images(g, plsfm);

View File

@@ -21,7 +21,7 @@
/*Defines*/ /*Defines*/
/*chip specific defines*/ /*chip specific defines*/
#define MAX_SUPPORTED_LSFM 1 /*PMU, FECS, GPCCS*/ #define MAX_SUPPORTED_LSFM 2 /*PMU, FECS, GPCCS*/
#define LSF_UCODE_DATA_ALIGNMENT 4096 #define LSF_UCODE_DATA_ALIGNMENT 4096
#define GM20B_PMU_UCODE_IMAGE "gpmu_ucode.bin" #define GM20B_PMU_UCODE_IMAGE "gpmu_ucode.bin"

View File

@@ -655,6 +655,56 @@ static int gr_gm20b_load_ctxsw_ucode_segments(struct gk20a *g, u64 addr_base,
return 0; return 0;
} }
#ifdef CONFIG_TEGRA_ACR
static void gr_gm20b_load_gpccs_with_bootloader(struct gk20a *g)
{
struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info;
u64 addr_base = ucode_info->ucode_gpuva;
gr_gk20a_load_falcon_bind_instblk(g);
g->ops.gr.falcon_load_ucode(g, addr_base,
&g->ctxsw_ucode_info.gpccs,
gr_gpcs_gpccs_falcon_hwcfg_r() -
gr_fecs_falcon_hwcfg_r());
}
static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g)
{
struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info;
u64 addr_base = ucode_info->ucode_gpuva;
int i;
gk20a_dbg_fn("");
if (tegra_platform_is_linsim()) {
gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(7),
gr_fecs_ctxsw_mailbox_value_f(0xc0de7777));
gk20a_writel(g, gr_gpccs_ctxsw_mailbox_r(7),
gr_gpccs_ctxsw_mailbox_value_f(0xc0de7777));
}
gr_gk20a_load_falcon_bind_instblk(g);
g->ops.gr.falcon_load_ucode(g, addr_base,
&g->ctxsw_ucode_info.gpccs,
gr_gpcs_gpccs_falcon_hwcfg_r() -
gr_fecs_falcon_hwcfg_r());
gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), 0x0);
gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(1), 0x1);
gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(6), 0xffffffff);
gk20a_writel(g, gr_gpccs_dmactl_r(), gr_gpccs_dmactl_require_ctx_f(0));
gk20a_writel(g, gr_gpccs_cpuctl_r(), gr_gpccs_cpuctl_startcpu_f(1));
gk20a_writel(g, gr_fecs_cpuctl_alias_r(), gr_fecs_cpuctl_startcpu_f(1));
gk20a_dbg_fn("done");
return 0;
}
#endif
void gm20b_init_gr(struct gpu_ops *gops) void gm20b_init_gr(struct gpu_ops *gops)
{ {
gops->gr.init_gpc_mmu = gr_gm20b_init_gpc_mmu; gops->gr.init_gpc_mmu = gr_gm20b_init_gpc_mmu;
@@ -676,4 +726,9 @@ void gm20b_init_gr(struct gpu_ops *gops)
gops->gr.init_fs_state = gr_gm20b_ctx_state_floorsweep; gops->gr.init_fs_state = gr_gm20b_ctx_state_floorsweep;
gops->gr.set_hww_esr_report_mask = gr_gm20b_set_hww_esr_report_mask; gops->gr.set_hww_esr_report_mask = gr_gm20b_set_hww_esr_report_mask;
gops->gr.falcon_load_ucode = gr_gm20b_load_ctxsw_ucode_segments; gops->gr.falcon_load_ucode = gr_gm20b_load_ctxsw_ucode_segments;
#ifdef CONFIG_TEGRA_ACR
gops->gr.load_ctxsw_ucode = gr_gm20b_load_ctxsw_ucode;
#else
gops->gr.load_ctxsw_ucode = gr_gk20a_load_ctxsw_ucode;
#endif
} }