gpu: nvgpu: pkc signature verification support

This change adds lsf_ucode_desc_wrapper to hold the pkc signature
header and corresponding lsf_lsb_header_v2. During blob preparation
based on the flag is_sig_pkc, the new header defines will be
packed into ls blob and passed to acr.
The flag NVGPU_PKC_LS_SIG_ENABLED is also added, which will be set
based on the acr core selection.

JIRA NVGPU-6365

Change-Id: I74e25d7c0f69d4007893e46006f97f2a607fd11f
Signed-off-by: smadhavan <smadhavan@nvidia.com>
Signed-off-by: deepak goyal <dgoyal@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2506136
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
smadhavan
2021-03-31 11:44:31 +05:30
committed by mobile promotions
parent f80dccb543
commit d9add2db52
7 changed files with 698 additions and 170 deletions

View File

@@ -104,7 +104,8 @@ exit:
#if defined(CONFIG_NVGPU_NON_FUSA)
s32 nvgpu_acr_lsf_pmu_ncore_ucode_details(struct gk20a *g, void *lsf_ucode_img)
{
struct lsf_ucode_desc *lsf_desc;
struct lsf_ucode_desc *lsf_desc = NULL;
struct lsf_ucode_desc_wrapper *lsf_desc_wrapper = NULL;
struct nvgpu_firmware *fw_sig;
struct nvgpu_firmware *fw_desc;
struct nvgpu_firmware *fw_image;
@@ -112,26 +113,45 @@ s32 nvgpu_acr_lsf_pmu_ncore_ucode_details(struct gk20a *g, void *lsf_ucode_img)
(struct flcn_ucode_img *)lsf_ucode_img;
s32 err = 0;
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc));
if (lsf_desc == NULL) {
err = -ENOMEM;
goto exit;
}
} else {
lsf_desc_wrapper =
nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc_wrapper));
if (lsf_desc_wrapper == NULL) {
err = -ENOMEM;
goto exit;
}
}
fw_sig = nvgpu_pmu_fw_sig_desc(g, g->pmu);
fw_desc = nvgpu_pmu_fw_desc_desc(g, g->pmu);
fw_image = nvgpu_pmu_fw_image_desc(g, g->pmu);
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
nvgpu_memcpy((u8 *)lsf_desc, (u8 *)fw_sig->data,
min_t(size_t, sizeof(*lsf_desc), fw_sig->size));
lsf_desc->falcon_id = FALCON_ID_PMU_NEXT_CORE;
} else {
nvgpu_memcpy((u8 *)lsf_desc_wrapper, (u8 *)fw_sig->data,
min_t(size_t, sizeof(*lsf_desc_wrapper), fw_sig->size));
lsf_desc_wrapper->lsf_ucode_desc_v2.falcon_id = FALCON_ID_PMU_NEXT_CORE;
}
p_img->ndesc = (struct falcon_next_core_ucode_desc *)(void *)fw_desc->data;
p_img->data = (u32 *)(void *)fw_image->data;
p_img->data_size = U32(fw_image->size);
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc;
} else {
p_img->lsf_desc_wrapper =
(struct lsf_ucode_desc_wrapper *)lsf_desc_wrapper;
}
p_img->is_next_core_img = true;
@@ -146,7 +166,10 @@ int nvgpu_acr_lsf_fecs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
u32 tmp_size;
u32 ver = nvgpu_safe_add_u32(g->params.gpu_arch,
g->params.gpu_impl);
struct lsf_ucode_desc *lsf_desc;
struct lsf_ucode_desc *lsf_desc = NULL;
#if defined(CONFIG_NVGPU_NON_FUSA)
struct lsf_ucode_desc_wrapper *lsf_desc_wrapper = NULL;
#endif
struct nvgpu_firmware *fecs_sig = NULL;
struct flcn_ucode_img *p_img =
(struct flcn_ucode_img *)lsf_ucode_img;
@@ -157,12 +180,22 @@ int nvgpu_acr_lsf_fecs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
switch (ver) {
case NVGPU_GPUID_GV11B:
#if defined(CONFIG_NVGPU_NON_FUSA)
case NVGPU_GPUID_GA10B:
#endif
fecs_sig = nvgpu_request_firmware(g, GM20B_FECS_UCODE_SIG,
NVGPU_REQUEST_FIRMWARE_NO_WARN);
break;
#if defined(CONFIG_NVGPU_NON_FUSA)
case NVGPU_GPUID_GA10B:
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
fecs_sig = nvgpu_request_firmware(g,
GM20B_FECS_UCODE_SIG,
NVGPU_REQUEST_FIRMWARE_NO_WARN);
} else {
fecs_sig = nvgpu_request_firmware(g,
GA10B_FECS_UCODE_PKC_SIG,
NVGPU_REQUEST_FIRMWARE_NO_WARN);
}
break;
#endif
#ifdef CONFIG_NVGPU_DGPU
case NVGPU_GPUID_TU104:
fecs_sig = nvgpu_request_firmware(g, TU104_FECS_UCODE_SIG,
@@ -185,6 +218,7 @@ int nvgpu_acr_lsf_fecs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
nvgpu_err(g, "failed to load fecs sig");
return -ENOENT;
}
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc));
if (lsf_desc == NULL) {
err = -ENOMEM;
@@ -194,6 +228,20 @@ int nvgpu_acr_lsf_fecs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
min_t(size_t, sizeof(*lsf_desc), fecs_sig->size));
lsf_desc->falcon_id = FALCON_ID_FECS;
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
lsf_desc_wrapper =
nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc_wrapper));
if (lsf_desc_wrapper == NULL) {
err = -ENOMEM;
goto rel_sig;
}
nvgpu_memcpy((u8 *)lsf_desc_wrapper, (u8 *)fecs_sig->data,
min_t(size_t, sizeof(*lsf_desc_wrapper), fecs_sig->size));
lsf_desc_wrapper->lsf_ucode_desc_v2.falcon_id = FALCON_ID_FECS;
#endif
}
p_img->desc = nvgpu_kzalloc(g, sizeof(struct ls_falcon_ucode_desc));
if (p_img->desc == NULL) {
@@ -230,7 +278,14 @@ int nvgpu_acr_lsf_fecs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
p_img->data = nvgpu_gr_falcon_get_surface_desc_cpu_va(gr_falcon);
p_img->data_size = p_img->desc->image_size;
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc;
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
p_img->lsf_desc_wrapper =
(struct lsf_ucode_desc_wrapper *)lsf_desc_wrapper;
#endif
}
nvgpu_acr_dbg(g, "fecs fw loaded\n");
@@ -238,7 +293,13 @@ int nvgpu_acr_lsf_fecs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
return 0;
free_lsf_desc:
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
nvgpu_kfree(g, lsf_desc);
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
nvgpu_kfree(g, lsf_desc_wrapper);
#endif
}
rel_sig:
nvgpu_release_firmware(g, fecs_sig);
return err;
@@ -248,7 +309,10 @@ int nvgpu_acr_lsf_gpccs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
{
u32 tmp_size;
u32 ver = nvgpu_safe_add_u32(g->params.gpu_arch, g->params.gpu_impl);
struct lsf_ucode_desc *lsf_desc;
struct lsf_ucode_desc *lsf_desc = NULL;
#if defined(CONFIG_NVGPU_NON_FUSA)
struct lsf_ucode_desc_wrapper *lsf_desc_wrapper = NULL;
#endif
struct nvgpu_firmware *gpccs_sig = NULL;
struct flcn_ucode_img *p_img =
(struct flcn_ucode_img *)lsf_ucode_img;
@@ -267,12 +331,22 @@ int nvgpu_acr_lsf_gpccs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
switch (ver) {
case NVGPU_GPUID_GV11B:
#if defined(CONFIG_NVGPU_NON_FUSA)
case NVGPU_GPUID_GA10B:
#endif
gpccs_sig = nvgpu_request_firmware(g, T18x_GPCCS_UCODE_SIG,
NVGPU_REQUEST_FIRMWARE_NO_WARN);
break;
#if defined(CONFIG_NVGPU_NON_FUSA)
case NVGPU_GPUID_GA10B:
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
gpccs_sig = nvgpu_request_firmware(g,
T18x_GPCCS_UCODE_SIG,
NVGPU_REQUEST_FIRMWARE_NO_WARN);
} else {
gpccs_sig = nvgpu_request_firmware(g,
GA10B_GPCCS_UCODE_PKC_SIG,
NVGPU_REQUEST_FIRMWARE_NO_WARN);
}
break;
#endif
#ifdef CONFIG_NVGPU_DGPU
case NVGPU_GPUID_TU104:
gpccs_sig = nvgpu_request_firmware(g, TU104_GPCCS_UCODE_SIG,
@@ -291,10 +365,12 @@ int nvgpu_acr_lsf_gpccs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
break;
}
nvgpu_acr_dbg(g, "gpccs fw fetched from FS\n");
if (gpccs_sig == NULL) {
nvgpu_err(g, "failed to load gpccs sig");
return -ENOENT;
}
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
lsf_desc = nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc));
if (lsf_desc == NULL) {
err = -ENOMEM;
@@ -303,7 +379,21 @@ int nvgpu_acr_lsf_gpccs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
nvgpu_memcpy((u8 *)lsf_desc, gpccs_sig->data,
min_t(size_t, sizeof(*lsf_desc), gpccs_sig->size));
lsf_desc->falcon_id = FALCON_ID_GPCCS;
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
lsf_desc_wrapper =
nvgpu_kzalloc(g, sizeof(struct lsf_ucode_desc_wrapper));
if (lsf_desc_wrapper == NULL) {
err = -ENOMEM;
goto rel_sig;
}
nvgpu_memcpy((u8 *)lsf_desc_wrapper, gpccs_sig->data,
min_t(size_t, sizeof(*lsf_desc_wrapper), gpccs_sig->size));
lsf_desc_wrapper->lsf_ucode_desc_v2.falcon_id = FALCON_ID_GPCCS;
#endif
}
nvgpu_acr_dbg(g, "gpccs fw copied to desc buffer\n");
p_img->desc = nvgpu_kzalloc(g, sizeof(struct ls_falcon_ucode_desc));
if (p_img->desc == NULL) {
err = -ENOMEM;
@@ -348,7 +438,15 @@ int nvgpu_acr_lsf_gpccs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
+ gpccs->boot.offset);
p_img->data_size = NVGPU_ALIGN(p_img->desc->image_size,
LSF_DATA_SIZE_ALIGNMENT);
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc;
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
p_img->lsf_desc_wrapper =
(struct lsf_ucode_desc_wrapper *)lsf_desc_wrapper;
#endif
}
nvgpu_acr_dbg(g, "gpccs fw loaded\n");
@@ -356,7 +454,13 @@ int nvgpu_acr_lsf_gpccs_ucode_details(struct gk20a *g, void *lsf_ucode_img)
return 0;
free_lsf_desc:
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
nvgpu_kfree(g, lsf_desc);
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
nvgpu_kfree(g, lsf_desc_wrapper);
#endif
}
rel_sig:
nvgpu_release_firmware(g, gpccs_sig);
return err;
@@ -455,8 +559,7 @@ release_img_fw:
}
#endif
/* Populate static LSB header information using the provided ucode image */
static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g,
static void lsfm_fill_static_lsb_hdr_info_aes(struct gk20a *g,
u32 falcon_id, struct lsfm_managed_ucode_img *pnode)
{
u32 full_app_size = 0;
@@ -468,7 +571,6 @@ static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g,
sizeof(struct lsf_ucode_desc));
}
if (!pnode->ucode_img.is_next_core_img) {
pnode->lsb_header.ucode_size = pnode->ucode_img.data_size;
/* Uses a loader. that is has a desc */
@@ -514,13 +616,95 @@ static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g,
NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE;
}
} else {
}
#if defined(CONFIG_NVGPU_NON_FUSA)
static void lsfm_fill_static_lsb_hdr_info_pkc(struct gk20a *g,
u32 falcon_id, struct lsfm_managed_ucode_img *pnode)
{
u32 full_app_size = 0;
if (pnode->ucode_img.lsf_desc_wrapper != NULL) {
nvgpu_memcpy((u8 *)&pnode->lsb_header_v2.signature,
(u8 *)pnode->ucode_img.lsf_desc_wrapper,
sizeof(struct lsf_ucode_desc_wrapper));
}
pnode->lsb_header_v2.ucode_size = pnode->ucode_img.data_size;
pnode->lsb_header_v2.data_size = LSB_HDR_DATA_SIZE;
pnode->lsb_header_v2.bl_code_size = NVGPU_ALIGN(
pnode->ucode_img.desc->bootloader_size,
LSF_BL_CODE_SIZE_ALIGNMENT);
full_app_size = nvgpu_safe_add_u32(
NVGPU_ALIGN(pnode->ucode_img.desc->app_size,
LSF_BL_CODE_SIZE_ALIGNMENT),
pnode->lsb_header_v2.bl_code_size);
pnode->lsb_header_v2.ucode_size = nvgpu_safe_add_u32(NVGPU_ALIGN(
pnode->ucode_img.desc->app_resident_data_offset,
LSF_BL_CODE_SIZE_ALIGNMENT),
pnode->lsb_header_v2.bl_code_size);
pnode->lsb_header_v2.data_size = nvgpu_safe_sub_u32(full_app_size,
pnode->lsb_header_v2.ucode_size);
pnode->lsb_header_v2.bl_imem_off =
pnode->ucode_img.desc->bootloader_imem_offset;
pnode->lsb_header_v2.flags = NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_FALSE;
if (g->acr->lsf[falcon_id].is_priv_load) {
pnode->lsb_header_v2.flags |=
NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD_TRUE;
}
}
#endif
/* Populate static LSB header information using the provided ucode image */
static void lsfm_fill_static_lsb_hdr_info(struct gk20a *g,
u32 falcon_id, struct lsfm_managed_ucode_img *pnode)
{
#if defined(CONFIG_NVGPU_NON_FUSA)
u32 base_size = 0;
u32 image_padding_size = 0;
struct falcon_next_core_ucode_desc *ndesc = pnode->ucode_img.ndesc;
#endif
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)
&& (!pnode->ucode_img.is_next_core_img)) {
lsfm_fill_static_lsb_hdr_info_aes(g, falcon_id, pnode);
#if defined(CONFIG_NVGPU_NON_FUSA)
} else if (nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)
&& (!pnode->ucode_img.is_next_core_img)) {
lsfm_fill_static_lsb_hdr_info_pkc(g, falcon_id, pnode);
} else if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)
&& (pnode->ucode_img.is_next_core_img)) {
pnode->lsb_header.ucode_size = 0;
pnode->lsb_header.data_size = 0;
pnode->lsb_header.bl_code_size = 0;
pnode->lsb_header.bl_imem_off = 0;
pnode->lsb_header.bl_data_size = 0;
pnode->lsb_header.bl_data_off = 0;
} else {
if (pnode->ucode_img.lsf_desc_wrapper != NULL) {
nvgpu_memcpy((u8 *)&pnode->lsb_header_v2.signature,
(u8 *)pnode->ucode_img.lsf_desc_wrapper,
sizeof(struct lsf_ucode_desc_wrapper));
}
pnode->lsb_header_v2.ucode_size = ndesc->bootloader_offset +
ndesc->bootloader_size +
ndesc->bootloader_param_size;
base_size = pnode->lsb_header_v2.ucode_size +
ndesc->next_core_elf_size;
image_padding_size = PAGE_ALIGN(base_size) - base_size;
pnode->lsb_header_v2.data_size = ndesc->next_core_elf_size +
image_padding_size;
pnode->lsb_header_v2.bl_code_size = 0;
pnode->lsb_header_v2.bl_imem_off = 0;
pnode->lsb_header_v2.bl_data_size = 0;
pnode->lsb_header_v2.bl_data_off = 0;
#endif
}
}
@@ -550,7 +734,15 @@ static int lsfm_add_ucode_img(struct gk20a *g, struct ls_flcn_mgr *plsfm,
/* Fill in static LSB header info elsewhere */
lsfm_fill_static_lsb_hdr_info(g, falcon_id, pnode);
pnode->wpr_header.bin_version = pnode->lsb_header.signature.version;
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
pnode->wpr_header.bin_version =
pnode->lsb_header.signature.version;
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
pnode->wpr_header.bin_version =
pnode->lsb_header_v2.signature.lsf_ucode_desc_v2.ls_ucode_version;
#endif
}
pnode->next = plsfm->ucode_img_list;
plsfm->ucode_img_list = pnode;
@@ -562,7 +754,7 @@ static int lsfm_check_and_add_ucode_image(struct gk20a *g,
{
struct flcn_ucode_img ucode_img;
struct nvgpu_acr *acr = g->acr;
u32 falcon_id;
u32 falcon_id = 0U;
int err = 0;
if (!nvgpu_test_bit(lsf_index, (void *)&acr->lsf_enable_mask)) {
@@ -584,7 +776,14 @@ static int lsfm_check_and_add_ucode_image(struct gk20a *g,
return err;
}
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
falcon_id = ucode_img.lsf_desc->falcon_id;
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
falcon_id = ucode_img.lsf_desc_wrapper->lsf_ucode_desc_v2.falcon_id;
#endif
}
err = lsfm_add_ucode_img(g, plsfm, &ucode_img, falcon_id);
if (err != 0) {
nvgpu_err(g, " Failed to add falcon-%d to LSFM ", falcon_id);
@@ -672,6 +871,116 @@ static int lsfm_discover_and_add_sub_wprs(struct gk20a *g,
}
#endif
static void lsf_calc_wpr_size_aes(struct lsfm_managed_ucode_img *pnode,
u32 *wpr_off)
{
u32 wpr_offset = *wpr_off;
/* Align, save off and include an LSB header size */
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_LSB_HEADER_ALIGNMENT);
pnode->wpr_header.lsb_offset = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
(u32)sizeof(struct lsf_lsb_header));
/*
* Align, save off and include the original (static)ucode
* image size
*/
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_UCODE_DATA_ALIGNMENT);
pnode->lsb_header.ucode_off = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
pnode->ucode_img.data_size);
/*
* For falcons that use a boot loader (BL), we append a loader
* desc structure on the end of the ucode image and consider this
* the boot loader data. The host will then copy the loader desc
* args to this space within the WPR region (before locking down)
* and the HS bin will then copy them to DMEM 0 for the loader.
*/
/*
* Track the size for LSB details filled in later
* Note that at this point we don't know what kind of
* boot loader desc, so we just take the size of the
* generic one, which is the largest it will ever be.
*/
/* Align (size bloat) and save off generic descriptor size*/
pnode->lsb_header.bl_data_size = NVGPU_ALIGN(
nvgpu_safe_cast_u64_to_u32(
sizeof(pnode->bl_gen_desc)),
LSF_BL_DATA_SIZE_ALIGNMENT);
/*Align, save off, and include the additional BL data*/
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_BL_DATA_ALIGNMENT);
pnode->lsb_header.bl_data_off = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
pnode->lsb_header.bl_data_size);
/* Finally, update ucode surface size to include updates */
pnode->full_ucode_size = wpr_offset -
pnode->lsb_header.ucode_off;
if (pnode->wpr_header.falcon_id != FALCON_ID_PMU &&
pnode->wpr_header.falcon_id != FALCON_ID_PMU_NEXT_CORE) {
pnode->lsb_header.app_code_off =
pnode->lsb_header.bl_code_size;
pnode->lsb_header.app_code_size =
pnode->lsb_header.ucode_size -
pnode->lsb_header.bl_code_size;
pnode->lsb_header.app_data_off =
pnode->lsb_header.ucode_size;
pnode->lsb_header.app_data_size =
pnode->lsb_header.data_size;
}
*wpr_off = wpr_offset;
}
#if defined(CONFIG_NVGPU_NON_FUSA)
static void lsf_calc_wpr_size_pkc(struct lsfm_managed_ucode_img *pnode,
u32 *wpr_off)
{
u32 wpr_offset = *wpr_off;
/* Align, save off, and include an LSB header size */
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_LSB_HEADER_ALIGNMENT);
pnode->wpr_header.lsb_offset = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
(u32)sizeof(struct lsf_lsb_header_v2));
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_UCODE_DATA_ALIGNMENT);
pnode->lsb_header_v2.ucode_off = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
pnode->ucode_img.data_size);
pnode->lsb_header_v2.bl_data_size = NVGPU_ALIGN(
nvgpu_safe_cast_u64_to_u32(
sizeof(pnode->bl_gen_desc)),
LSF_BL_DATA_SIZE_ALIGNMENT);
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_BL_DATA_ALIGNMENT);
pnode->lsb_header_v2.bl_data_off = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
pnode->lsb_header_v2.bl_data_size);
pnode->full_ucode_size = wpr_offset -
pnode->lsb_header_v2.ucode_off;
if (pnode->wpr_header.falcon_id != FALCON_ID_PMU &&
pnode->wpr_header.falcon_id != FALCON_ID_PMU_NEXT_CORE) {
pnode->lsb_header_v2.app_code_off =
pnode->lsb_header_v2.bl_code_size;
pnode->lsb_header_v2.app_code_size =
pnode->lsb_header_v2.ucode_size -
pnode->lsb_header_v2.bl_code_size;
pnode->lsb_header_v2.app_data_off =
pnode->lsb_header_v2.ucode_size;
pnode->lsb_header_v2.app_data_size =
pnode->lsb_header_v2.data_size;
}
*wpr_off = wpr_offset;
}
#endif
/* Generate WPR requirements for ACR allocation request */
static int lsf_gen_wpr_requirements(struct gk20a *g,
struct ls_flcn_mgr *plsfm)
@@ -715,60 +1024,12 @@ static int lsf_gen_wpr_requirements(struct gk20a *g,
* as well as the ucode images.
*/
while (pnode != NULL) {
/* Align, save off, and include an LSB header size */
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_LSB_HEADER_ALIGNMENT);
pnode->wpr_header.lsb_offset = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
(u32)sizeof(struct lsf_lsb_header));
/*
* Align, save off, and include the original (static)ucode
* image size
*/
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_UCODE_DATA_ALIGNMENT);
pnode->lsb_header.ucode_off = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
pnode->ucode_img.data_size);
/*
* For falcons that use a boot loader (BL), we append a loader
* desc structure on the end of the ucode image and consider this
* the boot loader data. The host will then copy the loader desc
* args to this space within the WPR region (before locking down)
* and the HS bin will then copy them to DMEM 0 for the loader.
*/
/*
* Track the size for LSB details filled in later
* Note that at this point we don't know what kind of
* boot loader desc, so we just take the size of the
* generic one, which is the largest it will will ever be.
*/
/* Align (size bloat) and save off generic descriptor size*/
pnode->lsb_header.bl_data_size = NVGPU_ALIGN(
nvgpu_safe_cast_u64_to_u32(
sizeof(pnode->bl_gen_desc)),
LSF_BL_DATA_SIZE_ALIGNMENT);
/*Align, save off, and include the additional BL data*/
wpr_offset = NVGPU_ALIGN(wpr_offset, LSF_BL_DATA_ALIGNMENT);
pnode->lsb_header.bl_data_off = wpr_offset;
wpr_offset = nvgpu_safe_add_u32(wpr_offset,
pnode->lsb_header.bl_data_size);
/* Finally, update ucode surface size to include updates */
pnode->full_ucode_size = wpr_offset -
pnode->lsb_header.ucode_off;
if (pnode->wpr_header.falcon_id != FALCON_ID_PMU &&
pnode->wpr_header.falcon_id != FALCON_ID_PMU_NEXT_CORE) {
pnode->lsb_header.app_code_off =
pnode->lsb_header.bl_code_size;
pnode->lsb_header.app_code_size =
pnode->lsb_header.ucode_size -
pnode->lsb_header.bl_code_size;
pnode->lsb_header.app_data_off =
pnode->lsb_header.ucode_size;
pnode->lsb_header.app_data_size =
pnode->lsb_header.data_size;
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
lsf_calc_wpr_size_aes(pnode, &wpr_offset);
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
lsf_calc_wpr_size_pkc(pnode, &wpr_offset);
#endif
}
#if defined(CONFIG_NVGPU_NON_FUSA)
/* Falcon image is cleanly partitioned between a code and
@@ -817,7 +1078,7 @@ static int lsfm_populate_flcn_bl_dmem_desc(struct gk20a *g,
struct flcn_ucode_img *p_img = &(p_lsfm->ucode_img);
struct flcn_bl_dmem_desc *ldr_cfg =
&(p_lsfm->bl_gen_desc);
u64 addr_base;
u64 addr_base = 0;
struct ls_falcon_ucode_desc *desc;
u64 addr_code, addr_data;
@@ -838,7 +1099,13 @@ static int lsfm_populate_flcn_bl_dmem_desc(struct gk20a *g,
* The 32-bit addresses will be the upper 32-bits of the virtual or
* physical addresses of each respective segment.
*/
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
addr_base = p_lsfm->lsb_header.ucode_off;
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
addr_base = p_lsfm->lsb_header_v2.ucode_off;
#endif
}
g->acr->get_wpr_info(g, &wpr_inf);
addr_base = nvgpu_safe_add_u64(addr_base, wpr_inf.wpr_base);
@@ -970,12 +1237,22 @@ static int lsfm_init_wpr_contents(struct gk20a *g,
pnode->wpr_header.status);
/*Flush LSB header to memory*/
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
nvgpu_mem_wr_n(g, ucode, pnode->wpr_header.lsb_offset,
&pnode->lsb_header,
nvgpu_safe_cast_u64_to_u32(
sizeof(pnode->lsb_header)));
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
nvgpu_mem_wr_n(g, ucode, pnode->wpr_header.lsb_offset,
&pnode->lsb_header_v2,
nvgpu_safe_cast_u64_to_u32(
sizeof(pnode->lsb_header_v2)));
#endif
}
nvgpu_acr_dbg(g, "lsb header");
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
nvgpu_acr_dbg(g, "ucode_off :%x",
pnode->lsb_header.ucode_off);
nvgpu_acr_dbg(g, "ucode_size :%x",
@@ -1000,6 +1277,34 @@ static int lsfm_init_wpr_contents(struct gk20a *g,
pnode->lsb_header.app_data_size);
nvgpu_acr_dbg(g, "flags :%x",
pnode->lsb_header.flags);
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
nvgpu_acr_dbg(g, "ucode_off :%x",
pnode->lsb_header_v2.ucode_off);
nvgpu_acr_dbg(g, "ucode_size :%x",
pnode->lsb_header_v2.ucode_size);
nvgpu_acr_dbg(g, "data_size :%x",
pnode->lsb_header_v2.data_size);
nvgpu_acr_dbg(g, "bl_code_size :%x",
pnode->lsb_header_v2.bl_code_size);
nvgpu_acr_dbg(g, "bl_imem_off :%x",
pnode->lsb_header_v2.bl_imem_off);
nvgpu_acr_dbg(g, "bl_data_off :%x",
pnode->lsb_header_v2.bl_data_off);
nvgpu_acr_dbg(g, "bl_data_size :%x",
pnode->lsb_header_v2.bl_data_size);
nvgpu_acr_dbg(g, "app_code_off :%x",
pnode->lsb_header_v2.app_code_off);
nvgpu_acr_dbg(g, "app_code_size :%x",
pnode->lsb_header_v2.app_code_size);
nvgpu_acr_dbg(g, "app_data_off :%x",
pnode->lsb_header_v2.app_data_off);
nvgpu_acr_dbg(g, "app_data_size :%x",
pnode->lsb_header_v2.app_data_size);
nvgpu_acr_dbg(g, "flags :%x",
pnode->lsb_header_v2.flags);
#endif
}
if (!pnode->ucode_img.is_next_core_img) {
/*
@@ -1012,13 +1317,33 @@ static int lsfm_init_wpr_contents(struct gk20a *g,
nvgpu_err(g, "bl_gen_desc failed err=%d", err);
return err;
}
nvgpu_mem_wr_n(g, ucode, pnode->lsb_header.bl_data_off,
&pnode->bl_gen_desc, pnode->bl_gen_desc_size);
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
nvgpu_mem_wr_n(g, ucode,
pnode->lsb_header.bl_data_off,
&pnode->bl_gen_desc,
pnode->bl_gen_desc_size);
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
nvgpu_mem_wr_n(g, ucode,
pnode->lsb_header_v2.bl_data_off,
&pnode->bl_gen_desc,
pnode->bl_gen_desc_size);
#endif
}
}
/* Copying of ucode */
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
nvgpu_mem_wr_n(g, ucode, pnode->lsb_header.ucode_off,
pnode->ucode_img.data, pnode->ucode_img.data_size);
pnode->ucode_img.data,
pnode->ucode_img.data_size);
#if defined(CONFIG_NVGPU_NON_FUSA)
} else {
nvgpu_mem_wr_n(g, ucode, pnode->lsb_header_v2.ucode_off,
pnode->ucode_img.data,
pnode->ucode_img.data_size);
#endif
}
pnode = pnode->next;
i = nvgpu_safe_add_u32(i, 1U);
@@ -1043,6 +1368,12 @@ static void lsfm_free_ucode_img_res(struct gk20a *g,
nvgpu_kfree(g, p_img->lsf_desc);
p_img->lsf_desc = NULL;
}
#if defined(CONFIG_NVGPU_NON_FUSA)
if (p_img->lsf_desc_wrapper != NULL) {
nvgpu_kfree(g, p_img->lsf_desc_wrapper);
p_img->lsf_desc_wrapper = NULL;
}
#endif
}
static void lsfm_free_nonpmu_ucode_img_res(struct gk20a *g,
@@ -1052,6 +1383,12 @@ static void lsfm_free_nonpmu_ucode_img_res(struct gk20a *g,
nvgpu_kfree(g, p_img->lsf_desc);
p_img->lsf_desc = NULL;
}
#if defined(CONFIG_NVGPU_NON_FUSA)
if (p_img->lsf_desc_wrapper != NULL) {
nvgpu_kfree(g, p_img->lsf_desc_wrapper);
p_img->lsf_desc_wrapper = NULL;
}
#endif
if (p_img->desc != NULL) {
nvgpu_kfree(g, p_img->desc);
p_img->desc = NULL;
@@ -1065,8 +1402,8 @@ static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm)
while (cnt != 0U) {
mg_ucode_img = plsfm->ucode_img_list;
if (mg_ucode_img->ucode_img.lsf_desc->falcon_id ==
FALCON_ID_PMU) {
if (mg_ucode_img->ucode_img.lsf_desc != NULL &&
mg_ucode_img->ucode_img.lsf_desc->falcon_id == FALCON_ID_PMU) {
lsfm_free_ucode_img_res(g, &mg_ucode_img->ucode_img);
} else {
lsfm_free_nonpmu_ucode_img_res(g,

View File

@@ -88,6 +88,7 @@ struct flcn_ucode_img {
struct lsf_ucode_desc *lsf_desc;
bool is_next_core_img;
#if defined(CONFIG_NVGPU_NON_FUSA)
struct lsf_ucode_desc_wrapper *lsf_desc_wrapper;
struct falcon_next_core_ucode_desc *ndesc;
#endif
};
@@ -96,6 +97,9 @@ struct lsfm_managed_ucode_img {
struct lsfm_managed_ucode_img *next;
struct lsf_wpr_header wpr_header;
struct lsf_lsb_header lsb_header;
#if defined(CONFIG_NVGPU_NON_FUSA)
struct lsf_lsb_header_v2 lsb_header_v2;
#endif
struct flcn_bl_dmem_desc bl_gen_desc;
u32 bl_gen_desc_size;
u32 full_ucode_size;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -89,6 +89,9 @@ struct wpr_carveout_info;
#define GM20B_FECS_UCODE_SIG "fecs_sig.bin"
#define T18x_GPCCS_UCODE_SIG "gpccs_sig.bin"
#define GA10B_FECS_UCODE_PKC_SIG "fecs_pkc_sig.bin"
#define GA10B_GPCCS_UCODE_PKC_SIG "gpccs_pkc_sig.bin"
#define TU104_FECS_UCODE_SIG "tu104/fecs_sig.bin"
#define TU104_GPCCS_UCODE_SIG "tu104/gpccs_sig.bin"

View File

@@ -321,6 +321,7 @@ void nvgpu_ga10b_acr_sw_init(struct gk20a *g, struct nvgpu_acr *acr)
#ifdef CONFIG_NVGPU_NON_FUSA
if (nvgpu_falcon_is_falcon2_enabled(&g->gsp_flcn)) {
nvgpu_set_enabled(g, NVGPU_ACR_NEXT_CORE_ENABLED, true);
nvgpu_set_enabled(g, NVGPU_PKC_LS_SIG_ENABLED, false);
}
#else
if (nvgpu_falcon_is_falcon2_enabled(&g->pmu_flcn)) {
@@ -329,6 +330,7 @@ void nvgpu_ga10b_acr_sw_init(struct gk20a *g, struct nvgpu_acr *acr)
* in ACR unit
*/
nvgpu_set_enabled(g, NVGPU_ACR_NEXT_CORE_ENABLED, true);
nvgpu_set_enabled(g, NVGPU_PKC_LS_SIG_ENABLED, false);
}
#endif

View File

@@ -249,6 +249,92 @@ struct lsf_ucode_desc {
u8 kdf[16];
};
/* PKC */
/*
* Currently 2 components in ucode image have signature.
* One is code section and another is data section.
*/
#define LSF_UCODE_COMPONENT_INDEX_CODE (0)
#define LSF_UCODE_COMPONENT_INDEX_DATA (1)
#define LSF_UCODE_COMPONENT_INDEX_MAX (2)
/*
* For PKC operation, SE engine needs each input component size to be 512 bytes
* length. So even though PKC signature is 384 bytes, it needs to be padded with
* zeros until size is 512.
* Currently, for version 2, MAX LS signature size is set to be 512 as well.
*/
#define PKC_SIGNATURE_SIZE_BYTE (384)
#define PKC_SIGNATURE_PADDING_SIZE_BYTE (128)
#define PKC_SIGNATURE_PADDED_SIZE_BYTE \
(PKC_SIGNATURE_SIZE_BYTE + PKC_SIGNATURE_PADDING_SIZE_BYTE)
/* Size in bytes for RSA 3K (RSA_3K struct from bootrom_pkc_parameters.h */
#define PKC_PK_SIZE_BYTE (2048)
#define LSF_SIGNATURE_SIZE_PKC_BYTE \
(PKC_SIGNATURE_SIZE_BYTE + PKC_SIGNATURE_PADDING_SIZE_BYTE)
#define LSF_SIGNATURE_SIZE_MAX_BYTE LSF_SIGNATURE_SIZE_PKC_BYTE
#define LSF_PK_SIZE_MAX PKC_PK_SIZE_BYTE
/* LS Encryption Defines */
#define LS_ENCRYPTION_AES_CBC_IV_SIZE_BYTE (16)
/*!
* WPR generic struct header
* identifier - To identify type of WPR struct i.e. WPR vs SUBWPR vs LSB vs LSF_UCODE_DESC
* version - To specify version of struct, for backward compatibility
* size - Size of struct, include header and body
*/
struct wpr_generic_header {
u16 identifier;
u16 version;
u32 size;
};
/*
* Light Secure Falcon Ucode Version 2 Description Defines
* This stucture is prelim and may change as the ucode signing flow evolves.
*/
struct lsf_ucode_desc_v2 {
u32 falcon_id; // lsenginedid
u8 b_prd_present;
u8 b_dbg_present;
u16 reserved;
u32 sig_size;
u8 prod_sig[LSF_UCODE_COMPONENT_INDEX_MAX][LSF_SIGNATURE_SIZE_PKC_BYTE];
u8 debug_sig[LSF_UCODE_COMPONENT_INDEX_MAX][LSF_SIGNATURE_SIZE_PKC_BYTE];
u16 sig_algo_ver;
u16 sig_algo;
u16 hash_algo_ver;
u16 hash_algo;
u32 sig_algo_padding_type;
u8 dep_map[LSF_FALCON_DEPMAP_SIZE * 8];
u32 dep_map_count;
u8 b_supports_versioning;
u8 pad[3];
u32 ls_ucode_version; // lsucodeversion
u32 ls_ucode_id; // lsucodeid
u32 b_ucode_ls_encrypted;
u32 ls_encalgo_type;
u32 ls_enc_algo_ver;
u8 ls_enc_iv[LS_ENCRYPTION_AES_CBC_IV_SIZE_BYTE];
u8 rsvd[36]; // reserved for any future usage
};
/*
* The wrapper for LSF_UCODE_DESC, start support from version 2.
*/
struct lsf_ucode_desc_wrapper {
struct wpr_generic_header generic_hdr;
union {
struct lsf_ucode_desc_v2 lsf_ucode_desc_v2;
};
};
/* PKC end*/
/** @} */
/**
@@ -355,7 +441,94 @@ struct lsf_lsb_header {
u32 flags;
};
struct lsf_lsb_header_v2 {
/** Code/data signature details of each LS falcon */
struct lsf_ucode_desc_wrapper signature;
/**
* Offset from non-WPR base where UCODE is located,
* Offset = Non-WPR base + #LSF_LSB_HEADER_ALIGNMENT +
* #LSF_UCODE_DATA_ALIGNMENT + ( #LSF_BL_DATA_ALIGNMENT *
* LS Falcon index)
*/
u32 ucode_off;
/**
* Size of LS Falcon ucode, required to perform signature verification
* of LS Falcon ucode by ACR HS.
*/
u32 ucode_size;
/**
* Size of LS Falcon ucode data, required to perform signature
* verification of LS Falcon ucode data by ACR HS.
*/
u32 data_size;
/**
* Size of bootloader that needs to be loaded by bootstrap owner.
*
* On GV11B, respective LS Falcon BL code size should not exceed
* below mentioned size.
* FALCON_ID_FECS IMEM size - 32k
* FALCON_ID_GPCCS IMEM size - 16k
*/
u32 bl_code_size;
/** BL starting virtual address. Need for tagging */
u32 bl_imem_off;
/**
* Offset from non-WPR base holding the BL data
* Offset = (Non-WPR base + #LSF_LSB_HEADER_ALIGNMENT +
* #LSF_UCODE_DATA_ALIGNMENT + #LSF_BL_DATA_ALIGNMENT) *
* #LS Falcon index
*/
u32 bl_data_off;
/**
* Size of BL data, BL data will be copied to LS Falcon DMEM of
* bl data size
*
* On GV11B, respective LS Falcon BL data size should not exceed
* below mentioned size.
* FALCON_ID_FECS DMEM size - 8k
* FALCON_ID_GPCCS DMEM size - 5k
*/
u32 bl_data_size;
/**
* Offset from non-WPR base address where UCODE Application code is
* located.
*/
u32 app_code_off;
/**
* Size of UCODE Application code.
*
* On GV11B, FECS/GPCCS LS Falcon app code size should not exceed
* below mentioned size.
* FALCON_ID_FECS IMEM size - 32k
* FALCON_ID_GPCCS IMEM size - 16k
*/
u32 app_code_size;
/**
* Offset from non-WPR base address where UCODE Application data
* is located
*/
u32 app_data_off;
/**
* Size of UCODE Application data.
*
* On GV11B, respective LS Falcon app data size should not exceed
* below mentioned size.
* FALCON_ID_FECS DMEM size - 8k
* FALCON_ID_GPCCS DMEM size - 5k
*/
u32 app_data_size;
/**
* NV_FLCN_ACR_LSF_FLAG_LOAD_CODE_AT_0 - Load BL at 0th IMEM offset
* NV_FLCN_ACR_LSF_FLAG_DMACTL_REQ_CTX - This falcon requires a ctx
* before issuing DMAs.
* NV_FLCN_ACR_LSF_FLAG_FORCE_PRIV_LOAD - Use priv loading method
* instead of bootloader/DMAs
*/
u32 flags;
};
#define FLCN_SIG_SIZE (4U)
/** @} */
/**

View File

@@ -39,6 +39,7 @@
#define NVGPU_PMU_UCODE_SIG "pmu_sig.bin"
#define NVGPU_PMU_UCODE_NEXT_IMAGE "gpmu_ucode_next_image.bin"
#define NVGPU_PMU_UCODE_NEXT_DESC "gpmu_ucode_next_desc.bin"
#define NVGPU_PMU_UCODE_NEXT_SIG "pmu_pkc_sig.bin"
void nvgpu_pmu_fw_get_cmd_line_args_offset(struct gk20a *g,
u32 *args_offset)
@@ -303,8 +304,14 @@ int nvgpu_pmu_init_pmu_fw(struct gk20a *g, struct nvgpu_pmu *pmu,
*rtos_fw_p = rtos_fw;
if (nvgpu_is_enabled(g, NVGPU_PMU_NEXT_CORE_ENABLED)) {
if (!nvgpu_is_enabled(g, NVGPU_PKC_LS_SIG_ENABLED)) {
err = pmu_fw_read(g, NVGPU_PMU_UCODE_NEXT_IMAGE,
NVGPU_PMU_UCODE_NEXT_DESC, NVGPU_PMU_UCODE_SIG);
} else {
err = pmu_fw_read(g, NVGPU_PMU_UCODE_NEXT_IMAGE,
NVGPU_PMU_UCODE_NEXT_DESC,
NVGPU_PMU_UCODE_NEXT_SIG);
}
} else {
err = pmu_fw_read(g, NVGPU_PMU_UCODE_IMAGE,

View File

@@ -207,6 +207,8 @@ struct gk20a;
DEFINE_FLAG(NVGPU_PMU_NEXT_CORE_ENABLED, "PMU NEXT CORE enabled"), \
DEFINE_FLAG(NVGPU_ACR_NEXT_CORE_ENABLED, \
"NEXT CORE availability for acr"), \
DEFINE_FLAG(NVGPU_PKC_LS_SIG_ENABLED, \
"PKC signature support"), \
DEFINE_FLAG(NVGPU_ELPG_MS_ENABLED, "ELPG_MS support"), \
DEFINE_FLAG(NVGPU_L2_MAX_WAYS_EVICT_LAST_ENABLED, \
"Set L2 Max Ways Evict Last support"), \