[Nouveau] [PATCH 5/8] secboot: use falcon library
Alexandre Courbot
acourbot at nvidia.com
Tue Dec 6 05:35:42 UTC 2016
Use the falcon library functions in secure boot. This removes a lot of
code and makes the secure boot flow easier to understand as no register
is directly accessed.
Signed-off-by: Alexandre Courbot <acourbot at nvidia.com>
---
drm/nouveau/include/nvkm/subdev/secboot.h | 3 +-
drm/nouveau/nvkm/subdev/secboot/base.c | 152 +----------------------
drm/nouveau/nvkm/subdev/secboot/gm200.c | 114 +++++------------
drm/nouveau/nvkm/subdev/secboot/priv.h | 2 +-
4 files changed, 45 insertions(+), 226 deletions(-)
diff --git a/drm/nouveau/include/nvkm/subdev/secboot.h b/drm/nouveau/include/nvkm/subdev/secboot.h
index fe0b849ac94e..7ead4cab363b 100644
--- a/drm/nouveau/include/nvkm/subdev/secboot.h
+++ b/drm/nouveau/include/nvkm/subdev/secboot.h
@@ -35,8 +35,7 @@ struct nvkm_secboot {
const struct nvkm_secboot_func *func;
struct nvkm_subdev subdev;
- enum nvkm_devidx devidx;
- u32 base;
+ bool debug;
};
#define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev)
diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c b/drm/nouveau/nvkm/subdev/secboot/base.c
index ad3767236475..bf23349e1edd 100644
--- a/drm/nouveau/nvkm/subdev/secboot/base.c
+++ b/drm/nouveau/nvkm/subdev/secboot/base.c
@@ -24,138 +24,6 @@
#include <subdev/mc.h>
#include <subdev/timer.h>
-static const char *
-managed_falcons_names[] = {
- [NVKM_FALCON_PMU] = "PMU",
- [NVKM_FALCON_RESERVED] = "<reserved>",
- [NVKM_FALCON_FECS] = "FECS",
- [NVKM_FALCON_GPCCS] = "GPCCS",
- [NVKM_FALCON_END] = "<invalid>",
-};
-
-/*
- * Helper falcon functions
- */
-
-static int
-falcon_clear_halt_interrupt(struct nvkm_device *device, u32 base)
-{
- int ret;
-
- /* clear halt interrupt */
- nvkm_mask(device, base + 0x004, 0x10, 0x10);
- /* wait until halt interrupt is cleared */
- ret = nvkm_wait_msec(device, 10, base + 0x008, 0x10, 0x0);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int
-falcon_wait_idle(struct nvkm_device *device, u32 base)
-{
- int ret;
-
- ret = nvkm_wait_msec(device, 10, base + 0x04c, 0xffff, 0x0);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int
-nvkm_secboot_falcon_enable(struct nvkm_secboot *sb)
-{
- struct nvkm_device *device = sb->subdev.device;
- int ret;
-
- /* enable engine */
- nvkm_mc_enable(device, sb->devidx);
- ret = nvkm_wait_msec(device, 10, sb->base + 0x10c, 0x6, 0x0);
- if (ret < 0) {
- nvkm_error(&sb->subdev, "Falcon mem scrubbing timeout\n");
- nvkm_mc_disable(device, sb->devidx);
- return ret;
- }
-
- ret = falcon_wait_idle(device, sb->base);
- if (ret)
- return ret;
-
- /* enable IRQs */
- nvkm_wr32(device, sb->base + 0x010, 0xff);
- nvkm_mc_intr_mask(device, sb->devidx, true);
-
- return 0;
-}
-
-static int
-nvkm_secboot_falcon_disable(struct nvkm_secboot *sb)
-{
- struct nvkm_device *device = sb->subdev.device;
-
- /* disable IRQs and wait for any previous code to complete */
- nvkm_mc_intr_mask(device, sb->devidx, false);
- nvkm_wr32(device, sb->base + 0x014, 0xff);
-
- falcon_wait_idle(device, sb->base);
-
- /* disable engine */
- nvkm_mc_disable(device, sb->devidx);
-
- return 0;
-}
-
-int
-nvkm_secboot_falcon_reset(struct nvkm_secboot *sb)
-{
- int ret;
-
- ret = nvkm_secboot_falcon_disable(sb);
- if (ret)
- return ret;
-
- ret = nvkm_secboot_falcon_enable(sb);
- if (ret)
- return ret;
-
- return 0;
-}
-
-/**
- * nvkm_secboot_falcon_run - run the falcon that will perform secure boot
- *
- * This function is to be called after all chip-specific preparations have
- * been completed. It will start the falcon to perform secure boot, wait for
- * it to halt, and report if an error occurred.
- */
-int
-nvkm_secboot_falcon_run(struct nvkm_secboot *sb)
-{
- struct nvkm_device *device = sb->subdev.device;
- int ret;
-
- /* Start falcon */
- nvkm_wr32(device, sb->base + 0x100, 0x2);
-
- /* Wait for falcon halt */
- ret = nvkm_wait_msec(device, 100, sb->base + 0x100, 0x10, 0x10);
- if (ret < 0)
- return ret;
-
- /* If mailbox register contains an error code, then ACR has failed */
- ret = nvkm_rd32(device, sb->base + 0x040);
- if (ret) {
- nvkm_error(&sb->subdev, "ACR boot failed, ret 0x%08x", ret);
- falcon_clear_halt_interrupt(device, sb->base);
- return -EINVAL;
- }
-
- return 0;
-}
-
-
/**
* nvkm_secboot_reset() - reset specified falcon
*/
@@ -202,8 +70,15 @@ static int
nvkm_secboot_oneinit(struct nvkm_subdev *subdev)
{
struct nvkm_secboot *sb = nvkm_secboot(subdev);
+ struct nvkm_falcon *falcon;
int ret = 0;
+ falcon = nvkm_falcon_get(subdev, sb->func->boot_falcon);
+ if (IS_ERR(falcon))
+ return PTR_ERR(falcon);
+ sb->debug = falcon->debug;
+ nvkm_falcon_put(falcon);
+
/* Call chip-specific init function */
if (sb->func->init)
ret = sb->func->init(sb);
@@ -257,20 +132,9 @@ nvkm_secboot_ctor(const struct nvkm_secboot_func *func,
nvkm_subdev_ctor(&nvkm_secboot, device, index, &sb->subdev);
sb->func = func;
- /* setup the performing falcon's base address and masks */
- switch (func->boot_falcon) {
- case NVKM_FALCON_PMU:
- sb->devidx = NVKM_SUBDEV_PMU;
- sb->base = 0x10a000;
- break;
- default:
- nvkm_error(&sb->subdev, "invalid secure boot falcon\n");
- return -EINVAL;
- };
-
nvkm_debug(&sb->subdev, "securely managed falcons:\n");
for_each_set_bit(fid, &sb->func->managed_falcons, NVKM_FALCON_END)
- nvkm_debug(&sb->subdev, "- %s\n", managed_falcons_names[fid]);
+ nvkm_debug(&sb->subdev, "- %s\n", nvkm_falcon_name[fid]);
return 0;
}
diff --git a/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drm/nouveau/nvkm/subdev/secboot/gm200.c
index 718cfa129a82..b82e8072e332 100644
--- a/drm/nouveau/nvkm/subdev/secboot/gm200.c
+++ b/drm/nouveau/nvkm/subdev/secboot/gm200.c
@@ -878,7 +878,7 @@ gm200_secboot_hsf_patch_signature(struct gm200_secboot *gsb, void *acr_image)
u32 sig_size;
/* Falcon in debug or production mode? */
- if ((nvkm_rd32(sb->subdev.device, sb->base + 0xc08) >> 20) & 0x1) {
+ if (sb->debug) {
sig = acr_image + fw_hdr->sig_dbg_offset;
sig_size = fw_hdr->sig_dbg_size;
} else {
@@ -1092,96 +1092,33 @@ gm200_secboot_blobs_ready(struct gm200_secboot *gsb)
* gm200_secboot_load_hs_bl() - load HS bootloader into DMEM and IMEM
*/
static void
-gm200_secboot_load_hs_bl(struct gm200_secboot *gsb, void *data, u32 data_size)
+gm200_secboot_load_hs_bl(struct gm200_secboot *gsb, struct nvkm_falcon *falcon,
+ void *data, u32 data_size)
{
- struct nvkm_device *device = gsb->base.subdev.device;
struct fw_bin_header *hdr = gsb->hsbl_blob;
struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset;
void *blob_data = gsb->hsbl_blob + hdr->data_offset;
void *hsbl_code = blob_data + hsbl_desc->code_off;
void *hsbl_data = blob_data + hsbl_desc->data_off;
u32 code_size = ALIGN(hsbl_desc->code_size, 256);
- const u32 base = gsb->base.base;
- u32 blk;
u32 tag;
- int i;
/*
* Copy HS bootloader data
*/
- nvkm_wr32(device, base + 0x1c0, (0x00000000 | (0x1 << 24)));
- for (i = 0; i < hsbl_desc->data_size / 4; i++)
- nvkm_wr32(device, base + 0x1c4, ((u32 *)hsbl_data)[i]);
+ nvkm_falcon_load_dmem(falcon, hsbl_data, 0x0, hsbl_desc->data_size, 0);
/*
* Copy HS bootloader interface structure where the HS descriptor
* expects it to be
*/
- nvkm_wr32(device, base + 0x1c0,
- (hsbl_desc->dmem_load_off | (0x1 << 24)));
- for (i = 0; i < data_size / 4; i++)
- nvkm_wr32(device, base + 0x1c4, ((u32 *)data)[i]);
+ nvkm_falcon_load_dmem(falcon, data, hsbl_desc->dmem_load_off, data_size,
+ 0);
/* Copy HS bootloader code to end of IMEM */
- blk = (nvkm_rd32(device, base + 0x108) & 0x1ff) - (code_size >> 8);
tag = hsbl_desc->start_tag;
- nvkm_wr32(device, base + 0x180, ((blk & 0xff) << 8) | (0x1 << 24));
- for (i = 0; i < code_size / 4; i++) {
- /* write new tag every 256B */
- if ((i & 0x3f) == 0) {
- nvkm_wr32(device, base + 0x188, tag & 0xffff);
- tag++;
- }
- nvkm_wr32(device, base + 0x184, ((u32 *)hsbl_code)[i]);
- }
- nvkm_wr32(device, base + 0x188, 0);
-}
-
-/**
- * gm200_secboot_setup_falcon() - set up the secure falcon for secure boot
- */
-static int
-gm200_secboot_setup_falcon(struct gm200_secboot *gsb)
-{
- struct nvkm_device *device = gsb->base.subdev.device;
- struct fw_bin_header *hdr = gsb->hsbl_blob;
- struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset;
- /* virtual start address for boot vector */
- u32 virt_addr = hsbl_desc->start_tag << 8;
- const u32 base = gsb->base.base;
- const u32 reg_base = base + 0xe00;
- u32 inst_loc;
- int ret;
-
- ret = nvkm_secboot_falcon_reset(&gsb->base);
- if (ret)
- return ret;
-
- /* setup apertures - virtual */
- nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_UCODE), 0x4);
- nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_VIRT), 0x0);
- /* setup apertures - physical */
- nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_VID), 0x4);
- nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_SYS_COH),
- 0x4 | 0x1);
- nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_SYS_NCOH),
- 0x4 | 0x2);
-
- /* Set context */
- if (nvkm_memory_target(gsb->inst->memory) == NVKM_MEM_TARGET_VRAM)
- inst_loc = 0x0; /* FB */
- else
- inst_loc = 0x3; /* Non-coherent sysmem */
-
- nvkm_mask(device, base + 0x048, 0x1, 0x1);
- nvkm_wr32(device, base + 0x480,
- ((gsb->inst->addr >> 12) & 0xfffffff) |
- (inst_loc << 28) | (1 << 30));
-
- /* Set boot vector to code's starting virtual address */
- nvkm_wr32(device, base + 0x104, virt_addr);
-
- return 0;
+ nvkm_falcon_load_imem(falcon, hsbl_code, falcon->code.limit - code_size,
+ code_size, tag, 0, false);
}
/**
@@ -1191,16 +1128,27 @@ static int
gm200_secboot_run_hs_blob(struct gm200_secboot *gsb, struct nvkm_gpuobj *blob,
struct gm200_flcn_bl_desc *desc)
{
+ struct nvkm_subdev *subdev = &gsb->base.subdev;
+ struct fw_bin_header *hdr = gsb->hsbl_blob;
+ struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset;
struct nvkm_vma vma;
+ struct nvkm_falcon *falcon;
u64 vma_addr;
const u32 bl_desc_size = gsb->func->bl_desc_size;
+ const u32 virt_addr = hsbl_desc->start_tag << 8;
u8 bl_desc[bl_desc_size];
int ret;
+ falcon = nvkm_falcon_get(subdev, gsb->base.func->boot_falcon);
+ if (IS_ERR(falcon))
+ return PTR_ERR(falcon);
+
/* Map the HS firmware so the HS bootloader can see it */
ret = nvkm_gpuobj_map(blob, gsb->vm, NV_MEM_ACCESS_RW, &vma);
- if (ret)
+ if (ret) {
+ nvkm_falcon_put(falcon);
return ret;
+ }
/* Add the mapping address to the DMA bases */
vma_addr = flcn64_to_u64(desc->code_dma_base) + vma.offset;
@@ -1213,19 +1161,28 @@ gm200_secboot_run_hs_blob(struct gm200_secboot *gsb, struct nvkm_gpuobj *blob,
/* Fixup the BL header */
gsb->func->fixup_bl_desc(desc, &bl_desc);
- /* Reset the falcon and make it ready to run the HS bootloader */
- ret = gm200_secboot_setup_falcon(gsb);
- if (ret)
- goto done;
+ /* Reset and set the falcon up */
+ nvkm_falcon_reset(falcon);
+ nvkm_falcon_bind_context(falcon, gsb->inst);
/* Load the HS bootloader into the falcon's IMEM/DMEM */
- gm200_secboot_load_hs_bl(gsb, &bl_desc, bl_desc_size);
+ gm200_secboot_load_hs_bl(gsb, falcon, &bl_desc, bl_desc_size);
/* Start the HS bootloader */
- ret = nvkm_secboot_falcon_run(&gsb->base);
+ nvkm_falcon_set_start_addr(falcon, virt_addr);
+ nvkm_falcon_start(falcon);
+ ret = nvkm_falcon_wait_for_halt(falcon, 100);
if (ret)
goto done;
+ /* If mailbox register contains an error code, then ACR has failed */
+ ret = nvkm_falcon_rd32(falcon, 0x040);
+ if (ret) {
+ nvkm_error(subdev, "ACR boot failed, ret 0x%08x", ret);
+ ret = -EINVAL;
+ goto done;
+ }
+
done:
/* Restore the original DMA addresses */
vma_addr = flcn64_to_u64(desc->code_dma_base) - vma.offset;
@@ -1237,6 +1194,7 @@ done:
/* We don't need the ACR firmware anymore */
nvkm_gpuobj_unmap(&vma);
+ nvkm_falcon_put(falcon);
return ret;
}
diff --git a/drm/nouveau/nvkm/subdev/secboot/priv.h b/drm/nouveau/nvkm/subdev/secboot/priv.h
index f77b69219b44..2123539a7ae5 100644
--- a/drm/nouveau/nvkm/subdev/secboot/priv.h
+++ b/drm/nouveau/nvkm/subdev/secboot/priv.h
@@ -42,8 +42,6 @@ struct nvkm_secboot_func {
int nvkm_secboot_ctor(const struct nvkm_secboot_func *, struct nvkm_device *,
int index, struct nvkm_secboot *);
-int nvkm_secboot_falcon_reset(struct nvkm_secboot *);
-int nvkm_secboot_falcon_run(struct nvkm_secboot *);
struct flcn_u64 {
u32 lo;
--
git-series 0.8.10
More information about the Nouveau
mailing list