summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/pmu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2020-01-14 23:34:22 +0300
committerBen Skeggs <bskeggs@redhat.com>2020-01-15 03:50:29 +0300
commit22dcda45a3d1dfe6eeb4ab0a3b9aaa2333cb649d (patch)
treefc4d20a93edce93ca252d9f0663cd620e65d1c51 /drivers/gpu/drm/nouveau/nvkm/subdev/pmu
parentebe52a58acca308142ba2811e50a1b3bf047240d (diff)
downloadlinux-22dcda45a3d1dfe6eeb4ab0a3b9aaa2333cb649d.tar.xz
drm/nouveau/acr: implement new subdev to replace "secure boot"
ACR is responsible for managing the firmware for LS (Low Secure) falcons, this was previously handled in the driver by SECBOOT. This rewrite started from some test code that attempted to replicate the procedure RM uses in order to debug early Turing ACR firmwares that were provided by NVIDIA for development. Compared with SECBOOT, the code is structured into more individual steps, with the aim of making the process easier to follow/debug, whilst making it possible to support newer firmware versions that may have a different binary format or API interface. The HS (High Secure) binary(s) are now booted earlier in device init, to match the behaviour of RM, whereas SECBOOT would delay this until we try to boot the first LS falcon. There's also additional debugging features available, with the intention of making it easier to solve issues during FW/HW bring-up in the future. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/pmu')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c56
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h4
3 files changed, 64 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
index ef22678d041a..6d5a13e4a857 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
@@ -21,9 +21,10 @@
*/
#include "priv.h"
-#include <core/msgqueue.h>
+#include <core/memory.h>
#include <subdev/acr.h>
+#include <nvfw/flcn.h>
#include <nvfw/pmu.h>
static int
@@ -60,14 +61,65 @@ int
gm20b_pmu_acr_boot(struct nvkm_falcon *falcon)
{
struct nv_pmu_args args = { .secure_mode = true };
- const u32 addr_args = falcon->data.limit - NVKM_MSGQUEUE_CMDLINE_SIZE; /*XXX*/
+ const u32 addr_args = falcon->data.limit - sizeof(struct nv_pmu_args);
nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0);
nvkm_falcon_start(falcon);
return 0;
}
+void
+gm20b_pmu_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
+{
+ struct loader_config hdr;
+ u64 addr;
+
+ nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr));
+ addr = ((u64)hdr.code_dma_base1 << 40 | hdr.code_dma_base << 8);
+ hdr.code_dma_base = lower_32_bits((addr + adjust) >> 8);
+ hdr.code_dma_base1 = upper_32_bits((addr + adjust) >> 8);
+ addr = ((u64)hdr.data_dma_base1 << 40 | hdr.data_dma_base << 8);
+ hdr.data_dma_base = lower_32_bits((addr + adjust) >> 8);
+ hdr.data_dma_base1 = upper_32_bits((addr + adjust) >> 8);
+ addr = ((u64)hdr.overlay_dma_base1 << 40 | hdr.overlay_dma_base << 8);
+ hdr.overlay_dma_base = lower_32_bits((addr + adjust) << 8);
+ hdr.overlay_dma_base1 = upper_32_bits((addr + adjust) << 8);
+ nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
+
+ loader_config_dump(&acr->subdev, &hdr);
+}
+
+void
+gm20b_pmu_acr_bld_write(struct nvkm_acr *acr, u32 bld,
+ struct nvkm_acr_lsfw *lsfw)
+{
+ const u64 base = lsfw->offset.img + lsfw->app_start_offset;
+ const u64 code = (base + lsfw->app_resident_code_offset) >> 8;
+ const u64 data = (base + lsfw->app_resident_data_offset) >> 8;
+ const struct loader_config hdr = {
+ .dma_idx = FALCON_DMAIDX_UCODE,
+ .code_dma_base = lower_32_bits(code),
+ .code_size_total = lsfw->app_size,
+ .code_size_to_load = lsfw->app_resident_code_size,
+ .code_entry_point = lsfw->app_imem_entry,
+ .data_dma_base = lower_32_bits(data),
+ .data_size = lsfw->app_resident_data_size,
+ .overlay_dma_base = lower_32_bits(code),
+ .argc = 1,
+ .argv = lsfw->falcon->data.limit - sizeof(struct nv_pmu_args),
+ .code_dma_base1 = upper_32_bits(code),
+ .data_dma_base1 = upper_32_bits(data),
+ .overlay_dma_base1 = upper_32_bits(code),
+ };
+
+ nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr));
+}
+
static const struct nvkm_acr_lsf_func
gm20b_pmu_acr = {
+ .flags = NVKM_ACR_LSF_DMACTL_REQ_CTX,
+ .bld_size = sizeof(struct loader_config),
+ .bld_write = gm20b_pmu_acr_bld_write,
+ .bld_patch = gm20b_pmu_acr_bld_patch,
.boot = gm20b_pmu_acr_boot,
.bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
index 0e0ebd6857da..39c86bc56310 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
@@ -23,6 +23,7 @@
#include <subdev/acr.h>
+#include <nvfw/flcn.h>
#include <nvfw/pmu.h>
static int
@@ -58,6 +59,11 @@ gp10b_pmu_acr_bootstrap_multiple_falcons(struct nvkm_falcon *falcon, u32 mask)
static const struct nvkm_acr_lsf_func
gp10b_pmu_acr = {
+ .flags = NVKM_ACR_LSF_DMACTL_REQ_CTX,
+ .bld_size = sizeof(struct loader_config),
+ .bld_write = gm20b_pmu_acr_bld_write,
+ .bld_patch = gm20b_pmu_acr_bld_patch,
+ .boot = gm20b_pmu_acr_boot,
.bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
.bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
index 21ca224fc186..f470859244de 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
@@ -5,6 +5,7 @@
#include <subdev/pmu.h>
#include <subdev/pmu/fuc/os.h>
enum nvkm_acr_lsf_id;
+struct nvkm_acr_lsfw;
struct nvkm_pmu_func {
const struct nvkm_falcon_func *flcn;
@@ -43,6 +44,9 @@ void gf100_pmu_reset(struct nvkm_pmu *);
void gk110_pmu_pgob(struct nvkm_pmu *, bool);
+void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64);
+void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *);
+int gm20b_pmu_acr_boot(struct nvkm_falcon *);
int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
void gm20b_pmu_recv(struct nvkm_pmu *);
int gm20b_pmu_initmsg(struct nvkm_pmu *);