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