linux/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20 * DEALINGS IN THE SOFTWARE.
  21 */
  22
  23
  24#include "acr.h"
  25#include "gm200.h"
  26
  27#include <core/gpuobj.h>
  28#include <subdev/fb.h>
  29#include <engine/falcon.h>
  30#include <subdev/mc.h>
  31
  32/**
  33 * gm200_secboot_run_blob() - run the given high-secure blob
  34 *
  35 */
  36int
  37gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob,
  38                       struct nvkm_falcon *falcon)
  39{
  40        struct gm200_secboot *gsb = gm200_secboot(sb);
  41        struct nvkm_subdev *subdev = &gsb->base.subdev;
  42        struct nvkm_vma *vma = NULL;
  43        u32 start_address;
  44        int ret;
  45
  46        ret = nvkm_falcon_get(falcon, subdev);
  47        if (ret)
  48                return ret;
  49
  50        /* Map the HS firmware so the HS bootloader can see it */
  51        ret = nvkm_vmm_get(gsb->vmm, 12, blob->size, &vma);
  52        if (ret) {
  53                nvkm_falcon_put(falcon, subdev);
  54                return ret;
  55        }
  56
  57        ret = nvkm_memory_map(blob, 0, gsb->vmm, vma, NULL, 0);
  58        if (ret)
  59                goto end;
  60
  61        /* Reset and set the falcon up */
  62        ret = nvkm_falcon_reset(falcon);
  63        if (ret)
  64                goto end;
  65        nvkm_falcon_bind_context(falcon, gsb->inst);
  66
  67        /* Load the HS bootloader into the falcon's IMEM/DMEM */
  68        ret = sb->acr->func->load(sb->acr, falcon, blob, vma->addr);
  69        if (ret < 0)
  70                goto end;
  71
  72        start_address = ret;
  73
  74        /* Disable interrupts as we will poll for the HALT bit */
  75        nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, false);
  76
  77        /* Set default error value in mailbox register */
  78        nvkm_falcon_wr32(falcon, 0x040, 0xdeada5a5);
  79
  80        /* Start the HS bootloader */
  81        nvkm_falcon_set_start_addr(falcon, start_address);
  82        nvkm_falcon_start(falcon);
  83        ret = nvkm_falcon_wait_for_halt(falcon, 100);
  84        if (ret)
  85                goto end;
  86
  87        /*
  88         * The mailbox register contains the (positive) error code - return this
  89         * to the caller
  90         */
  91        ret = nvkm_falcon_rd32(falcon, 0x040);
  92
  93end:
  94        /* Reenable interrupts */
  95        nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, true);
  96
  97        /* We don't need the ACR firmware anymore */
  98        nvkm_vmm_put(gsb->vmm, &vma);
  99        nvkm_falcon_put(falcon, subdev);
 100
 101        return ret;
 102}
 103
 104int
 105gm200_secboot_oneinit(struct nvkm_secboot *sb)
 106{
 107        struct gm200_secboot *gsb = gm200_secboot(sb);
 108        struct nvkm_device *device = sb->subdev.device;
 109        int ret;
 110
 111        /* Allocate instance block and VM */
 112        ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, true,
 113                              &gsb->inst);
 114        if (ret)
 115                return ret;
 116
 117        ret = nvkm_vmm_new(device, 0, 600 * 1024, NULL, 0, NULL, "acr",
 118                           &gsb->vmm);
 119        if (ret)
 120                return ret;
 121
 122        atomic_inc(&gsb->vmm->engref[NVKM_SUBDEV_PMU]);
 123        gsb->vmm->debug = gsb->base.subdev.debug;
 124
 125        ret = nvkm_vmm_join(gsb->vmm, gsb->inst);
 126        if (ret)
 127                return ret;
 128
 129        if (sb->acr->func->oneinit) {
 130                ret = sb->acr->func->oneinit(sb->acr, sb);
 131                if (ret)
 132                        return ret;
 133        }
 134
 135        return 0;
 136}
 137
 138int
 139gm200_secboot_fini(struct nvkm_secboot *sb, bool suspend)
 140{
 141        int ret = 0;
 142
 143        if (sb->acr->func->fini)
 144                ret = sb->acr->func->fini(sb->acr, sb, suspend);
 145
 146        return ret;
 147}
 148
 149void *
 150gm200_secboot_dtor(struct nvkm_secboot *sb)
 151{
 152        struct gm200_secboot *gsb = gm200_secboot(sb);
 153
 154        sb->acr->func->dtor(sb->acr);
 155
 156        nvkm_vmm_part(gsb->vmm, gsb->inst);
 157        nvkm_vmm_unref(&gsb->vmm);
 158        nvkm_memory_unref(&gsb->inst);
 159
 160        return gsb;
 161}
 162
 163
 164static const struct nvkm_secboot_func
 165gm200_secboot = {
 166        .dtor = gm200_secboot_dtor,
 167        .oneinit = gm200_secboot_oneinit,
 168        .fini = gm200_secboot_fini,
 169        .run_blob = gm200_secboot_run_blob,
 170};
 171
 172int
 173gm200_secboot_new(struct nvkm_device *device, int index,
 174                  struct nvkm_secboot **psb)
 175{
 176        int ret;
 177        struct gm200_secboot *gsb;
 178        struct nvkm_acr *acr;
 179
 180        acr = acr_r361_new(BIT(NVKM_SECBOOT_FALCON_FECS) |
 181                           BIT(NVKM_SECBOOT_FALCON_GPCCS));
 182        if (IS_ERR(acr))
 183                return PTR_ERR(acr);
 184
 185        gsb = kzalloc(sizeof(*gsb), GFP_KERNEL);
 186        if (!gsb) {
 187                psb = NULL;
 188                return -ENOMEM;
 189        }
 190        *psb = &gsb->base;
 191
 192        ret = nvkm_secboot_ctor(&gm200_secboot, acr, device, index, &gsb->base);
 193        if (ret)
 194                return ret;
 195
 196        return 0;
 197}
 198
 199
 200MODULE_FIRMWARE("nvidia/gm200/acr/bl.bin");
 201MODULE_FIRMWARE("nvidia/gm200/acr/ucode_load.bin");
 202MODULE_FIRMWARE("nvidia/gm200/acr/ucode_unload.bin");
 203MODULE_FIRMWARE("nvidia/gm200/gr/fecs_bl.bin");
 204MODULE_FIRMWARE("nvidia/gm200/gr/fecs_inst.bin");
 205MODULE_FIRMWARE("nvidia/gm200/gr/fecs_data.bin");
 206MODULE_FIRMWARE("nvidia/gm200/gr/fecs_sig.bin");
 207MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_bl.bin");
 208MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_inst.bin");
 209MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_data.bin");
 210MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_sig.bin");
 211MODULE_FIRMWARE("nvidia/gm200/gr/sw_ctx.bin");
 212MODULE_FIRMWARE("nvidia/gm200/gr/sw_nonctx.bin");
 213MODULE_FIRMWARE("nvidia/gm200/gr/sw_bundle_init.bin");
 214MODULE_FIRMWARE("nvidia/gm200/gr/sw_method_init.bin");
 215
 216MODULE_FIRMWARE("nvidia/gm204/acr/bl.bin");
 217MODULE_FIRMWARE("nvidia/gm204/acr/ucode_load.bin");
 218MODULE_FIRMWARE("nvidia/gm204/acr/ucode_unload.bin");
 219MODULE_FIRMWARE("nvidia/gm204/gr/fecs_bl.bin");
 220MODULE_FIRMWARE("nvidia/gm204/gr/fecs_inst.bin");
 221MODULE_FIRMWARE("nvidia/gm204/gr/fecs_data.bin");
 222MODULE_FIRMWARE("nvidia/gm204/gr/fecs_sig.bin");
 223MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_bl.bin");
 224MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_inst.bin");
 225MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_data.bin");
 226MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_sig.bin");
 227MODULE_FIRMWARE("nvidia/gm204/gr/sw_ctx.bin");
 228MODULE_FIRMWARE("nvidia/gm204/gr/sw_nonctx.bin");
 229MODULE_FIRMWARE("nvidia/gm204/gr/sw_bundle_init.bin");
 230MODULE_FIRMWARE("nvidia/gm204/gr/sw_method_init.bin");
 231
 232MODULE_FIRMWARE("nvidia/gm206/acr/bl.bin");
 233MODULE_FIRMWARE("nvidia/gm206/acr/ucode_load.bin");
 234MODULE_FIRMWARE("nvidia/gm206/acr/ucode_unload.bin");
 235MODULE_FIRMWARE("nvidia/gm206/gr/fecs_bl.bin");
 236MODULE_FIRMWARE("nvidia/gm206/gr/fecs_inst.bin");
 237MODULE_FIRMWARE("nvidia/gm206/gr/fecs_data.bin");
 238MODULE_FIRMWARE("nvidia/gm206/gr/fecs_sig.bin");
 239MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_bl.bin");
 240MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_inst.bin");
 241MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_data.bin");
 242MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_sig.bin");
 243MODULE_FIRMWARE("nvidia/gm206/gr/sw_ctx.bin");
 244MODULE_FIRMWARE("nvidia/gm206/gr/sw_nonctx.bin");
 245MODULE_FIRMWARE("nvidia/gm206/gr/sw_bundle_init.bin");
 246MODULE_FIRMWARE("nvidia/gm206/gr/sw_method_init.bin");
 247
 248MODULE_FIRMWARE("nvidia/gp100/acr/bl.bin");
 249MODULE_FIRMWARE("nvidia/gp100/acr/ucode_load.bin");
 250MODULE_FIRMWARE("nvidia/gp100/acr/ucode_unload.bin");
 251MODULE_FIRMWARE("nvidia/gp100/gr/fecs_bl.bin");
 252MODULE_FIRMWARE("nvidia/gp100/gr/fecs_inst.bin");
 253MODULE_FIRMWARE("nvidia/gp100/gr/fecs_data.bin");
 254MODULE_FIRMWARE("nvidia/gp100/gr/fecs_sig.bin");
 255MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_bl.bin");
 256MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_inst.bin");
 257MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_data.bin");
 258MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_sig.bin");
 259MODULE_FIRMWARE("nvidia/gp100/gr/sw_ctx.bin");
 260MODULE_FIRMWARE("nvidia/gp100/gr/sw_nonctx.bin");
 261MODULE_FIRMWARE("nvidia/gp100/gr/sw_bundle_init.bin");
 262MODULE_FIRMWARE("nvidia/gp100/gr/sw_method_init.bin");
 263