nouveau: add secure boot support for dGPU and Tegra
v3 cover nouveau: add secure boot support for dGPU and Tegra
New version of the secure boot code that works with the blobs just merged into linux-firmware. Since the required Mesa patches are also merged, this set is the last piece of the puzzle to get out-of-the-box accelerated Maxwell 2.
The basic code remains the same, with a few improvements with respect to how secure falcons are started. Hopefully the patchset is better split too.
I have a work-in-progress to further split the secboot subdev and handle other format differences that future chips are likely to introduce, but this current code should be good for Maxwell 2 chips.
I hope to get this merged in time for 4.6, so please let me know quickly of any required changes!
Changes since v2:
- Works with final firmware in linux-firmware
- Use func structure in secboot to abstract differences between dGPU and Tegra
- Better management of firmware loading in GR
- Abstract the way secure falcons are started
- Add MODULE_FIRMWARE statements
- ... plenty of small fixes
Alexandre Courbot (11):
core: add gpuobj memcpy helper functions gr/gk20a: move firmware bundle release to gf100 gr/gf100: load firmware in outer function gr/gk20a: simplify external bundle loading functions gr/gk20a: share external bundles loading functions gr/gm200: load external firmware and bundles
core: add support for secure boot
gr/gf100: add support for securely-managed falcons gr/gm200: do not load firmware for secure falcons secboot/gm200: add secure-boot support secboot/gm20b: add secure boot support
drm/nouveau/include/nvkm/core/device.h | 3 + drm/nouveau/include/nvkm/core/gpuobj.h | 4 + drm/nouveau/include/nvkm/subdev/secboot.h | 59 ++ drm/nouveau/nvkm/core/gpuobj.c | 20 + drm/nouveau/nvkm/core/subdev.c | 1 + drm/nouveau/nvkm/engine/device/base.c | 5 + drm/nouveau/nvkm/engine/device/priv.h | 1 + drm/nouveau/nvkm/engine/gr/gf100.c | 65 +- drm/nouveau/nvkm/engine/gr/gf100.h | 16 +- drm/nouveau/nvkm/engine/gr/gk20a.c | 181 ++-- drm/nouveau/nvkm/engine/gr/gm200.c | 49 +- drm/nouveau/nvkm/engine/gr/gm206.c | 2 +- drm/nouveau/nvkm/engine/gr/gm20b.c | 12 +- drm/nouveau/nvkm/subdev/Kbuild | 1 + drm/nouveau/nvkm/subdev/secboot/Kbuild | 3 + drm/nouveau/nvkm/subdev/secboot/base.c | 296 ++++++ drm/nouveau/nvkm/subdev/secboot/gm200.c | 1485 +++++++++++++++++++++++++++++ drm/nouveau/nvkm/subdev/secboot/gm20b.c | 233 +++++ drm/nouveau/nvkm/subdev/secboot/priv.h | 226 +++++ 19 files changed, 2544 insertions(+), 118 deletions(-) create mode 100644 drm/nouveau/include/nvkm/subdev/secboot.h create mode 100644 drm/nouveau/nvkm/subdev/secboot/Kbuild create mode 100644 drm/nouveau/nvkm/subdev/secboot/base.c create mode 100644 drm/nouveau/nvkm/subdev/secboot/gm200.c create mode 100644 drm/nouveau/nvkm/subdev/secboot/gm20b.c create mode 100644 drm/nouveau/nvkm/subdev/secboot/priv.h
Signature · 1 line
2.7.1
A message that is not in the archive (sent off-list or not yet received): 1456292544-32206-1-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org
PATCH v3 1/11 core: add gpuobj memcpy helper functions
Add memcpy functions to copy a buffer to a gpuobj and vice-versa. This will be used by the secure boot code.
--- drm/nouveau/include/nvkm/core/gpuobj.h | 4 ++++ drm/nouveau/nvkm/core/gpuobj.c | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+)
drm/nouveau/include/nvkm/core/gpuobj.h +4 -0
@@ -37,4 +37,8 @@ int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **);int nvkm_gpuobj_map (struct nvkm_gpuobj *,struct nvkm_vm *,u32 access,struct nvkm_vma *);void nvkm_gpuobj_unmap (struct nvkm_vma *); +void nvkm_gpuobj_memcpy_to (struct nvkm_gpuobj *dst,u32 dstoffset,void *src, +u32 length); +void nvkm_gpuobj_memcpy_from (void *dst,struct nvkm_gpuobj *src,u32 srcoffset, +u32 length);#endif
drm/nouveau/nvkm/core/gpuobj.c +20 -0
@@ -253,3 +253,23 @@ nvkm_gpuobj_wrap(struct nvkm_memory *memory, struct nvkm_gpuobj **pgpuobj) (*pgpuobj)->size =nvkm_memory_size (memory);return 0 ; } + +void +nvkm_gpuobj_memcpy_to (struct nvkm_gpuobj *dst,u32 dstoffset,void *src, +u32 length) +{ +int i; + +for (i =0 ; i < length; i +=4 ) +nvkm_wo32 (dst, dstoffset + i, *(u32 *)(src + i)); +} + +void +nvkm_gpuobj_memcpy_from (void *dst,struct nvkm_gpuobj *src,u32 srcoffset, +u32 length) +{ +int i; + +for (i =0 ; i < length; i +=4 ) + ((u32 *)src)[i /4 ] =nvkm_ro32 (src, srcoffset + i); +}
Signature · 1 line
2.7.1
PATCH v3 2/11 gr/gk20a: move firmware bundle release to gf100
In reply to a message not in the archiveSome members of gf100_gr were freed by the gk20a driver. That's not where it should be done - free them in gf100 so other chips that use NVIDIA-provided firmware free these structures properly.
This also removes the need for a GK20A-specific destructor.
--- drm/nouveau/nvkm/engine/gr/gf100.c | 11 +++++++++++ drm/nouveau/nvkm/engine/gr/gf100.h | 3 +-- drm/nouveau/nvkm/engine/gr/gk20a.c | 16 ---------------- drm/nouveau/nvkm/engine/gr/gm20b.c | 1 - 4 files changed, 12 insertions(+), 19 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.c +11 -0
@@ -1684,6 +1684,12 @@ gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc) fuc->data =NULL ; } +static void +gf100_gr_dtor_init (struct gf100_gr_pack *pack) +{ +vfree (pack); +} +void *gf100_gr_dtor (struct nvkm_gr *base) {
@@ -1698,6 +1704,11 @@ gf100_gr_dtor(struct nvkm_gr *base)gf100_gr_dtor_fw (&gr->fuc41ac);gf100_gr_dtor_fw (&gr->fuc41ad); +gf100_gr_dtor_init (gr->fuc_bundle); +gf100_gr_dtor_init (gr->fuc_method); +gf100_gr_dtor_init (gr->fuc_sw_ctx); +gf100_gr_dtor_init (gr->fuc_sw_nonctx); +nvkm_memory_del (&gr->unk4188b8);nvkm_memory_del (&gr->unk4188b4);return gr;
drm/nouveau/nvkm/engine/gr/gf100.h +1 -2
@@ -82,7 +82,7 @@ struct gf100_gr {/* * Used if the register packs are loaded from NVIDIA fw instead of -* using hardcoded arrays. +* using hardcoded arrays. To be allocated with vzalloc(). */ struct gf100_gr_pack *fuc_sw_nonctx;struct gf100_gr_pack *fuc_sw_ctx;
@@ -140,7 +140,6 @@ int gk104_gr_init(struct gf100_gr *);int gk20a_gr_new_ (const struct gf100_gr_func *,struct nvkm_device *,int ,struct nvkm_gr **); -void gk20a_gr_dtor (struct gf100_gr *);int gk20a_gr_init (struct gf100_gr *);int gm200_gr_init (struct gf100_gr *);
drm/nouveau/nvkm/engine/gr/gk20a.c +0 -16
@@ -26,12 +26,6 @@#include <nvif/class.h> -static void -gk20a_gr_init_dtor (struct gf100_gr_pack *pack) -{ -vfree (pack); -} -struct gk20a_fw_av {u32 addr;
@@ -273,15 +267,6 @@ gk20a_gr_init(struct gf100_gr *gr)return gf100_gr_init_ctxctl (gr); } -void -gk20a_gr_dtor (struct gf100_gr *gr) -{ -gk20a_gr_init_dtor (gr->fuc_method); -gk20a_gr_init_dtor (gr->fuc_bundle); -gk20a_gr_init_dtor (gr->fuc_sw_ctx); -gk20a_gr_init_dtor (gr->fuc_sw_nonctx); -} -int gk20a_gr_new_ (const struct gf100_gr_func *func,struct nvkm_device *device,int index,struct nvkm_gr **pgr)
@@ -335,7 +320,6 @@ gk20a_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device,static const struct gf100_gr_func gk20a_gr = { - .dtor = gk20a_gr_dtor, .init = gk20a_gr_init, .set_hww_esr_report_mask = gk20a_gr_set_hww_esr_report_mask, .ppc_nr =1 ,
drm/nouveau/nvkm/engine/gr/gm20b.c +0 -1
@@ -61,7 +61,6 @@ gm20b_gr_set_hww_esr_report_mask(struct gf100_gr *gr)static const struct gf100_gr_func gm20b_gr = { - .dtor = gk20a_gr_dtor, .init = gk20a_gr_init, .init_gpc_mmu = gm20b_gr_init_gpc_mmu, .set_hww_esr_report_mask = gm20b_gr_set_hww_esr_report_mask,
Signature · 1 line
2.7.1
PATCH v3 3/11 gr/gf100: load firmware in outer function
In reply to a message not in the archiveThe firmwares required by GR may vary from chip to chip, especially with the introduction of secure boot and NVIDIA-provided firmwares. Move the firmware loading outside of gf100_gr_ctor so other chips may still call it while managing their firmwares themselves.
--- drm/nouveau/nvkm/engine/gr/gf100.c | 26 ++++++++++++++++---------- drm/nouveau/nvkm/engine/gr/gk20a.c | 6 ++++++ 2 files changed, 22 insertions(+), 10 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.c +16 -10
@@ -1762,15 +1762,6 @@ gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,if (ret)return ret; -if (gr->firmware) { -nvkm_info (&gr->base.engine.subdev,"using external firmware\n" ); -if (gf100_gr_ctor_fw (gr,"fecs_inst" , &gr->fuc409c) || -gf100_gr_ctor_fw (gr,"fecs_data" , &gr->fuc409d) || -gf100_gr_ctor_fw (gr,"gpccs_inst" , &gr->fuc41ac) || -gf100_gr_ctor_fw (gr,"gpccs_data" , &gr->fuc41ad)) -return -ENODEV ; - } -return 0 ; }
@@ -1779,10 +1770,25 @@ gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, int index, struct nvkm_gr **pgr) { struct gf100_gr *gr; +int ret; +if (!(gr =kzalloc (sizeof (*gr),GFP_KERNEL )))return -ENOMEM ; *pgr = &gr->base; -return gf100_gr_ctor (func, device, index, gr); + + ret =gf100_gr_ctor (func, device, index, gr); +if (ret) +return ret; + +if (gr->firmware) { +if (gf100_gr_ctor_fw (gr,"fecs_inst" , &gr->fuc409c) || +gf100_gr_ctor_fw (gr,"fecs_data" , &gr->fuc409d) || +gf100_gr_ctor_fw (gr,"gpccs_inst" , &gr->fuc41ac) || +gf100_gr_ctor_fw (gr,"gpccs_data" , &gr->fuc41ad)) +return -ENODEV ; + } + +return 0 ; }int
drm/nouveau/nvkm/engine/gr/gk20a.c +6 -0
@@ -283,6 +283,12 @@ gk20a_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device,if (ret)return ret; +if (gf100_gr_ctor_fw (gr,"fecs_inst" , &gr->fuc409c) || +gf100_gr_ctor_fw (gr,"fecs_data" , &gr->fuc409d) || +gf100_gr_ctor_fw (gr,"gpccs_inst" , &gr->fuc41ac) || +gf100_gr_ctor_fw (gr,"gpccs_data" , &gr->fuc41ad)) +return -ENODEV ; + ret =gf100_gr_ctor_fw (gr,"sw_nonctx" , &fuc);if (ret)return ret;
Signature · 1 line
2.7.1
PATCH v3 4/11 gr/gk20a: simplify external bundle loading functions
In reply to a message not in the archiveMake these functions easier to use by handling memory management from within.
--- drm/nouveau/nvkm/engine/gr/gk20a.c | 120 ++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 47 deletions(-)
drm/nouveau/nvkm/engine/gr/gk20a.c +73 -47
@@ -32,25 +32,34 @@ struct gk20a_fw_avu32 data; }; -static struct gf100_gr_pack * -gk20a_gr_av_to_init (struct gf100_gr_fuc *fuc) +static int +gk20a_gr_av_to_init (struct gf100_gr *gr,const char *fw_name, +struct gf100_gr_pack **ppack) { +struct gf100_gr_fuc fuc;struct gf100_gr_init *init;struct gf100_gr_pack *pack; -const int nent = (fuc->size /sizeof (struct gk20a_fw_av )); +int nent; +int ret;int i; + ret =gf100_gr_ctor_fw (gr, fw_name, &fuc); +if (ret) +return ret; + + nent = (fuc.size /sizeof (struct gk20a_fw_av )); pack =vzalloc ((sizeof (*pack) *2 ) + (sizeof (*init) * (nent +1 ))); -if (!pack) -return ERR_PTR (-ENOMEM ); +if (!pack) { + ret = -ENOMEM ; + goto end; + } init = (void *)(pack +2 ); - pack[0 ].init = init;for (i =0 ; i < nent; i++) {struct gf100_gr_init *ent = &init[i]; -struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc->data)[i]; +struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc.data)[i]; ent->addr = av->addr; ent->data = av->data;
@@ -58,7 +67,11 @@ gk20a_gr_av_to_init(struct gf100_gr_fuc *fuc) ent->pitch =1 ; } -return pack; + *ppack = pack; + +end: +gf100_gr_dtor_fw (&fuc); +return ret; }struct gk20a_fw_aiv
@@ -68,25 +81,34 @@ struct gk20a_fw_aivu32 data; }; -static struct gf100_gr_pack * -gk20a_gr_aiv_to_init (struct gf100_gr_fuc *fuc) +static int +gk20a_gr_aiv_to_init (struct gf100_gr *gr,const char *fw_name, +struct gf100_gr_pack **ppack) { +struct gf100_gr_fuc fuc;struct gf100_gr_init *init;struct gf100_gr_pack *pack; -const int nent = (fuc->size /sizeof (struct gk20a_fw_aiv )); +int nent; +int ret;int i; + ret =gf100_gr_ctor_fw (gr, fw_name, &fuc); +if (ret) +return ret; + + nent = (fuc.size /sizeof (struct gk20a_fw_aiv )); pack =vzalloc ((sizeof (*pack) *2 ) + (sizeof (*init) * (nent +1 ))); -if (!pack) -return ERR_PTR (-ENOMEM ); +if (!pack) { + ret = -ENOMEM ; + goto end; + } init = (void *)(pack +2 ); - pack[0 ].init = init;for (i =0 ; i < nent; i++) {struct gf100_gr_init *ent = &init[i]; -struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)fuc->data)[i]; +struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)fuc.data)[i]; ent->addr = av->addr; ent->data = av->data;
@@ -94,30 +116,45 @@ gk20a_gr_aiv_to_init(struct gf100_gr_fuc *fuc) ent->pitch =1 ; } -return pack; + *ppack = pack; + +end: +gf100_gr_dtor_fw (&fuc); +return ret; } -static struct gf100_gr_pack * -gk20a_gr_av_to_method (struct gf100_gr_fuc *fuc) +static int +gk20a_gr_av_to_method (struct gf100_gr *gr,const char *fw_name, +struct gf100_gr_pack **ppack) { +struct gf100_gr_fuc fuc;struct gf100_gr_init *init;struct gf100_gr_pack *pack;/* We don't suppose we will initialize more than 16 classes here... */ static const unsigned int max_classes =16 ; -const int nent = (fuc->size /sizeof (struct gk20a_fw_av )); -int i, classidx =0 ; -u32 prevclass =0 ; +u32 classidx =0 , prevclass =0 ; +int nent; +int ret; +int i; + + ret =gf100_gr_ctor_fw (gr, fw_name, &fuc); +if (ret) +return ret; + + nent = (fuc.size /sizeof (struct gk20a_fw_av )); pack =vzalloc ((sizeof (*pack) * max_classes) + (sizeof (*init) * (nent +1 ))); -if (!pack) -return ERR_PTR (-ENOMEM ); +if (!pack) { + ret = -ENOMEM ; + goto end; + } init = (void *)(pack + max_classes);for (i =0 ; i < nent; i++) {struct gf100_gr_init *ent = &init[i]; -struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc->data)[i]; +struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc.data)[i];u32 class = av->addr &0xffff ;u32 addr = (av->addr &0xffff0000 ) >>14 ;
@@ -127,7 +164,8 @@ gk20a_gr_av_to_method(struct gf100_gr_fuc *fuc) prevclass = class;if (++classidx >= max_classes) {vfree (pack); -return ERR_PTR (-ENOSPC ); + ret = -ENOSPC ; + goto end; } }
@@ -137,7 +175,11 @@ gk20a_gr_av_to_method(struct gf100_gr_fuc *fuc) ent->pitch =1 ; } -return pack; + *ppack = pack; + +end: +gf100_gr_dtor_fw (&fuc); +return ret; } static int
@@ -271,7 +313,6 @@ int gk20a_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - struct gf100_gr_fuc fuc; struct gf100_gr *gr;int ret;
@@ -289,37 +330,22 @@ gk20a_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, gf100_gr_ctor_fw(gr, "gpccs_data", &gr->fuc41ad)) return -ENODEV; - ret =gf100_gr_ctor_fw (gr,"sw_nonctx" , &fuc); + ret =gk20a_gr_av_to_init (gr,"sw_nonctx" , &gr->fuc_sw_nonctx);if (ret)return ret; - gr->fuc_sw_nonctx =gk20a_gr_av_to_init (&fuc); -gf100_gr_dtor_fw (&fuc); -if (IS_ERR (gr->fuc_sw_nonctx)) -return PTR_ERR (gr->fuc_sw_nonctx); - ret =gf100_gr_ctor_fw (gr,"sw_ctx" , &fuc); + ret =gk20a_gr_aiv_to_init (gr,"sw_ctx" , &gr->fuc_sw_ctx);if (ret)return ret; - gr->fuc_sw_ctx =gk20a_gr_aiv_to_init (&fuc); -gf100_gr_dtor_fw (&fuc); -if (IS_ERR (gr->fuc_sw_ctx)) -return PTR_ERR (gr->fuc_sw_ctx); - ret =gf100_gr_ctor_fw (gr,"sw_bundle_init" , &fuc); + ret =gk20a_gr_av_to_init (gr,"sw_bundle_init" , &gr->fuc_bundle);if (ret)return ret; - gr->fuc_bundle =gk20a_gr_av_to_init (&fuc); -gf100_gr_dtor_fw (&fuc); -if (IS_ERR (gr->fuc_bundle)) -return PTR_ERR (gr->fuc_bundle); - ret =gf100_gr_ctor_fw (gr,"sw_method_init" , &fuc); + ret =gk20a_gr_av_to_method (gr,"sw_method_init" , &gr->fuc_method);if (ret)return ret; - gr->fuc_method =gk20a_gr_av_to_method (&fuc); -gf100_gr_dtor_fw (&fuc); -if (IS_ERR (gr->fuc_method)) -return PTR_ERR (gr->fuc_method); +return 0 ; }
Signature · 1 line
2.7.1
PATCH v3 5/11 gr/gk20a: share external bundles loading functions
In reply to a message not in the archiveThere functions are going to be used by other chips that rely on NVIDIA-provided firmware. Export them.
--- drm/nouveau/nvkm/engine/gr/gf100.h | 8 ++++++++ drm/nouveau/nvkm/engine/gr/gk20a.c | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.h +8 -0
@@ -203,6 +203,14 @@ void gf100_gr_icmd(struct gf100_gr *, const struct gf100_gr_pack *);void gf100_gr_mthd (struct gf100_gr *,const struct gf100_gr_pack *);int gf100_gr_init_ctxctl (struct gf100_gr *); +/* external bundles loading functions */ +int gk20a_gr_av_to_init (struct gf100_gr *,const char *, +struct gf100_gr_pack **); +int gk20a_gr_aiv_to_init (struct gf100_gr *,const char *, +struct gf100_gr_pack **); +int gk20a_gr_av_to_method (struct gf100_gr *,const char *, +struct gf100_gr_pack **); +/* register init value lists */ extern const struct gf100_gr_init gf100_gr_init_main_0[];
drm/nouveau/nvkm/engine/gr/gk20a.c +3 -3
@@ -32,7 +32,7 @@ struct gk20a_fw_avu32 data; }; -static int +int gk20a_gr_av_to_init (struct gf100_gr *gr,const char *fw_name,struct gf100_gr_pack **ppack) {
@@ -81,7 +81,7 @@ struct gk20a_fw_aivu32 data; }; -static int +int gk20a_gr_aiv_to_init (struct gf100_gr *gr,const char *fw_name,struct gf100_gr_pack **ppack) {
@@ -123,7 +123,7 @@ end:return ret; } -static int +int gk20a_gr_av_to_method (struct gf100_gr *gr,const char *fw_name,struct gf100_gr_pack **ppack) {
Signature · 1 line
2.7.1
PATCH v3 6/11 gr/gm200: load external firmware and bundles
In reply to a message not in the archiveLoad firmware and bundles in GM200's constructor. The previously called GF100 function did not care about the bundles.
--- drm/nouveau/nvkm/engine/gr/gf100.h | 5 +++-- drm/nouveau/nvkm/engine/gr/gk20a.c | 41 ++++++++++++++++---------------------- drm/nouveau/nvkm/engine/gr/gm200.c | 32 ++++++++++++++++++++++++++++- drm/nouveau/nvkm/engine/gr/gm206.c | 2 +- drm/nouveau/nvkm/engine/gr/gm20b.c | 2 +- 5 files changed, 53 insertions(+), 29 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.h +3 -2
@@ -138,8 +138,6 @@ int gf100_gr_init(struct gf100_gr *);int gk104_gr_init (struct gf100_gr *); -int gk20a_gr_new_ (const struct gf100_gr_func *,struct nvkm_device *, -int ,struct nvkm_gr **);int gk20a_gr_init (struct gf100_gr *);int gm200_gr_init (struct gf100_gr *);
@@ -211,6 +209,9 @@ int gk20a_gr_aiv_to_init(struct gf100_gr *, const char *,int gk20a_gr_av_to_method (struct gf100_gr *,const char *,struct gf100_gr_pack **); +int gm200_gr_new_ (const struct gf100_gr_func *,struct nvkm_device *,int , +struct nvkm_gr **); +/* register init value lists */ extern const struct gf100_gr_init gf100_gr_init_main_0[];
drm/nouveau/nvkm/engine/gr/gk20a.c +17 -24
57 lines not on this page · raw message
drm/nouveau/nvkm/engine/gr/gm200.c +31 -1
@@ -351,6 +351,36 @@ gm200_gr_init(struct gf100_gr *gr)return gm200_gr_init_ctxctl (gr); } +int gm200_gr_new_ (const struct gf100_gr_func *func,struct nvkm_device *device, +int index,struct nvkm_gr **pgr) +{ +struct gf100_gr *gr; +int ret; + +if (!(gr =kzalloc (sizeof (*gr),GFP_KERNEL ))) +return -ENOMEM ; + *pgr = &gr->base; + + ret =gf100_gr_ctor (func, device, index, gr); +if (ret) +return ret; + +if ((ret =gf100_gr_ctor_fw (gr,"gr/fecs_inst" , &gr->fuc409c)) || + (ret =gf100_gr_ctor_fw (gr,"gr/fecs_data" , &gr->fuc409d))) +return ret; +if ((ret =gf100_gr_ctor_fw (gr,"gr/gpccs_inst" , &gr->fuc41ac)) || + (ret =gf100_gr_ctor_fw (gr,"gr/gpccs_data" , &gr->fuc41ad))) +return ret; + +if ((ret =gk20a_gr_av_to_init (gr,"gr/sw_nonctx" , &gr->fuc_sw_nonctx)) || + (ret =gk20a_gr_aiv_to_init (gr,"gr/sw_ctx" , &gr->fuc_sw_ctx)) || + (ret =gk20a_gr_av_to_init (gr,"gr/sw_bundle_init" , &gr->fuc_bundle)) || + (ret =gk20a_gr_av_to_method (gr,"gr/sw_method_init" , &gr->fuc_method))) +return ret; + +return 0 ; +} +static const struct gf100_gr_func gm200_gr = { .init = gm200_gr_init,
@@ -369,5 +399,5 @@ gm200_gr = {int gm200_gr_new (struct nvkm_device *device,int index,struct nvkm_gr **pgr) { -return gf100_gr_new_ (&gm200_gr, device, index, pgr); +return gm200_gr_new_ (&gm200_gr, device, index, pgr); }
drm/nouveau/nvkm/engine/gr/gm206.c +1 -1
@@ -44,5 +44,5 @@ gm206_gr = {int gm206_gr_new (struct nvkm_device *device,int index,struct nvkm_gr **pgr) { -return gf100_gr_new_ (&gm206_gr, device, index, pgr); +return gm200_gr_new_ (&gm206_gr, device, index, pgr); }
drm/nouveau/nvkm/engine/gr/gm20b.c +1 -1
@@ -78,5 +78,5 @@ gm20b_gr = {int gm20b_gr_new (struct nvkm_device *device,int index,struct nvkm_gr **pgr) { -return gk20a_gr_new_ (&gm20b_gr, device, index, pgr); +return gm200_gr_new_ (&gm20b_gr, device, index, pgr); }
Signature · 1 line
2.7.1
PATCH v3 7/11 core: add support for secure boot
In reply to a message not in the archiveOn GM200 and later GPUs, firmware for some essential falcons (notably GR ones) must be authenticated by a NVIDIA-produced signature and loaded by a high-secure falcon in order to be able to access privileged registers, in a process known as Secure Boot.
Secure Boot requires building a binary blob containing the firmwares and signatures of the falcons to be loaded. This blob is then given to a high-secure falcon running a signed loader firmware that copies the blob into a write-protected region, checks that the signatures are valid, and finally loads the verified firmware into the managed falcons and switches them to privileged mode.
This patch adds infrastructure code to support this process on chips that require it.
--- drm/nouveau/include/nvkm/core/device.h | 3 + drm/nouveau/include/nvkm/subdev/secboot.h | 56 ++++++ drm/nouveau/nvkm/core/subdev.c | 1 + drm/nouveau/nvkm/engine/device/base.c | 2 + drm/nouveau/nvkm/engine/device/priv.h | 1 + drm/nouveau/nvkm/subdev/Kbuild | 1 + drm/nouveau/nvkm/subdev/secboot/Kbuild | 1 + drm/nouveau/nvkm/subdev/secboot/base.c | 296 ++++++++++++++++++++++++++++++ drm/nouveau/nvkm/subdev/secboot/priv.h | 48 +++++ 9 files changed, 409 insertions(+) create mode 100644 drm/nouveau/include/nvkm/subdev/secboot.h create mode 100644 drm/nouveau/nvkm/subdev/secboot/Kbuild create mode 100644 drm/nouveau/nvkm/subdev/secboot/base.c create mode 100644 drm/nouveau/nvkm/subdev/secboot/priv.h
drm/nouveau/include/nvkm/core/device.h +3 -0
@@ -24,6 +24,7 @@ enum nvkm_devidx {NVKM_SUBDEV_VOLT ,NVKM_SUBDEV_THERM ,NVKM_SUBDEV_CLK , +NVKM_SUBDEV_SECBOOT ,NVKM_ENGINE_DMAOBJ , NVKM_ENGINE_IFB,
@@ -119,6 +120,7 @@ struct nvkm_device {struct nvkm_therm *therm;struct nvkm_timer *timer;struct nvkm_volt *volt; +struct nvkm_secboot *secboot;struct nvkm_engine *bsp;struct nvkm_engine *ce[3 ];
@@ -184,6 +186,7 @@ struct nvkm_device_chip {int (*therm )(struct nvkm_device *,int idx,struct nvkm_therm **);int (*timer )(struct nvkm_device *,int idx,struct nvkm_timer **);int (*volt )(struct nvkm_device *,int idx,struct nvkm_volt **); +int (*secboot)(struct nvkm_device *,int idx,struct nvkm_secboot **);int (*bsp )(struct nvkm_device *,int idx,struct nvkm_engine **);int (*ce[3 ] )(struct nvkm_device *,int idx,struct nvkm_engine **);
drm/nouveau/include/nvkm/subdev/secboot.h new file +56 -0
56 lines not on this page · raw message
drm/nouveau/nvkm/core/subdev.c +1 -0
@@ -49,6 +49,7 @@ nvkm_subdev_name[NVKM_SUBDEV_NR] = { [NVKM_SUBDEV_THERM ] = "therm", [NVKM_SUBDEV_TIMER ] = "tmr", [NVKM_SUBDEV_VOLT ] = "volt", + [NVKM_SUBDEV_SECBOOT] = "secboot", [NVKM_ENGINE_BSP ] = "bsp", [NVKM_ENGINE_CE0 ] = "ce0", [NVKM_ENGINE_CE1 ] = "ce1",
drm/nouveau/nvkm/engine/device/base.c +2 -0
@@ -2123,6 +2123,7 @@ nvkm_device_subdev(struct nvkm_device *device, int index)_ (THERM , device->therm , &device->therm->subdev);_ (TIMER , device->timer , &device->timer->subdev);_ (VOLT , device->volt , &device->volt->subdev); +_ (SECBOOT , device->secboot, &device->secboot->subdev);#undef _default : engine =nvkm_device_engine (device, index);
@@ -2572,6 +2573,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,_ (NVKM_SUBDEV_THERM , therm);_ (NVKM_SUBDEV_TIMER , timer);_ (NVKM_SUBDEV_VOLT , volt); +_ (NVKM_SUBDEV_SECBOOT , secboot);_ (NVKM_ENGINE_BSP , bsp);_ (NVKM_ENGINE_CE0 , ce[0 ]);_ (NVKM_ENGINE_CE1 , ce[1 ]);
drm/nouveau/nvkm/engine/device/priv.h +1 -0
@@ -22,6 +22,7 @@#include <subdev/therm.h> #include <subdev/timer.h> #include <subdev/volt.h> +#include <subdev/secboot.h> #include <engine/bsp.h> #include <engine/ce.h>
drm/nouveau/nvkm/subdev/Kbuild +1 -0
@@ -15,6 +15,7 @@ include $(src)/nvkm/subdev/mmu/Kbuild include $(src)/nvkm/subdev/mxm/Kbuild include $(src)/nvkm/subdev/pci/Kbuild include $(src)/nvkm/subdev/pmu/Kbuild +include $(src)/nvkm/subdev/secboot/Kbuild include $(src)/nvkm/subdev/therm/Kbuild include $(src)/nvkm/subdev/timer/Kbuild include $(src)/nvkm/subdev/volt/Kbuild
drm/nouveau/nvkm/subdev/secboot/Kbuild new file +1 -0
@@ -0,0 +1 @@ +nvkm-y += nvkm/subdev/secboot/base.o
drm/nouveau/nvkm/subdev/secboot/base.c new file +296 -0
296 lines not on this page · raw message
drm/nouveau/nvkm/subdev/secboot/priv.h new file +48 -0
48 lines not on this page · raw message
Signature · 1 line
2.7.1
PATCH v3 8/11 gr/gf100: add support for securely-managed falcons
In reply to a message not in the archiveStart securely-managed falcons using secboot functions since the process for them is different from just writing CPUCTL.
--- drm/nouveau/nvkm/engine/gr/gf100.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)
drm/nouveau/nvkm/engine/gr/gf100.c +24 -4
@@ -28,6 +28,7 @@#include <core/client.h> #include <core/option.h> #include <core/firmware.h> +#include <subdev/secboot.h> #include <subdev/fb.h> #include <subdev/mc.h> #include <subdev/pmu.h>
@@ -1428,21 +1429,40 @@ gf100_gr_init_ctxctl(struct gf100_gr *gr)const struct gf100_grctx_func *grctx = gr->func->grctx;struct nvkm_subdev *subdev = &gr->base.engine.subdev;struct nvkm_device *device = subdev->device; +struct nvkm_secboot *sb = device->secboot;int i; if (gr->firmware) { /* load fuc microcode */ nvkm_mc_unk260(device->mc, 0); - gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d); - gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad); + + /* securely-managed falcons must be reset using secure boot */ + if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) + nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS); + else + gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, + &gr->fuc409d); + if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) + nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS); + else + gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, + &gr->fuc41ad); + nvkm_mc_unk260(device->mc, 1); /* start both of them running */ nvkm_wr32(device, 0x409840, 0xffffffff); nvkm_wr32(device, 0x41a10c, 0x00000000); nvkm_wr32(device, 0x40910c, 0x00000000); - nvkm_wr32(device, 0x41a100, 0x00000002); - nvkm_wr32(device, 0x409100, 0x00000002); + + if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) + nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_GPCCS); + else + nvkm_wr32(device, 0x41a100, 0x00000002); + if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) + nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_FECS); + else + nvkm_wr32(device, 0x409100, 0x00000002); if (nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800) & 0x00000001) break;
Signature · 1 line
2.7.1
PATCH v3 9/11 gr/gm200: do not load firmware for secure falcons
In reply to a message not in the archiveSecure falcons' firmware is managed by secboot. Do not load it in GR for them.
--- drm/nouveau/nvkm/engine/gr/gm200.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
drm/nouveau/nvkm/engine/gr/gm200.c +15 -6
@@ -24,6 +24,8 @@#include "gf100.h" #include "ctxgf100.h" +#include <subdev/secboot.h> +#include <nvif/class.h> /*******************************************************************************
@@ -365,12 +367,19 @@ int gm200_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device,if (ret)return ret; -if ((ret =gf100_gr_ctor_fw (gr,"gr/fecs_inst" , &gr->fuc409c)) || - (ret =gf100_gr_ctor_fw (gr,"gr/fecs_data" , &gr->fuc409d))) -return ret; -if ((ret =gf100_gr_ctor_fw (gr,"gr/gpccs_inst" , &gr->fuc41ac)) || - (ret =gf100_gr_ctor_fw (gr,"gr/gpccs_data" , &gr->fuc41ad))) -return ret; +/* Load firmwares for non-secure falcons */ +if (!nvkm_secboot_is_managed (device->secboot, +NVKM_SECBOOT_FALCON_FECS )) { +if ((ret =gf100_gr_ctor_fw (gr,"gr/fecs_inst" , &gr->fuc409c)) || + (ret =gf100_gr_ctor_fw (gr,"gr/fecs_data" , &gr->fuc409d))) +return ret; + } +if (!nvkm_secboot_is_managed (device->secboot, +NVKM_SECBOOT_FALCON_GPCCS )) { +if ((ret =gf100_gr_ctor_fw (gr,"gr/gpccs_inst" , &gr->fuc41ac)) || + (ret =gf100_gr_ctor_fw (gr,"gr/gpccs_data" , &gr->fuc41ad))) +return ret; + } if ((ret = gk20a_gr_av_to_init(gr, "gr/sw_nonctx", &gr->fuc_sw_nonctx)) || (ret = gk20a_gr_aiv_to_init(gr, "gr/sw_ctx", &gr->fuc_sw_ctx)) ||
Signature · 1 line
2.7.1
PATCH v3 10/11 secboot/gm200: add secure-boot support
In reply to a message not in the archiveAdd secure-boot for the dGPU set of GM20X chips, using the PMU as the high-secure falcon.
This work is based on Deepak Goyal's initial port of Secure Boot to Nouveau.
--- drm/nouveau/include/nvkm/subdev/secboot.h | 2 + drm/nouveau/nvkm/engine/device/base.c | 2 + drm/nouveau/nvkm/engine/gr/gm200.c | 8 +- drm/nouveau/nvkm/subdev/secboot/Kbuild | 1 + drm/nouveau/nvkm/subdev/secboot/gm200.c | 1485 +++++++++++++++++++++++++++++ drm/nouveau/nvkm/subdev/secboot/priv.h | 178 ++++ 6 files changed, 1669 insertions(+), 7 deletions(-) create mode 100644 drm/nouveau/nvkm/subdev/secboot/gm200.c
drm/nouveau/include/nvkm/subdev/secboot.h +2 -0
@@ -53,4 +53,6 @@ bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_secboot_falcon);int nvkm_secboot_reset (struct nvkm_secboot *,u32 falcon);int nvkm_secboot_start (struct nvkm_secboot *,u32 falcon); +int gm200_secboot_new (struct nvkm_device *,int ,struct nvkm_secboot **); +#endif
drm/nouveau/nvkm/engine/device/base.c +2 -0
@@ -2022,6 +2022,7 @@ nv124_chipset = { .fifo = gm200_fifo_new, .gr = gm200_gr_new, .sw = gf100_sw_new, + .secboot = gm200_secboot_new, }; static const struct nvkm_device_chip
@@ -2053,6 +2054,7 @@ nv126_chipset = { .fifo = gm200_fifo_new, .gr = gm206_gr_new, .sw = gf100_sw_new, + .secboot = gm200_secboot_new, }; static const struct nvkm_device_chip
drm/nouveau/nvkm/engine/gr/gm200.c +1 -7
@@ -231,12 +231,6 @@ gm200_gr_data[] = {* PGRAPH engine/subdev functions ******************************************************************************/ -static int -gm200_gr_init_ctxctl (struct gf100_gr *gr) -{ -return 0 ; -} -int gm200_gr_init (struct gf100_gr *gr) {
@@ -350,7 +344,7 @@ gm200_gr_init(struct gf100_gr *gr)gf100_gr_zbc_init (gr); -return gm200_gr_init_ctxctl (gr); +return gf100_gr_init_ctxctl (gr); } int gm200_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device,
drm/nouveau/nvkm/subdev/secboot/Kbuild +1 -0
@@ -1 +1,2 @@ nvkm-y += nvkm/subdev/secboot/base.o +nvkm-y += nvkm/subdev/secboot/gm200.o
drm/nouveau/nvkm/subdev/secboot/gm200.c new file +1485 -0
1,485 lines not on this page · raw message
drm/nouveau/nvkm/subdev/secboot/priv.h +178 -0
182 lines not on this page · raw message
Signature · 1 line
2.7.1
PATCH v3 11/11 secboot/gm20b: add secure boot support
In reply to a message not in the archiveAdd secure boot support for the GM20B chip found in Tegra X1. Secure boot on Tegra works slightly differently from desktop, notably in the way the WPR region is set up.
In addition, the firmware bootloaders use a slightly different header format.
--- drm/nouveau/include/nvkm/subdev/secboot.h | 1 + drm/nouveau/nvkm/engine/device/base.c | 1 + drm/nouveau/nvkm/engine/gr/gm20b.c | 9 +- drm/nouveau/nvkm/subdev/secboot/Kbuild | 1 + drm/nouveau/nvkm/subdev/secboot/gm20b.c | 233 ++++++++++++++++++++++++++++++ 5 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 drm/nouveau/nvkm/subdev/secboot/gm20b.c
drm/nouveau/include/nvkm/subdev/secboot.h +1 -0
@@ -54,5 +54,6 @@ int nvkm_secboot_reset(struct nvkm_secboot *, u32 falcon);int nvkm_secboot_start (struct nvkm_secboot *,u32 falcon);int gm200_secboot_new (struct nvkm_device *,int ,struct nvkm_secboot **); +int gm20b_secboot_new (struct nvkm_device *,int ,struct nvkm_secboot **);#endif
drm/nouveau/nvkm/engine/device/base.c +1 -0
@@ -2075,6 +2075,7 @@ nv12b_chipset = { .fifo = gm20b_fifo_new, .gr = gm20b_gr_new, .sw = gf100_sw_new, + .secboot = gm20b_secboot_new, }; static int
drm/nouveau/nvkm/engine/gr/gm20b.c +6 -3
@@ -32,12 +32,15 @@ gm20b_gr_init_gpc_mmu(struct gf100_gr *gr)struct nvkm_device *device = gr->base.engine.subdev.device;u32 val; -/* TODO this needs to be removed once secure boot works */ -if (1 ) { +/* Bypass MMU check for non-secure boot */ +if (!device->secboot) {nvkm_wr32 (device,0x100ce4 ,0xffffffff ); + +if (nvkm_rd32 (device,0x100ce4 ) !=0xffffffff ) +nvdev_warn (device, +"cannot bypass secure boot - expect failure soon!\n" ); } -/* TODO update once secure boot works */ val =nvkm_rd32 (device,0x100c80 ); val &=0xf000087f ;nvkm_wr32 (device,0x418880 , val);
drm/nouveau/nvkm/subdev/secboot/Kbuild +1 -0
@@ -1,2 +1,3 @@ nvkm-y += nvkm/subdev/secboot/base.o nvkm-y += nvkm/subdev/secboot/gm200.o +nvkm-y += nvkm/subdev/secboot/gm20b.o
drm/nouveau/nvkm/subdev/secboot/gm20b.c new file +233 -0
233 lines not on this page · raw message
Signature · 1 line
2.7.1