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{
  39        struct gm200_secboot *gsb = gm200_secboot(sb);
  40        struct nvkm_subdev *subdev = &gsb->base.subdev;
  41        struct nvkm_falcon *falcon = gsb->base.boot_falcon;
  42        struct nvkm_vma vma;
  43        int ret;
  44
  45        ret = nvkm_falcon_get(falcon, subdev);
  46        if (ret)
  47                return ret;
  48
  49        /* Map the HS firmware so the HS bootloader can see it */
  50        ret = nvkm_gpuobj_map(blob, gsb->vm, NV_MEM_ACCESS_RW, &vma);
  51        if (ret) {
  52                nvkm_falcon_put(falcon, subdev);
  53                return ret;
  54        }
  55
  56        /* Reset and set the falcon up */
  57        ret = nvkm_falcon_reset(falcon);
  58        if (ret)
  59                goto end;
  60        nvkm_falcon_bind_context(falcon, gsb->inst);
  61
  62        /* Load the HS bootloader into the falcon's IMEM/DMEM */
  63        ret = sb->acr->func->load(sb->acr, &gsb->base, blob, vma.offset);
  64        if (ret)
  65                goto end;
  66
  67        /* Disable interrupts as we will poll for the HALT bit */
  68        nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, false);
  69
  70        /* Set default error value in mailbox register */
  71        nvkm_falcon_wr32(falcon, 0x040, 0xdeada5a5);
  72
  73        /* Start the HS bootloader */
  74        nvkm_falcon_set_start_addr(falcon, sb->acr->start_address);
  75        nvkm_falcon_start(falcon);
  76        ret = nvkm_falcon_wait_for_halt(falcon, 100);
  77        if (ret)
  78                goto end;
  79
  80        /* If mailbox register contains an error code, then ACR has failed */
  81        ret = nvkm_falcon_rd32(falcon, 0x040);
  82        if (ret) {
  83                nvkm_error(subdev, "ACR boot failed, ret 0x%08x", ret);
  84                ret = -EINVAL;
  85                goto end;
  86        }
  87
  88end:
  89        /* Reenable interrupts */
  90        nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, true);
  91
  92        /* We don't need the ACR firmware anymore */
  93        nvkm_gpuobj_unmap(&vma);
  94        nvkm_falcon_put(falcon, subdev);
  95
  96        return ret;
  97}
  98
  99int
 100gm200_secboot_oneinit(struct nvkm_secboot *sb)
 101{
 102        struct gm200_secboot *gsb = gm200_secboot(sb);
 103        struct nvkm_device *device = sb->subdev.device;
 104        struct nvkm_vm *vm;
 105        const u64 vm_area_len = 600 * 1024;
 106        int ret;
 107
 108        /* Allocate instance block and VM */
 109        ret = nvkm_gpuobj_new(device, 0x1000, 0, true, NULL, &gsb->inst);
 110        if (ret)
 111                return ret;
 112
 113        ret = nvkm_gpuobj_new(device, 0x8000, 0, true, NULL, &gsb->pgd);
 114        if (ret)
 115                return ret;
 116
 117        ret = nvkm_vm_new(device, 0, vm_area_len, 0, NULL, &vm);
 118        if (ret)
 119                return ret;
 120
 121        atomic_inc(&vm->engref[NVKM_SUBDEV_PMU]);
 122
 123        ret = nvkm_vm_ref(vm, &gsb->vm, gsb->pgd);
 124        nvkm_vm_ref(NULL, &vm, NULL);
 125        if (ret)
 126                return ret;
 127
 128        nvkm_kmap(gsb->inst);
 129        nvkm_wo32(gsb->inst, 0x200, lower_32_bits(gsb->pgd->addr));
 130        nvkm_wo32(gsb->inst, 0x204, upper_32_bits(gsb->pgd->addr));
 131        nvkm_wo32(gsb->inst, 0x208, lower_32_bits(vm_area_len - 1));
 132        nvkm_wo32(gsb->inst, 0x20c, upper_32_bits(vm_area_len - 1));
 133        nvkm_done(gsb->inst);
 134
 135        if (sb->acr->func->oneinit) {
 136                ret = sb->acr->func->oneinit(sb->acr, sb);
 137                if (ret)
 138                        return ret;
 139        }
 140
 141        return 0;
 142}
 143
 144int
 145gm200_secboot_fini(struct nvkm_secboot *sb, bool suspend)
 146{
 147        int ret = 0;
 148
 149        if (sb->acr->func->fini)
 150                ret = sb->acr->func->fini(sb->acr, sb, suspend);
 151
 152        return ret;
 153}
 154
 155void *
 156gm200_secboot_dtor(struct nvkm_secboot *sb)
 157{
 158        struct gm200_secboot *gsb = gm200_secboot(sb);
 159
 160        sb->acr->func->dtor(sb->acr);
 161
 162        nvkm_vm_ref(NULL, &gsb->vm, gsb->pgd);
 163        nvkm_gpuobj_del(&gsb->pgd);
 164        nvkm_gpuobj_del(&gsb->inst);
 165
 166        return gsb;
 167}
 168
 169
 170static const struct nvkm_secboot_func
 171gm200_secboot = {
 172        .dtor = gm200_secboot_dtor,
 173        .oneinit = gm200_secboot_oneinit,
 174        .fini = gm200_secboot_fini,
 175        .run_blob = gm200_secboot_run_blob,
 176};
 177
 178int
 179gm200_secboot_new(struct nvkm_device *device, int index,
 180                  struct nvkm_secboot **psb)
 181{
 182        int ret;
 183        struct gm200_secboot *gsb;
 184        struct nvkm_acr *acr;
 185
 186        acr = acr_r361_new(BIT(NVKM_SECBOOT_FALCON_FECS) |
 187                           BIT(NVKM_SECBOOT_FALCON_GPCCS));
 188        if (IS_ERR(acr))
 189                return PTR_ERR(acr);
 190
 191        gsb = kzalloc(sizeof(*gsb), GFP_KERNEL);
 192        if (!gsb) {
 193                psb = NULL;
 194                return -ENOMEM;
 195        }
 196        *psb = &gsb->base;
 197
 198        ret = nvkm_secboot_ctor(&gm200_secboot, acr, device, index, &gsb->base);
 199        if (ret)
 200                return ret;
 201
 202        return 0;
 203}
 204
 205
 206MODULE_FIRMWARE("nvidia/gm200/acr/bl.bin");
 207MODULE_FIRMWARE("nvidia/gm200/acr/ucode_load.bin");
 208MODULE_FIRMWARE("nvidia/gm200/acr/ucode_unload.bin");
 209MODULE_FIRMWARE("nvidia/gm200/gr/fecs_bl.bin");
 210MODULE_FIRMWARE("nvidia/gm200/gr/fecs_inst.bin");
 211MODULE_FIRMWARE("nvidia/gm200/gr/fecs_data.bin");
 212MODULE_FIRMWARE("nvidia/gm200/gr/fecs_sig.bin");
 213MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_bl.bin");
 214MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_inst.bin");
 215MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_data.bin");
 216MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_sig.bin");
 217MODULE_FIRMWARE("nvidia/gm200/gr/sw_ctx.bin");
 218MODULE_FIRMWARE("nvidia/gm200/gr/sw_nonctx.bin");
 219MODULE_FIRMWARE("nvidia/gm200/gr/sw_bundle_init.bin");
 220MODULE_FIRMWARE("nvidia/gm200/gr/sw_method_init.bin");
 221
 222MODULE_FIRMWARE("nvidia/gm204/acr/bl.bin");
 223MODULE_FIRMWARE("nvidia/gm204/acr/ucode_load.bin");
 224MODULE_FIRMWARE("nvidia/gm204/acr/ucode_unload.bin");
 225MODULE_FIRMWARE("nvidia/gm204/gr/fecs_bl.bin");
 226MODULE_FIRMWARE("nvidia/gm204/gr/fecs_inst.bin");
 227MODULE_FIRMWARE("nvidia/gm204/gr/fecs_data.bin");
 228MODULE_FIRMWARE("nvidia/gm204/gr/fecs_sig.bin");
 229MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_bl.bin");
 230MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_inst.bin");
 231MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_data.bin");
 232MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_sig.bin");
 233MODULE_FIRMWARE("nvidia/gm204/gr/sw_ctx.bin");
 234MODULE_FIRMWARE("nvidia/gm204/gr/sw_nonctx.bin");
 235MODULE_FIRMWARE("nvidia/gm204/gr/sw_bundle_init.bin");
 236MODULE_FIRMWARE("nvidia/gm204/gr/sw_method_init.bin");
 237
 238MODULE_FIRMWARE("nvidia/gm206/acr/bl.bin");
 239MODULE_FIRMWARE("nvidia/gm206/acr/ucode_load.bin");
 240MODULE_FIRMWARE("nvidia/gm206/acr/ucode_unload.bin");
 241MODULE_FIRMWARE("nvidia/gm206/gr/fecs_bl.bin");
 242MODULE_FIRMWARE("nvidia/gm206/gr/fecs_inst.bin");
 243MODULE_FIRMWARE("nvidia/gm206/gr/fecs_data.bin");
 244MODULE_FIRMWARE("nvidia/gm206/gr/fecs_sig.bin");
 245MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_bl.bin");
 246MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_inst.bin");
 247MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_data.bin");
 248MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_sig.bin");
 249MODULE_FIRMWARE("nvidia/gm206/gr/sw_ctx.bin");
 250MODULE_FIRMWARE("nvidia/gm206/gr/sw_nonctx.bin");
 251MODULE_FIRMWARE("nvidia/gm206/gr/sw_bundle_init.bin");
 252MODULE_FIRMWARE("nvidia/gm206/gr/sw_method_init.bin");
 253
 254MODULE_FIRMWARE("nvidia/gp100/acr/bl.bin");
 255MODULE_FIRMWARE("nvidia/gp100/acr/ucode_load.bin");
 256MODULE_FIRMWARE("nvidia/gp100/acr/ucode_unload.bin");
 257MODULE_FIRMWARE("nvidia/gp100/gr/fecs_bl.bin");
 258MODULE_FIRMWARE("nvidia/gp100/gr/fecs_inst.bin");
 259MODULE_FIRMWARE("nvidia/gp100/gr/fecs_data.bin");
 260MODULE_FIRMWARE("nvidia/gp100/gr/fecs_sig.bin");
 261MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_bl.bin");
 262MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_inst.bin");
 263MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_data.bin");
 264MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_sig.bin");
 265MODULE_FIRMWARE("nvidia/gp100/gr/sw_ctx.bin");
 266MODULE_FIRMWARE("nvidia/gp100/gr/sw_nonctx.bin");
 267MODULE_FIRMWARE("nvidia/gp100/gr/sw_bundle_init.bin");
 268MODULE_FIRMWARE("nvidia/gp100/gr/sw_method_init.bin");
 269