base.c 7.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

/*
 * Secure boot is the process by which NVIDIA-signed firmware is loaded into
 * some of the falcons of a GPU. For production devices this is the only way
 * for the firmware to access useful (but sensitive) registers.
 *
 * A Falcon microprocessor supporting advanced security modes can run in one of
 * three modes:
 *
 * - Non-secure (NS). In this mode, functionality is similar to Falcon
 *   architectures before security modes were introduced (pre-Maxwell), but
 *   capability is restricted. In particular, certain registers may be
 *   inaccessible for reads and/or writes, and physical memory access may be
 *   disabled (on certain Falcon instances). This is the only possible mode that
 *   can be used if you don't have microcode cryptographically signed by NVIDIA.
 *
 * - Heavy Secure (HS). In this mode, the microprocessor is a black box - it's
 *   not possible to read or write any Falcon internal state or Falcon registers
 *   from outside the Falcon (for example, from the host system). The only way
 *   to enable this mode is by loading microcode that has been signed by NVIDIA.
 *   (The loading process involves tagging the IMEM block as secure, writing the
 *   signature into a Falcon register, and starting execution. The hardware will
 *   validate the signature, and if valid, grant HS privileges.)
 *
 * - Light Secure (LS). In this mode, the microprocessor has more privileges
 *   than NS but fewer than HS. Some of the microprocessor state is visible to
 *   host software to ease debugging. The only way to enable this mode is by HS
 *   microcode enabling LS mode. Some privileges available to HS mode are not
 *   available here. LS mode is introduced in GM20x.
 *
 * Secure boot consists in temporarily switching a HS-capable falcon (typically
 * PMU) into HS mode in order to validate the LS firmwares of managed falcons,
 * load them, and switch managed falcons into LS mode. Once secure boot
 * completes, no falcon remains in HS mode.
 *
 * Secure boot requires a write-protected memory region (WPR) which can only be
 * written by the secure falcon. On dGPU, the driver sets up the WPR region in
 * video memory. On Tegra, it is set up by the bootloader and its location and
 * size written into memory controller registers.
 *
 * The secure boot process takes place as follows:
 *
 * 1) A LS blob is constructed that contains all the LS firmwares we want to
 *    load, along with their signatures and bootloaders.
 *
 * 2) A HS blob (also called ACR) is created that contains the signed HS
 *    firmware in charge of loading the LS firmwares into their respective
 *    falcons.
 *
 * 3) The HS blob is loaded (via its own bootloader) and executed on the
 *    HS-capable falcon. It authenticates itself, switches the secure falcon to
 *    HS mode and setup the WPR region around the LS blob (dGPU) or copies the
 *    LS blob into the WPR region (Tegra).
 *
 * 4) The LS blob is now secure from all external tampering. The HS falcon
 *    checks the signatures of the LS firmwares and, if valid, switches the
 *    managed falcons to LS mode and makes them ready to run the LS firmware.
 *
 * 5) The managed falcons remain in LS mode and can be started.
 *
 */

84
#include "priv.h"
85
#include "acr.h"
86 87

#include <subdev/mc.h>
88
#include <subdev/timer.h>
89
#include <subdev/pmu.h>
90
#include <engine/sec2.h>
91

92 93
const char *
nvkm_secboot_falcon_name[] = {
94 95 96 97
	[NVKM_SECBOOT_FALCON_PMU] = "PMU",
	[NVKM_SECBOOT_FALCON_RESERVED] = "<reserved>",
	[NVKM_SECBOOT_FALCON_FECS] = "FECS",
	[NVKM_SECBOOT_FALCON_GPCCS] = "GPCCS",
98
	[NVKM_SECBOOT_FALCON_SEC2] = "SEC2",
99 100 101 102 103 104
	[NVKM_SECBOOT_FALCON_END] = "<invalid>",
};
/**
 * nvkm_secboot_reset() - reset specified falcon
 */
