aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2016-11-18 03:47:08 -0500
committerBen Skeggs <bskeggs@redhat.com>2017-03-07 02:05:12 -0500
commit7775d0dcb215ce0eb639940d201fb9f557823bd7 (patch)
treef668fbb1293e8b3635034f303986a5b2b0d12fdf
parentbb5ec9c9dd1cc71bbae37a31229d72ffab9b6df4 (diff)
drm/nouveau/secboot: support optional falcons
PMU support has been enabled for r352 ACR, but it must remain optional if we want to preserve existing user-space that do not include it. Allow ACR to be instanciated with a list of optional LS falcons, that will not produce a fatal error if their firmware is not loaded. Also change the secure boot bootstrap logic to be able to fall back to legacy behavior if it turns out the boot falcon's LS firmware cannot be loaded. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c62
2 files changed, 39 insertions, 25 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h
index 58eb20a69e9c..580036d623b2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h
@@ -48,6 +48,7 @@ struct nvkm_acr_func {
48 * 48 *
49 * @boot_falcon: ID of the falcon that will perform secure boot 49 * @boot_falcon: ID of the falcon that will perform secure boot
50 * @managed_falcons: bitfield of falcons managed by this ACR 50 * @managed_falcons: bitfield of falcons managed by this ACR
51 * @optional_falcons: bitfield of falcons we can live without
51 * @start_address: virtual start address of the HS bootloader 52 * @start_address: virtual start address of the HS bootloader
52 */ 53 */
53struct nvkm_acr { 54struct nvkm_acr {
@@ -56,6 +57,7 @@ struct nvkm_acr {
56 57
57 enum nvkm_secboot_falcon boot_falcon; 58 enum nvkm_secboot_falcon boot_falcon;
58 unsigned long managed_falcons; 59 unsigned long managed_falcons;
60 unsigned long optional_falcons;
59 u32 start_address; 61 u32 start_address;
60}; 62};
61 63
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index a5d881438c1f..40c6568bfc31 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -503,6 +503,12 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
503 503
504 img = acr->func->ls_ucode_img_load(acr, falcon_id); 504 img = acr->func->ls_ucode_img_load(acr, falcon_id);
505 if (IS_ERR(img)) { 505 if (IS_ERR(img)) {
506 if (acr->base.optional_falcons & BIT(falcon_id)) {
507 managed_falcons &= ~BIT(falcon_id);
508 nvkm_info(subdev, "skipping %s falcon...\n",
509 nvkm_secboot_falcon_name[falcon_id]);
510 continue;
511 }
506 ret = PTR_ERR(img); 512 ret = PTR_ERR(img);
507 goto cleanup; 513 goto cleanup;
508 } 514 }
@@ -511,6 +517,24 @@ acr_r352_prepare_ls_blob(struct acr_r352 *acr, u64 wpr_addr, u32 wpr_size)
511 managed_count++; 517 managed_count++;
512 } 518 }
513 519
520 /* Commit the actual list of falcons we will manage from now on */
521 acr->base.managed_falcons = managed_falcons;
522
523 /*
524 * If the boot falcon has a firmare, let it manage the bootstrap of other
525 * falcons.
526 */
527 if (acr->func->ls_func[acr->base.boot_falcon] &&
528 (managed_falcons & BIT(acr->base.boot_falcon))) {
529 for_each_set_bit(falcon_id, &managed_falcons,
530 NVKM_SECBOOT_FALCON_END) {
531 if (falcon_id == acr->base.boot_falcon)
532 continue;
533
534 acr->lazy_bootstrap |= BIT(falcon_id);
535 }
536 }
537
514 /* 538 /*
515 * Fill the WPR and LSF headers with the right offsets and compute 539 * Fill the WPR and LSF headers with the right offsets and compute
516 * required WPR size 540 * required WPR size
@@ -948,20 +972,25 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
948 struct acr_r352 *acr = acr_r352(_acr); 972 struct acr_r352 *acr = acr_r352(_acr);
949 struct nvkm_pmu *pmu = sb->subdev.device->pmu; 973 struct nvkm_pmu *pmu = sb->subdev.device->pmu;
950 const char *fname = nvkm_secboot_falcon_name[falcon]; 974 const char *fname = nvkm_secboot_falcon_name[falcon];
975 bool wpr_already_set = sb->wpr_set;
951 int ret; 976 int ret;
952 977
953 /* Not self-managed? Redo secure boot entirely */ 978 /* Make sure secure boot is performed */
954 if (!nvkm_secboot_is_managed(sb, _acr->boot_falcon))
955 return acr_r352_reset_nopmu(acr, sb, falcon);
956
957 /*
958 * Otherwise ensure secure boot is done, and command the PMU to reset
959 * the desired falcon.
960 */
961 ret = acr_r352_bootstrap(acr, sb); 979 ret = acr_r352_bootstrap(acr, sb);
962 if (ret) 980 if (ret)
963 return ret; 981 return ret;
964 982
983 /* No PMU interface? */
984 if (!nvkm_secboot_is_managed(sb, _acr->boot_falcon)) {
985 /* Redo secure boot entirely if it was already done */
986 if (wpr_already_set)
987 return acr_r352_reset_nopmu(acr, sb, falcon);
988 /* Else return the result of the initial invokation */
989 else
990 return ret;
991 }
992
993 /* Otherwise just ask the PMU to reset the falcon */
965 nvkm_debug(&sb->subdev, "resetting %s falcon\n", fname); 994 nvkm_debug(&sb->subdev, "resetting %s falcon\n", fname);
966 ret = nvkm_msgqueue_acr_boot_falcon(pmu->queue, falcon); 995 ret = nvkm_msgqueue_acr_boot_falcon(pmu->queue, falcon);
967 if (ret) { 996 if (ret) {
@@ -1136,23 +1165,6 @@ acr_r352_new_(const struct acr_r352_func *func,
1136 acr->base.func = &acr_r352_base_func; 1165 acr->base.func = &acr_r352_base_func;
1137 acr->func = func; 1166 acr->func = func;
1138 1167
1139 /*
1140 * If we have a PMU firmware, let it manage the bootstrap of other
1141 * falcons.
1142 */
1143 if (func->ls_func[NVKM_SECBOOT_FALCON_PMU] &&
1144 (managed_falcons & BIT(NVKM_SECBOOT_FALCON_PMU))) {
1145 int i;
1146
1147 for (i = 0; i < NVKM_SECBOOT_FALCON_END; i++) {
1148 if (i == NVKM_SECBOOT_FALCON_PMU)
1149 continue;
1150
1151 if (func->ls_func[i])
1152 acr->lazy_bootstrap |= BIT(i);
1153 }
1154 }
1155
1156 return &acr->base; 1168 return &acr->base;
1157} 1169}
1158 1170