int
105
nvkm_secboot_reset(struct nvkm_secboot *sb, unsigned long falcon_mask)
106 107
{
	/* Unmanaged falcon? */
108
	if ((falcon_mask | sb->acr->managed_falcons) != sb->acr->managed_falcons) {
109 110 111 112
		nvkm_error(&sb->subdev, "cannot reset unmanaged falcon!\n");
		return -EINVAL;
	}

113
	return sb->acr->func->reset(sb->acr, sb, falcon_mask);
114 115 116 117 118 119
}

/**
 * nvkm_secboot_is_managed() - check whether a given falcon is securely-managed
 */
bool
120
nvkm_secboot_is_managed(struct nvkm_secboot *sb, enum nvkm_secboot_falcon fid)
121
{
122
	if (!sb)
123 124
		return false;

125
	return sb->acr->managed_falcons & BIT(fid);
126 127 128 129 130 131 132 133
}

static int
nvkm_secboot_oneinit(struct nvkm_subdev *subdev)
{
	struct nvkm_secboot *sb = nvkm_secboot(subdev);
	int ret = 0;

134
	switch (sb->acr->boot_falcon) {
135
	case NVKM_SECBOOT_FALCON_PMU:
136
		sb->halt_falcon = sb->boot_falcon = subdev->device->pmu->falcon;
137
		break;
138 139 140 141
	case NVKM_SECBOOT_FALCON_SEC2:
		/* we must keep SEC2 alive forever since ACR will run on it */
		nvkm_engine_ref(&subdev->device->sec2->engine);
		sb->boot_falcon = subdev->device->sec2->falcon;
142
		sb->halt_falcon = subdev->device->pmu->falcon;
143
		break;
144 145
	default:
		nvkm_error(subdev, "Unmanaged boot falcon %s!\n",
146
			                nvkm_secboot_falcon_name[sb->acr->boot_falcon]);
147 148
		return -EINVAL;
	}
149
	nvkm_debug(subdev, "using %s falcon for ACR\n", sb->boot_falcon->name);
150

151
	/* Call chip-specific init function */
152 153
	if (sb->func->oneinit)
		ret = sb->func->oneinit(sb);
154 155 156 157 158 159
	if (ret) {
		nvkm_error(subdev, "Secure Boot initialization failed: %d\n",
			   ret);
		return ret;
	}

160
	return 0;
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
}

static int
nvkm_secboot_fini(struct nvkm_subdev *subdev, bool suspend)
{
	struct nvkm_secboot *sb = nvkm_secboot(subdev);
	int ret = 0;

	if (sb->func->fini)
		ret = sb->func->fini(sb, suspend);

	return ret;
}

static void *
nvkm_secboot_dtor(struct nvkm_subdev *subdev)
{
	struct nvkm_secboot *sb = nvkm_secboot(subdev);
	void *ret = NULL;

	if (sb->func->dtor)
		ret = sb->func->dtor(sb);

	return ret;
}

static const struct nvkm_subdev_func
nvkm_secboot = {
	.oneinit = nvkm_secboot_oneinit,
	.fini = nvkm_secboot_fini,
	.dtor = nvkm_secboot_dtor,
};

int
195
nvkm_secboot_ctor(const struct nvkm_secboot_func *func, struct nvkm_acr *acr,
196 197 198 199 200
		  struct nvkm_device *device, int index,
		  struct nvkm_secboot *sb)
{
	unsigned long fid;

201
	nvkm_subdev_ctor(&nvkm_secboot, device, index, &sb->subdev);
202
	sb->func = func;
203 204
	sb->acr = acr;
	acr->subdev = &sb->subdev;
205 206

	nvkm_debug(&sb->subdev, "securely managed falcons:\n");
207
	for_each_set_bit(fid, &sb->acr->managed_falcons,
208
			 NVKM_SECBOOT_FALCON_END)
209 210
		nvkm_debug(&sb->subdev, "- %s\n",
			   nvkm_secboot_falcon_name[fid]);
211 212 213

	return 0;
}
新手
引导
客服 返回
顶部